Install
$ agentstack add skill-korchard333-claude-power-platform-community-web-resources ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Skill: Dataverse Web Resources
When to Use
Trigger when building JavaScript form scripts, HTML web resources, CSS styling, ribbon/command bar customization, or custom navigation for Model-Driven Apps.
Web Resource Types
| Type | Code | Extension | Use Case | |---|---|---|---| | HTML | 1 | .html | Custom pages, dashboards, dialog content | | CSS | 2 | .css | Custom styling for forms/views | | JavaScript | 3 | .js | Form event handlers, ribbon commands, business logic | | XML | 4 | .xml | Data files, configuration | | PNG | 5 | .png | Icons, images | | JPG | 6 | .jpg | Photos, images | | GIF | 7 | .gif | Animated icons | | SVG | 11 | .svg | Vector icons | | RESX | 12 | .resx | Localized strings |
⚠️ REQUIRED: Load Sub-Files Before Implementation
SKILL.md is a summary only — it is NOT sufficient for implementation.
The detailed content (complete payloads, XML templates, working examples, edge-case handling) lives in sub-files in the same directory as this SKILL.md. Before writing any code, you MUST use read_file on the sub-files relevant to your task:
- [Form Scripts](form-scripts.md) -- Form event handlers (OnLoad, OnSave, OnChange), formContext patterns, field/control/tab manipulation, save event handling, async OnSave
- [Ribbon Commands](ribbon-commands.md) -- Command bar customization, RibbonDiffXml, enable/display rules, command handlers, modern commanding (Power Fx)
- [Xrm Client API](xrm-client-api.md) -- Xrm.WebApi (CRUD, custom actions, FetchXML), Xrm.Navigation, Xrm.Utility, Xrm.Device, global context, async patterns, error handling
- [HTML Dashboards](html-dashboards.md) -- HTML web resource patterns, parent Xrm context access, postMessage communication, responsive sizing, embedding in dashboards and forms
- [formContext API Reference](form-context-api.md) -- formContext.data, formContext.ui, attributes (getValue/setValue/addOnChange/setRequiredLevel), controls (setDisabled/setVisible/addCustomFilter for lookups), tabs, sections, form events, save modes
Project Structure (Recommended)
webresources/
src/
scripts/
contact/
contactForm.ts # Contact form event handlers
contactRibbon.ts # Contact ribbon commands
account/
accountForm.ts
accountRibbon.ts
shared/
common.ts # Shared utilities
notifications.ts # Toast/notification helpers
webapi.ts # Web API wrapper
types/
xrm.d.ts # Xrm type definitions
html/
customDashboard.html
css/
formStyles.css
dist/ # Compiled output
contoso_/ # Publisher prefix folder
scripts/
html/
package.json
tsconfig.json
webpack.config.js # Bundle per form/feature
deploy.ps1 # Upload script
TypeScript Setup
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM"],
"strict": true,
"noImplicitAny": true,
"outDir": "./dist",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"esModuleInterop": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
Xrm Type Definitions
npm install --save-dev @types/xrm
Deployment via Web API
Upload Web Resource
POST /api/data/v9.2/webresourceset
Content-Type: application/json
MSCRM.SolutionUniqueName: YourSolution
{
"name": "contoso_/scripts/contactForm.js",
"displayname": "Contact Form Script",
"description": "Event handlers for the Contact form",
"webresourcetype": 3,
"content": ""
}
Update Existing Web Resource
PATCH /api/data/v9.2/webresourceset(guid-of-webresource)
Content-Type: application/json
{
"content": ""
}
Publish After Upload
POST /api/data/v9.2/PublishXml
Content-Type: application/json
{
"ParameterXml": "{guid}"
}
Upload Script (Bash)
#!/bin/bash
FILE=$1
WR_NAME=$2
CONTENT=$(base64 < "$FILE")
# Check if web resource exists
EXISTING=$(curl -s "${BASE_URL}/api/data/v9.2/webresourceset?\$filter=name eq '${WR_NAME}'&\$select=webresourceid" \
-H "Authorization: Bearer ${TOKEN}" -H "Accept: application/json")
WR_ID=$(echo "$EXISTING" | jq -r '.value[0].webresourceid // empty')
if [ -n "$WR_ID" ]; then
curl -s -X PATCH "${BASE_URL}/api/data/v9.2/webresourceset(${WR_ID})" \
-H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
-d "{\"content\":\"${CONTENT}\"}"
echo "Updated: ${WR_NAME}"
else
curl -s -X POST "${BASE_URL}/api/data/v9.2/webresourceset" \
-H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
-d "{\"name\":\"${WR_NAME}\",\"displayname\":\"${WR_NAME}\",\"webresourcetype\":3,\"content\":\"${CONTENT}\"}"
echo "Created: ${WR_NAME}"
fi
curl -s -X POST "${BASE_URL}/api/data/v9.2/PublishAllXml" -H "Authorization: Bearer ${TOKEN}"
echo "Published"
Naming Conventions
| Object | Convention | Example | |---|---|---| | JS web resource | {prefix}_/scripts/{entity}{Purpose}.js | contoso_/scripts/contactForm.js | | HTML web resource | {prefix}_/html/{purpose}.html | contoso_/html/projectDashboard.html | | CSS web resource | {prefix}_/css/{purpose}.css | contoso_/css/formStyles.css | | Image web resource | {prefix}_/images/{name}.{ext} | contoso_/images/approve16.png | | TypeScript namespace | {Publisher}.{Entity} | Contoso.Contact | | Event handler function | on{Event} | onLoad, onSave, onEmailChange | | Ribbon command function | {action}{Entity} | approveRecord, exportToPdf |
Anti-Patterns
- Using
Xrm.Page(deprecated) instead of execution context +getFormContext() - Not passing execution context as first parameter to event handlers
- jQuery or other DOM manipulation libraries -- jQuery was removed from Model-Driven Apps (October 2023)
- Direct DOM manipulation of form elements (unsupported, breaks on updates)
- Hardcoding GUIDs in scripts
- Synchronous XMLHttpRequest calls (blocks UI thread)
- Not handling errors in async Web API calls
- Using
setTimeoutfor timing-dependent logic instead of proper event handlers - Publishing all customizations when only specific web resources changed
- Not using TypeScript for type safety on Xrm API calls
Related Skills
model-driven-apps-- Web resources are used in Model-Driven App forms and ribbonsdataverse-web-api-- Web API calls from JavaScript web resources
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: korchard333
- Source: korchard333/claude-power-platform-community
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.