npx skills add ...
npx skills add forcedotcom/sf-skills --skill generating-ui-bundle-metadata
MUST activate when the project contains a uiBundles/*/src/ directory and scaffolding a new UI bundle or app, or when editing ui-bundle.json, .uibundle-meta.xml, or CSP trusted site files. Use this skill when scaffolding with sf template generate ui-bundle, configuring ui-bundle.json (routing, headers, outputDir), or registering CSP Trusted Sites. Activate when the task involves files matching *.uibundle-meta.xml, ui-bundle.json, or cspTrustedSites/*.cspTrustedSite-meta.xml.
npx skills add forcedotcom/sf-skills --skill generating-ui-bundle-metadata
Use sf template generate ui-bundle to create new apps — not create-react-app, Vite, or other generic scaffolds.
Always pass --template reactbasic to scaffold a React-based bundle.
UI bundle name (-n): Alphanumerical only — no spaces, hyphens, underscores, or special characters.
Example:
After generation:
<title>, placeholder textbuilding-ui-bundle-frontend skill)<target> in its meta XML will not be visible in the org. Use generating-ui-bundle-custom-app for internal (App Launcher) apps or generating-ui-bundle-site for external (Experience Site) apps.Always install dependencies before running any scripts in the UI bundle directory.
A UIBundle bundle lives under uiBundles/<AppName>/ and must contain:
<AppName>.uibundle-meta.xml — filename must exactly match the folder namedist/) with at least one fileRequired fields: masterLabel, version (max 20 chars), isActive (boolean).
Optional: description (max 255 chars), target.
The <target> element specifies where the UI bundle is hosted:
| Value | Use Case | Companion Metadata |
|---|---|---|
Experience | External-facing site via Digital Experience | Network, CustomSite, DigitalExperienceConfig, DigitalExperienceBundle |
CustomApplication | Internal app via Lightning App Launcher | CustomApplication (applications/*.app-meta.xml) |
A <target> is required for the app to be accessible in a Salesforce org. A UI bundle deployed without a target will not appear anywhere — no App Launcher entry, no Experience Site URL. Always pair the bundle with one of:
generating-ui-bundle-site (for Experience target)generating-ui-bundle-custom-app (for CustomApplication target)Example with Experience target:
Example with CustomApplication target:
Optional file. Allowed top-level keys: outputDir, routing, headers.
Constraints:
{}, arrays, or primitives)Path safety (applies to outputDir and routing.fallback): Reject backslashes, leading / or \, .. segments, null/control characters, globs (*, ?, **), and %. All resolved paths must stay within the bundle.
Non-empty string referencing a subdirectory (not . or ./). Directory must exist and contain at least one file.
If present, must be a non-empty object. Allowed keys: rewrites, redirects, fallback, trailingSlash, fileBasedRouting.
"always", "never", or "auto"{ route?, rewrite } objects — e.g., { "route": "/app/:path*", "rewrite": "/index.html" }{ route?, redirect, statusCode? } objects — statusCode must be 301, 302, 307, or 308Non-empty array of { source, headers: [{ key, value }] } objects.
Example:
Never suggest: {} as root, empty "routing": {}, empty arrays, [{}], "outputDir": ".", "outputDir": "./".
Salesforce enforces Content Security Policy headers. Any external domain not registered as a CSP Trusted Site will be blocked (images won't load, API calls fail, fonts missing).
Whenever the app references a new external domain: CDN images, external fonts, third-party APIs, map tiles, iframes, external stylesheets.
force-app/main/default/cspTrustedSites/| Resource Type | Directive Field |
|---|---|
| Images | isApplicableToImgSrc |
| API calls (fetch, XHR) | isApplicableToConnectSrc |
| Fonts | isApplicableToFontSrc |
| Stylesheets | isApplicableToStyleSrc |
| Video / audio | isApplicableToMediaSrc |
| Iframes | isApplicableToFrameSrc |
Always also set isApplicableToConnectSrc to true for preflight/redirect handling.
implementation/csp-metadata-format.md for the .cspTrustedSite-meta.xml format. Place in force-app/main/default/cspTrustedSites/.`