@salesforce/webapp-template-feature-react-agentforce-conversation-client-experimental 1.112.4 → 1.112.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/.a4drules/webapp-data.md +5 -5
  2. package/dist/.a4drules/webapp-ui.md +2 -2
  3. package/dist/AGENT.md +6 -10
  4. package/dist/CHANGELOG.md +16 -0
  5. package/dist/force-app/main/default/webapplications/feature-react-agentforce-conversation-client/.forceignore +15 -0
  6. package/dist/force-app/main/default/webapplications/feature-react-agentforce-conversation-client/package.json +3 -3
  7. package/dist/package-lock.json +2 -2
  8. package/dist/package.json +1 -1
  9. package/dist/{.a4drules/skills/using-salesforce-data → scripts}/graphql-search.sh +4 -4
  10. package/package.json +3 -4
  11. package/dist/.a4drules/skills/building-data-visualization/SKILL.md +0 -72
  12. package/dist/.a4drules/skills/building-data-visualization/implementation/bar-line-chart.md +0 -316
  13. package/dist/.a4drules/skills/building-data-visualization/implementation/dashboard-layout.md +0 -189
  14. package/dist/.a4drules/skills/building-data-visualization/implementation/donut-chart.md +0 -181
  15. package/dist/.a4drules/skills/building-data-visualization/implementation/stat-card.md +0 -150
  16. package/dist/.a4drules/skills/building-react-components/SKILL.md +0 -96
  17. package/dist/.a4drules/skills/building-react-components/implementation/component.md +0 -78
  18. package/dist/.a4drules/skills/building-react-components/implementation/header-footer.md +0 -132
  19. package/dist/.a4drules/skills/building-react-components/implementation/page.md +0 -93
  20. package/dist/.a4drules/skills/configuring-csp-trusted-sites/SKILL.md +0 -90
  21. package/dist/.a4drules/skills/configuring-csp-trusted-sites/implementation/metadata-format.md +0 -281
  22. package/dist/.a4drules/skills/configuring-webapp-metadata/SKILL.md +0 -158
  23. package/dist/.a4drules/skills/creating-webapp/SKILL.md +0 -140
  24. package/dist/.a4drules/skills/deploying-to-salesforce/SKILL.md +0 -226
  25. package/dist/.a4drules/skills/implementing-file-upload/SKILL.md +0 -396
  26. package/dist/.a4drules/skills/installing-webapp-features/SKILL.md +0 -210
  27. package/dist/.a4drules/skills/managing-agentforce-conversation-client/SKILL.md +0 -186
  28. package/dist/.a4drules/skills/managing-agentforce-conversation-client/references/constraints.md +0 -134
  29. package/dist/.a4drules/skills/managing-agentforce-conversation-client/references/examples.md +0 -132
  30. package/dist/.a4drules/skills/managing-agentforce-conversation-client/references/style-tokens.md +0 -101
  31. package/dist/.a4drules/skills/managing-agentforce-conversation-client/references/troubleshooting.md +0 -57
  32. package/dist/.a4drules/skills/using-salesforce-data/SKILL.md +0 -363
  33. package/skills/managing-agentforce-conversation-client/SKILL.md +0 -186
  34. package/skills/managing-agentforce-conversation-client/references/constraints.md +0 -134
  35. package/skills/managing-agentforce-conversation-client/references/examples.md +0 -132
  36. package/skills/managing-agentforce-conversation-client/references/style-tokens.md +0 -101
  37. package/skills/managing-agentforce-conversation-client/references/troubleshooting.md +0 -57
@@ -1,132 +0,0 @@
1
- # Implementation — Header / Footer
2
-
3
- ### Rules
4
-
5
- 1. **Edit `appLayout.tsx` only** — header and footer are layout-level concerns. Never add them to individual page files.
6
- 2. **Never modify `routes.tsx` or `app.tsx`** — the router setup must remain intact.
7
- 3. **Create component files in `src/components/layout/`** — the designated location for layout-level components.
8
- 4. **Use the full-height flex column pattern** — wrap layout in `min-h-screen flex flex-col` so footer stays at bottom.
9
- 5. **Use shadcn and Tailwind** — compose from `@/components/ui`; style with Tailwind utility classes and design tokens.
10
- 6. **Use path aliases** — import with `@/components/layout/...` and `@/components/ui`; no deep relative paths.
11
- 7. **Preserve existing content** — if `appLayout.tsx` already has a `<NavigationMenu />` or other shell elements, keep them in place.
12
-
13
- ### Step 1 — Create the header component (if requested)
14
-
15
- Create `src/components/layout/AppHeader.tsx`:
16
-
17
- ```tsx
18
- import { cn } from "@/lib/utils";
19
-
20
- interface AppHeaderProps {
21
- className?: string;
22
- }
23
-
24
- export function AppHeader({ className }: AppHeaderProps) {
25
- return (
26
- <header
27
- className={cn(
28
- "w-full border-b bg-background px-4 sm:px-6 lg:px-8 py-4",
29
- className,
30
- )}
31
- >
32
- <div className="max-w-7xl mx-auto flex items-center justify-between">
33
- <span className="text-lg font-semibold text-foreground">My App</span>
34
- </div>
35
- </header>
36
- );
37
- }
38
- ```
39
-
40
- ### Step 2 — Create the footer component (if requested)
41
-
42
- Create `src/components/layout/AppFooter.tsx`:
43
-
44
- ```tsx
45
- import { cn } from "@/lib/utils";
46
-
47
- interface AppFooterProps {
48
- className?: string;
49
- }
50
-
51
- export function AppFooter({ className }: AppFooterProps) {
52
- return (
53
- <footer
54
- className={cn(
55
- "w-full border-t bg-background px-4 sm:px-6 lg:px-8 py-4",
56
- className,
57
- )}
58
- >
59
- <div className="max-w-7xl mx-auto text-center text-sm text-muted-foreground">
60
- &copy; {new Date().getFullYear()} My App. All rights reserved.
61
- </div>
62
- </footer>
63
- );
64
- }
65
- ```
66
-
67
- ### Step 3 — Edit `appLayout.tsx`
68
-
69
- Open `src/appLayout.tsx` — this is the **only file to modify** for layout-level additions. Wrap existing content in a flex column and add header above and footer below `<Outlet />`:
70
-
71
- ```tsx
72
- import { Outlet } from "react-router";
73
- import { AppHeader } from "@/components/layout/AppHeader";
74
- import { AppFooter } from "@/components/layout/AppFooter";
75
- // Keep all existing imports unchanged
76
-
77
- export default function AppLayout() {
78
- return (
79
- <div className="min-h-screen flex flex-col bg-background">
80
- <AppHeader />
81
- {/* Keep any existing NavigationMenu or other shell elements here */}
82
- <main className="flex-1">
83
- <Outlet />
84
- </main>
85
- <AppFooter />
86
- </div>
87
- );
88
- }
89
- ```
90
-
91
- ### File Locations — Header / Footer
92
-
93
- | Component | File | Export |
94
- | ------------ | ------------------------------------- | ------------------------------ |
95
- | Header | `src/components/layout/AppHeader.tsx` | Named export |
96
- | Footer | `src/components/layout/AppFooter.tsx` | Named export |
97
- | Layout shell | `src/appLayout.tsx` | Default export (edit in place) |
98
-
99
- ### Why `appLayout.tsx` — Not Pages or Routes
100
-
101
- `AppLayout` is the single shell rendered at the root route. Every page is a child rendered via `<Outlet />`. Placing the header and footer here ensures they appear on every page without touching individual pages or the route registry.
102
-
103
- ```
104
- AppLayout (appLayout.tsx)
105
- ├── AppHeader ← renders on every page
106
- ├── NavigationMenu ← keep if already present
107
- ├── <Outlet /> ← active page renders here
108
- └── AppFooter ← renders on every page
109
- ```
110
-
111
- ### Useful Patterns — Header / Footer
112
-
113
- - **Sticky header:** add `sticky top-0 z-50` to the `<header>` element
114
- - **Separator:** use `<Separator />` from `@/components/ui` instead of `border-b`/`border-t` if a visible divider is preferred
115
- - **Nav links in header:** use `<Button variant="ghost" asChild>` wrapping a React Router `<Link>`
116
- - **Icons:** `lucide-react`; add `aria-hidden="true"` on decorative icons
117
- - **Design tokens:** `bg-background`, `text-foreground`, `text-muted-foreground`, `border`, `bg-primary`
118
-
119
- ### Mobile hamburger / Menu icon — Must be functional
120
-
121
- If the header includes a hamburger or `Menu` icon for mobile:
122
-
123
- - **Do not** add a Menu/hamburger icon that does nothing. It must toggle a visible mobile menu.
124
- - **Required:** (1) State: `const [isOpen, setIsOpen] = useState(false)`. (2) Button: `onClick={() => setIsOpen(!isOpen)}`, `aria-label="Toggle menu"`. (3) Conditional panel: `{isOpen && ( <div>...nav links...</div> )}` with responsive visibility (e.g. `md:hidden`). (4) Close on navigate: each link in the panel should `onClick={() => setIsOpen(false)}`.
125
- - Implement in `appLayout.tsx` (or the component that owns the header). Use the `Menu` icon from `lucide-react`.
126
-
127
- ### Confirm — Header / Footer
128
-
129
- - Header and footer appear on every page (navigate to at least two routes)
130
- - Imports use path aliases (`@/components/layout/...`)
131
- - No inline `style={{}}` — Tailwind only
132
- - `src/routes.tsx` and `src/app.tsx` are unchanged
@@ -1,93 +0,0 @@
1
- # Implementation — Page
2
-
3
- ### Rules
4
-
5
- 1. **Edit the component that owns the UI, never output raw HTML** — When editing the home page or any page content, modify the actual `.tsx` file that renders the target. If the target is inside a child component (e.g. `<GlobalSearchInput />` in `Home.tsx`), edit the child's file (e.g. `GlobalSearchInput.tsx`), not the parent. Do not wrap the component with extra elements in the parent; go into the component and change its JSX. Do not paste or generate raw HTML.
6
- 2. **`routes.tsx` is the only route registry** — never add routes in `app.tsx` or inside page files.
7
- 3. **All pages are children of the AppLayout route** — do not create top-level routes that bypass the layout shell.
8
- 4. **Default export per page** — each page file has exactly one default-export component.
9
- 5. **Path aliases in all imports** — use `@/pages/...`, `@/components/...`; no deep relative paths.
10
- 6. **No inline styles** — Tailwind utility classes and design tokens only.
11
- 7. **Catch-all last** — `path: '*'` (NotFound) must always remain the last child in the layout route.
12
- 8. **Never modify `appLayout.tsx`** when adding a page — layout changes are a separate concern.
13
-
14
- ### Step 1 — Create the page file
15
-
16
- Create `src/pages/MyPage.tsx` with a **default export** and the standard page container:
17
-
18
- ```tsx
19
- export default function MyPage() {
20
- return (
21
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
22
- <h1 className="text-3xl font-bold text-foreground">My Page</h1>
23
- <p className="mt-4 text-muted-foreground">Page content goes here.</p>
24
- </div>
25
- );
26
- }
27
- ```
28
-
29
- Use shadcn components from `@/components/ui` for UI elements. All styling via Tailwind — no inline `style={{}}`.
30
-
31
- ### Step 2 — Register the route in `routes.tsx`
32
-
33
- Open `src/routes.tsx`. Import the page and add it inside the layout route's `children` array:
34
-
35
- ```tsx
36
- import MyPage from "@/pages/MyPage";
37
-
38
- // Inside the layout route's children array (before the catch-all):
39
- {
40
- path: "my-page",
41
- element: <MyPage />,
42
- handle: { showInNavigation: true, label: "My Page" },
43
- },
44
- ```
45
-
46
- - `path` is a **relative segment** (e.g., `"contacts"`), not an absolute path.
47
- - Include `handle: { showInNavigation: true, label: "Label" }` only if the page should appear in the navigation menu.
48
- - The catch-all `path: '*'` must stay **last**.
49
-
50
- ### Step 3 — Apply an auth guard (if needed)
51
-
52
- | Access type | Guard | Behavior |
53
- | ---------------------------------- | ----------------------- | --------------------------------------- |
54
- | Public | None | Direct child of layout |
55
- | Authenticated only | `<PrivateRoute>` | Redirects to login if not authenticated |
56
- | Unauthenticated only (e.g., login) | `<AuthenticationRoute>` | Redirects away if already authenticated |
57
-
58
- Example — private page:
59
-
60
- ```tsx
61
- import { PrivateRoute } from "@/components/auth/private-route";
62
-
63
- {
64
- path: "settings",
65
- element: <PrivateRoute><SettingsPage /></PrivateRoute>,
66
- handle: { showInNavigation: true, label: "Settings" },
67
- },
68
- ```
69
-
70
- Use `ROUTES.*` constants from `@/utils/authenticationConfig` for auth-related paths — do not hardcode `/login`, `/profile`, etc.
71
-
72
- ### File Conventions — Page
73
-
74
- | Concern | Location |
75
- | ----------------- | ------------------------------------------------------ |
76
- | Page component | `src/pages/<PageName>.tsx` (default export) |
77
- | Route definition | `src/routes.tsx` only |
78
- | Layout shell | `src/appLayout.tsx` — do not modify for page additions |
79
- | Auth config paths | `ROUTES.*` from `@/utils/authenticationConfig` |
80
-
81
- ### State and Data
82
-
83
- - **Local state:** `useState`, `useReducer`, `useRef` inside the page component
84
- - **Shared or complex state:** extract to `src/hooks/` with a `use` prefix (e.g., `useContacts`)
85
- - **Data fetching:** prefer GraphQL (`executeGraphQL`) or REST utilities in `src/api/`; place shared data logic in `src/hooks/`
86
- - **Auth context:** `useAuth()` from `@/context/AuthContext` when current user is needed — only valid under `AuthProvider`
87
-
88
- ### Confirm — Page
89
-
90
- - The page renders inside the app shell (header/nav visible)
91
- - If `showInNavigation: true`, the link appears in the navigation menu
92
- - No TypeScript errors; no broken imports; no missing exports
93
- - Imports use path aliases (`@/`, not deep relative paths)
@@ -1,90 +0,0 @@
1
- ---
2
- name: configuring-csp-trusted-sites
3
- description: Creates Salesforce CSP Trusted Site metadata when adding external domains. Use when the user adds an external API, CDN, image host, font provider, map tile server, or any third-party URL that the web application needs to load resources from — or when a browser console shows a CSP violation error.
4
- ---
5
-
6
- # CSP Trusted Sites
7
-
8
- ## When to Use
9
-
10
- Use this skill whenever the application references a new external domain that is not already registered as a CSP Trusted Site. This includes:
11
-
12
- - Adding images from a new CDN (Unsplash, Pexels, Cloudinary, etc.)
13
- - Loading fonts from an external provider (Google Fonts, Adobe Fonts)
14
- - Calling a third-party API (Open-Meteo, Nominatim, Mapbox, etc.)
15
- - Loading map tiles from a tile server (OpenStreetMap, Mapbox)
16
- - Embedding iframes from external services (YouTube, Vimeo)
17
- - Loading external stylesheets or scripts
18
-
19
- Salesforce enforces Content Security Policy (CSP) headers on all web applications. Any external domain not registered as a CSP Trusted Site will be blocked by the browser, causing images to not load, API calls to fail, or fonts to be missing.
20
-
21
- **Reference:** [Salesforce CspTrustedSite Object Reference](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_csptrustedsite.htm)
22
-
23
- ---
24
-
25
- ## Step 1 — Identify external domains
26
-
27
- Scan the code for any URLs pointing to external domains. Common patterns:
28
-
29
- - `fetch("https://api.example.com/...")` — API calls
30
- - `<img src="https://images.example.com/..." />` — images
31
- - `<link href="https://fonts.example.com/..." />` — stylesheets
32
- - `url="https://tiles.example.com/{z}/{x}/{y}.png"` — map tiles
33
- - `@import url("https://cdn.example.com/...")` — CSS imports
34
-
35
- Extract the **origin** (scheme + host) from each URL. For example:
36
- - `https://api.open-meteo.com/v1/forecast?lat=...` → `https://api.open-meteo.com`
37
- - `https://images.unsplash.com/photo-123?w=800` → `https://images.unsplash.com`
38
-
39
- ---
40
-
41
- ## Step 2 — Check existing CSP Trusted Sites
42
-
43
- Before creating a new file, check if the domain already has a CSP Trusted Site:
44
-
45
- ```bash
46
- ls force-app/main/default/cspTrustedSites/
47
- ```
48
-
49
- If the domain is already registered, no action is needed.
50
-
51
- ---
52
-
53
- ## Step 3 — Determine the CSP directive(s)
54
-
55
- Map the resource type to the correct CSP `isApplicableTo*Src` fields. Read `implementation/metadata-format.md` for the full reference.
56
-
57
- Quick reference:
58
-
59
- | Resource type | CSP directive field(s) to set `true` |
60
- |--------------|--------------------------------------|
61
- | Images (img, background-image) | `isApplicableToImgSrc` |
62
- | API calls (fetch, XMLHttpRequest) | `isApplicableToConnectSrc` |
63
- | Fonts (.woff, .woff2, .ttf) | `isApplicableToFontSrc` |
64
- | Stylesheets (CSS) | `isApplicableToStyleSrc` |
65
- | Video / audio | `isApplicableToMediaSrc` |
66
- | Iframes | `isApplicableToFrameSrc` |
67
-
68
- **Always also set `isApplicableToConnectSrc` to `true`** — most resources also require connect-src for preflight/redirect handling.
69
-
70
- ---
71
-
72
- ## Step 4 — Create the metadata file
73
-
74
- Read `implementation/metadata-format.md` and follow the instructions to create the `.cspTrustedSite-meta.xml` file.
75
-
76
- ---
77
-
78
- ## Step 5 — Verify
79
-
80
- 1. Confirm the file is valid XML and matches the expected schema.
81
- 2. Confirm the file is placed in `force-app/main/default/cspTrustedSites/`.
82
- 3. Confirm only the necessary `isApplicableTo*Src` fields are set to `true`.
83
- 4. Run from the web app directory:
84
-
85
- ```bash
86
- cd force-app/main/default/webapplications/<appName> && npm run lint && npm run build
87
- ```
88
-
89
- - **Lint:** MUST result in 0 errors.
90
- - **Build:** MUST succeed.
@@ -1,281 +0,0 @@
1
- # CSP Trusted Site Metadata — Implementation Guide
2
-
3
- ## File location
4
-
5
- ```
6
- force-app/main/default/cspTrustedSites/{Name}.cspTrustedSite-meta.xml
7
- ```
8
-
9
- The `cspTrustedSites/` directory must be a direct child of `force-app/main/default/`. Create it if it does not exist.
10
-
11
- ---
12
-
13
- ## File naming convention
14
-
15
- The file name must match the `<fullName>` value inside the XML, with `.cspTrustedSite-meta.xml` appended.
16
-
17
- | Domain | fullName | File name |
18
- |--------|----------|-----------|
19
- | `https://images.unsplash.com` | `Unsplash_Images` | `Unsplash_Images.cspTrustedSite-meta.xml` |
20
- | `https://api.open-meteo.com` | `Open_Meteo_API` | `Open_Meteo_API.cspTrustedSite-meta.xml` |
21
- | `https://tile.openstreetmap.org` | `OpenStreetMap_Tiles` | `OpenStreetMap_Tiles.cspTrustedSite-meta.xml` |
22
-
23
- **Naming rules:**
24
- - Use PascalCase with underscores separating words (e.g. `Google_Fonts_Static`)
25
- - Name should describe the provider and resource type (e.g. `Pexels_Videos`, not just `Pexels`)
26
- - Must be unique across the org
27
- - Maximum 80 characters
28
-
29
- ---
30
-
31
- ## XML template
32
-
33
- ```xml
34
- <?xml version="1.0" encoding="UTF-8" ?>
35
- <CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
36
- <fullName>{UNIQUE_NAME}</fullName>
37
- <description>{DESCRIPTION}</description>
38
- <endpointUrl>{HTTPS_ORIGIN}</endpointUrl>
39
- <isActive>true</isActive>
40
- <context>All</context>
41
- <isApplicableToConnectSrc>{true|false}</isApplicableToConnectSrc>
42
- <isApplicableToFontSrc>{true|false}</isApplicableToFontSrc>
43
- <isApplicableToFrameSrc>{true|false}</isApplicableToFrameSrc>
44
- <isApplicableToImgSrc>{true|false}</isApplicableToImgSrc>
45
- <isApplicableToMediaSrc>{true|false}</isApplicableToMediaSrc>
46
- <isApplicableToStyleSrc>{true|false}</isApplicableToStyleSrc>
47
- </CspTrustedSite>
48
- ```
49
-
50
- ---
51
-
52
- ## Field reference
53
-
54
- | Field | Required | Description |
55
- |-------|----------|-------------|
56
- | `fullName` | Yes | Unique API name. Must match the file name (before `.cspTrustedSite-meta.xml`). |
57
- | `description` | Yes | Human-readable purpose. Start with "Allow access to..." |
58
- | `endpointUrl` | Yes | The external origin (scheme + host). Must start with `https://`. No trailing slash. No path. |
59
- | `isActive` | Yes | Always `true` for new entries. Set `false` to disable without deleting. |
60
- | `context` | Yes | `All` (applies to all contexts). Other values: `LEX` (Lightning Experience only), `Communities` (Experience Cloud only), `VisualForce`. Use `All` unless there is a specific reason to restrict. |
61
- | `isApplicableToConnectSrc` | Yes | `true` if the domain is called via `fetch()`, `XMLHttpRequest`, or WebSocket. |
62
- | `isApplicableToFontSrc` | Yes | `true` if the domain serves font files (`.woff`, `.woff2`, `.ttf`, `.otf`). |
63
- | `isApplicableToFrameSrc` | Yes | `true` if the domain is loaded in an `<iframe>` or `<object>`. |
64
- | `isApplicableToImgSrc` | Yes | `true` if the domain serves images (`<img>`, CSS `background-image`, `<svg>`). |
65
- | `isApplicableToMediaSrc` | Yes | `true` if the domain serves audio or video (`<audio>`, `<video>`). |
66
- | `isApplicableToStyleSrc` | Yes | `true` if the domain serves CSS stylesheets (`<link rel="stylesheet">`). |
67
-
68
- **Reference:** [CspTrustedSite — Salesforce Object Reference](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_csptrustedsite.htm)
69
-
70
- ---
71
-
72
- ## CSP directive mapping
73
-
74
- | CSP header directive | Metadata field | What it allows |
75
- |---------------------|----------------|----------------|
76
- | `connect-src` | `isApplicableToConnectSrc` | `fetch()`, `XMLHttpRequest`, WebSocket, `EventSource` |
77
- | `font-src` | `isApplicableToFontSrc` | `@font-face` sources |
78
- | `frame-src` | `isApplicableToFrameSrc` | `<iframe>`, `<frame>`, `<object>`, `<embed>` |
79
- | `img-src` | `isApplicableToImgSrc` | `<img>`, `background-image`, `favicon`, `<picture>` |
80
- | `media-src` | `isApplicableToMediaSrc` | `<audio>`, `<video>`, `<source>`, `<track>` |
81
- | `style-src` | `isApplicableToStyleSrc` | `<link rel="stylesheet">`, `@import` in CSS |
82
-
83
- ---
84
-
85
- ## Common external domains and their directives
86
-
87
- Use this table as a quick reference when adding new domains:
88
-
89
- | Domain | connect-src | font-src | frame-src | img-src | media-src | style-src |
90
- |--------|:-----------:|:--------:|:---------:|:-------:|:---------:|:---------:|
91
- | `https://images.unsplash.com` | true | false | false | true | false | false |
92
- | `https://images.pexels.com` | true | false | false | true | false | false |
93
- | `https://videos.pexels.com` | true | false | false | false | true | false |
94
- | `https://fonts.googleapis.com` | true | false | false | false | false | true |
95
- | `https://fonts.gstatic.com` | true | true | false | false | false | false |
96
- | `https://avatars.githubusercontent.com` | true | false | false | true | false | false |
97
- | `https://api.open-meteo.com` | true | false | false | false | false | false |
98
- | `https://nominatim.openstreetmap.org` | true | false | false | false | false | false |
99
- | `https://tile.openstreetmap.org` | true | false | false | true | false | false |
100
- | `https://api.mapbox.com` | true | false | false | true | false | false |
101
- | `https://cdn.jsdelivr.net` | true | false | false | false | false | true |
102
- | `https://www.youtube.com` | false | false | true | true | false | false |
103
- | `https://player.vimeo.com` | false | false | true | false | false | false |
104
- | `https://res.cloudinary.com` | true | false | false | true | false | false |
105
-
106
- ---
107
-
108
- ## Complete examples
109
-
110
- ### Image CDN (Unsplash)
111
-
112
- ```xml
113
- <?xml version="1.0" encoding="UTF-8" ?>
114
- <CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
115
- <fullName>Unsplash_Images</fullName>
116
- <description>Allow access to Unsplash image content for static app media</description>
117
- <endpointUrl>https://images.unsplash.com</endpointUrl>
118
- <isActive>true</isActive>
119
- <context>All</context>
120
- <isApplicableToConnectSrc>true</isApplicableToConnectSrc>
121
- <isApplicableToFontSrc>false</isApplicableToFontSrc>
122
- <isApplicableToFrameSrc>false</isApplicableToFrameSrc>
123
- <isApplicableToImgSrc>true</isApplicableToImgSrc>
124
- <isApplicableToMediaSrc>false</isApplicableToMediaSrc>
125
- <isApplicableToStyleSrc>false</isApplicableToStyleSrc>
126
- </CspTrustedSite>
127
- ```
128
-
129
- ### REST API (Open-Meteo weather)
130
-
131
- ```xml
132
- <?xml version="1.0" encoding="UTF-8" ?>
133
- <CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
134
- <fullName>Open_Meteo_API</fullName>
135
- <description>Allow access to Open-Meteo weather forecast API</description>
136
- <endpointUrl>https://api.open-meteo.com</endpointUrl>
137
- <isActive>true</isActive>
138
- <context>All</context>
139
- <isApplicableToConnectSrc>true</isApplicableToConnectSrc>
140
- <isApplicableToFontSrc>false</isApplicableToFontSrc>
141
- <isApplicableToFrameSrc>false</isApplicableToFrameSrc>
142
- <isApplicableToImgSrc>false</isApplicableToImgSrc>
143
- <isApplicableToMediaSrc>false</isApplicableToMediaSrc>
144
- <isApplicableToStyleSrc>false</isApplicableToStyleSrc>
145
- </CspTrustedSite>
146
- ```
147
-
148
- ### Font provider (Google Fonts — requires two entries)
149
-
150
- Google Fonts needs two CSP entries because CSS is served from `fonts.googleapis.com` and font files from `fonts.gstatic.com`:
151
-
152
- **Entry 1: Stylesheets**
153
- ```xml
154
- <?xml version="1.0" encoding="UTF-8" ?>
155
- <CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
156
- <fullName>Google_Fonts</fullName>
157
- <description>Allow access to Google Fonts stylesheets for custom typography</description>
158
- <endpointUrl>https://fonts.googleapis.com</endpointUrl>
159
- <isActive>true</isActive>
160
- <context>All</context>
161
- <isApplicableToConnectSrc>true</isApplicableToConnectSrc>
162
- <isApplicableToFontSrc>false</isApplicableToFontSrc>
163
- <isApplicableToFrameSrc>false</isApplicableToFrameSrc>
164
- <isApplicableToImgSrc>false</isApplicableToImgSrc>
165
- <isApplicableToMediaSrc>false</isApplicableToMediaSrc>
166
- <isApplicableToStyleSrc>true</isApplicableToStyleSrc>
167
- </CspTrustedSite>
168
- ```
169
-
170
- **Entry 2: Font files**
171
- ```xml
172
- <?xml version="1.0" encoding="UTF-8" ?>
173
- <CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
174
- <fullName>Google_Fonts_Static</fullName>
175
- <description>Allow access to Google Fonts static files for font loading</description>
176
- <endpointUrl>https://fonts.gstatic.com</endpointUrl>
177
- <isActive>true</isActive>
178
- <context>All</context>
179
- <isApplicableToConnectSrc>true</isApplicableToConnectSrc>
180
- <isApplicableToFontSrc>true</isApplicableToFontSrc>
181
- <isApplicableToFrameSrc>false</isApplicableToFrameSrc>
182
- <isApplicableToImgSrc>false</isApplicableToImgSrc>
183
- <isApplicableToMediaSrc>false</isApplicableToMediaSrc>
184
- <isApplicableToStyleSrc>false</isApplicableToStyleSrc>
185
- </CspTrustedSite>
186
- ```
187
-
188
- ### Map tiles (OpenStreetMap)
189
-
190
- ```xml
191
- <?xml version="1.0" encoding="UTF-8" ?>
192
- <CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
193
- <fullName>OpenStreetMap_Tiles</fullName>
194
- <description>Allow access to OpenStreetMap tile images for map rendering</description>
195
- <endpointUrl>https://tile.openstreetmap.org</endpointUrl>
196
- <isActive>true</isActive>
197
- <context>All</context>
198
- <isApplicableToConnectSrc>true</isApplicableToConnectSrc>
199
- <isApplicableToFontSrc>false</isApplicableToFontSrc>
200
- <isApplicableToFrameSrc>false</isApplicableToFrameSrc>
201
- <isApplicableToImgSrc>true</isApplicableToImgSrc>
202
- <isApplicableToMediaSrc>false</isApplicableToMediaSrc>
203
- <isApplicableToStyleSrc>false</isApplicableToStyleSrc>
204
- </CspTrustedSite>
205
- ```
206
-
207
- ### Geocoding API (Nominatim)
208
-
209
- ```xml
210
- <?xml version="1.0" encoding="UTF-8" ?>
211
- <CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
212
- <fullName>OpenStreetMap_Nominatim</fullName>
213
- <description>Allow access to OpenStreetMap Nominatim geocoding API</description>
214
- <endpointUrl>https://nominatim.openstreetmap.org</endpointUrl>
215
- <isActive>true</isActive>
216
- <context>All</context>
217
- <isApplicableToConnectSrc>true</isApplicableToConnectSrc>
218
- <isApplicableToFontSrc>false</isApplicableToFontSrc>
219
- <isApplicableToFrameSrc>false</isApplicableToFrameSrc>
220
- <isApplicableToImgSrc>false</isApplicableToImgSrc>
221
- <isApplicableToMediaSrc>false</isApplicableToMediaSrc>
222
- <isApplicableToStyleSrc>false</isApplicableToStyleSrc>
223
- </CspTrustedSite>
224
- ```
225
-
226
- ---
227
-
228
- ## Endpoint URL rules
229
-
230
- | Rule | Correct | Incorrect |
231
- |------|---------|-----------|
232
- | Must be HTTPS | `https://api.example.com` | `http://api.example.com` |
233
- | No trailing slash | `https://api.example.com` | `https://api.example.com/` |
234
- | No path | `https://api.example.com` | `https://api.example.com/v1/forecast` |
235
- | No port (unless non-standard) | `https://api.example.com` | `https://api.example.com:443` |
236
- | No wildcards | `https://api.example.com` | `https://*.example.com` |
237
-
238
- Each subdomain needs its own entry. For example, `fonts.googleapis.com` and `fonts.gstatic.com` are separate entries.
239
-
240
- ---
241
-
242
- ## When a service requires multiple domains
243
-
244
- Some services split resources across multiple subdomains. Create one CSP Trusted Site per domain:
245
-
246
- | Service | Domains needed |
247
- |---------|---------------|
248
- | Google Fonts | `fonts.googleapis.com` (CSS) + `fonts.gstatic.com` (font files) |
249
- | Mapbox | `api.mapbox.com` (tiles/API) + `events.mapbox.com` (telemetry) |
250
- | YouTube embed | `www.youtube.com` (iframe) + `i.ytimg.com` (thumbnails) |
251
- | Cloudflare CDN | `cdnjs.cloudflare.com` (scripts/CSS) |
252
-
253
- ---
254
-
255
- ## Troubleshooting CSP violations
256
-
257
- If the browser console shows a CSP error like:
258
-
259
- ```
260
- Refused to load the image 'https://example.com/image.png' because it violates
261
- the following Content Security Policy directive: "img-src 'self' ..."
262
- ```
263
-
264
- 1. Extract the **blocked origin** from the URL (e.g. `https://example.com`).
265
- 2. Identify the **directive** from the error message (e.g. `img-src` → `isApplicableToImgSrc`).
266
- 3. Check if a CSP Trusted Site already exists for that origin.
267
- 4. If not, create one using this skill.
268
- 5. Deploy the metadata and refresh the page.
269
-
270
- ---
271
-
272
- ## Common mistakes
273
-
274
- | Mistake | Fix |
275
- |---------|-----|
276
- | Including a path in `endpointUrl` | Use only the origin: `https://api.example.com` |
277
- | Adding trailing slash | Remove it: `https://api.example.com` not `https://api.example.com/` |
278
- | Using HTTP instead of HTTPS | Salesforce requires HTTPS. If the service only supports HTTP, it cannot be added. |
279
- | Forgetting `isApplicableToConnectSrc` | Most resources also need connect-src for redirects/preflight. Set to `true` by default. |
280
- | One entry for multiple subdomains | Each subdomain needs its own file (e.g. `api.example.com` and `cdn.example.com` are separate) |
281
- | File name doesn't match `fullName` | They must be identical (excluding the `.cspTrustedSite-meta.xml` extension) |