@salesforce/webapp-template-app-react-sample-b2e-experimental 1.82.0 → 1.84.0

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 (51) hide show
  1. package/dist/.a4drules/skills/webapp-csp-trusted-sites/SKILL.md +90 -0
  2. package/dist/.a4drules/skills/webapp-csp-trusted-sites/implementation/metadata-format.md +281 -0
  3. package/dist/.a4drules/skills/{webapp-add-react-component → webapp-react-add-component}/SKILL.md +1 -1
  4. package/dist/.a4drules/skills/webapp-react-data-visualization/SKILL.md +72 -0
  5. package/dist/.a4drules/skills/webapp-react-data-visualization/implementation/dashboard-layout.md +189 -0
  6. package/dist/.a4drules/skills/webapp-react-data-visualization/implementation/donut-chart.md +181 -0
  7. package/dist/.a4drules/skills/webapp-react-data-visualization/implementation/stat-card.md +150 -0
  8. package/dist/.a4drules/skills/webapp-react-interactive-map/SKILL.md +92 -0
  9. package/dist/.a4drules/skills/webapp-react-interactive-map/implementation/geocoding.md +245 -0
  10. package/dist/.a4drules/skills/webapp-react-interactive-map/implementation/leaflet-map.md +279 -0
  11. package/dist/.a4drules/skills/webapp-react-weather-widget/SKILL.md +65 -0
  12. package/dist/.a4drules/skills/webapp-react-weather-widget/implementation/weather-hook.md +258 -0
  13. package/dist/.a4drules/skills/webapp-react-weather-widget/implementation/weather-ui.md +216 -0
  14. package/dist/.a4drules/skills/webapp-ui-ux/SKILL.md +268 -0
  15. package/dist/.a4drules/skills/webapp-ui-ux/data/charts.csv +26 -0
  16. package/dist/.a4drules/skills/webapp-ui-ux/data/colors.csv +97 -0
  17. package/dist/.a4drules/skills/webapp-ui-ux/data/icons.csv +101 -0
  18. package/dist/.a4drules/skills/webapp-ui-ux/data/landing.csv +31 -0
  19. package/dist/.a4drules/skills/webapp-ui-ux/data/products.csv +97 -0
  20. package/dist/.a4drules/skills/webapp-ui-ux/data/react-performance.csv +45 -0
  21. package/dist/.a4drules/skills/webapp-ui-ux/data/stacks/html-tailwind.csv +56 -0
  22. package/dist/.a4drules/skills/webapp-ui-ux/data/stacks/react.csv +54 -0
  23. package/dist/.a4drules/skills/webapp-ui-ux/data/stacks/shadcn.csv +61 -0
  24. package/dist/.a4drules/skills/webapp-ui-ux/data/styles.csv +68 -0
  25. package/dist/.a4drules/skills/webapp-ui-ux/data/typography.csv +58 -0
  26. package/dist/.a4drules/skills/webapp-ui-ux/data/ui-reasoning.csv +101 -0
  27. package/dist/.a4drules/skills/webapp-ui-ux/data/ux-guidelines.csv +100 -0
  28. package/dist/.a4drules/skills/webapp-ui-ux/data/web-interface.csv +31 -0
  29. package/dist/.a4drules/skills/webapp-ui-ux/scripts/core.js +255 -0
  30. package/dist/.a4drules/skills/webapp-ui-ux/scripts/design_system.js +861 -0
  31. package/dist/.a4drules/skills/webapp-ui-ux/scripts/search.js +98 -0
  32. package/dist/.a4drules/skills/webapp-unsplash-images/SKILL.md +71 -0
  33. package/dist/.a4drules/skills/webapp-unsplash-images/implementation/usage.md +159 -0
  34. package/dist/.a4drules/webapp-no-node-e.md +54 -15
  35. package/dist/.a4drules/webapp-react.md +9 -10
  36. package/dist/.a4drules/webapp-skills-first.md +26 -0
  37. package/dist/.a4drules/webapp.md +8 -0
  38. package/dist/AGENT.md +2 -0
  39. package/dist/CHANGELOG.md +22 -0
  40. package/dist/force-app/main/default/webapplications/appreactsampleb2e/package.json +4 -4
  41. package/dist/force-app/main/default/webapplications/appreactsampleb2e/webapplication.json +1 -1
  42. package/dist/package.json +3 -2
  43. package/dist/scripts/prepare-import-unique-fields.js +108 -0
  44. package/dist/scripts/setup-cli.mjs +282 -0
  45. package/package.json +3 -3
  46. package/dist/.a4drules/webapp-images.md +0 -15
  47. /package/dist/.a4drules/skills/{webapp-add-react-component → webapp-react-add-component}/implementation/component.md +0 -0
  48. /package/dist/.a4drules/skills/{webapp-add-react-component → webapp-react-add-component}/implementation/header-footer.md +0 -0
  49. /package/dist/.a4drules/skills/{webapp-add-react-component → webapp-react-add-component}/implementation/page.md +0 -0
  50. /package/dist/.a4drules/{webapp-code-quality.md → webapp-react-code-quality.md} +0 -0
  51. /package/dist/.a4drules/{webapp-typescript.md → webapp-react-typescript.md} +0 -0
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { CSV_CONFIG, AVAILABLE_STACKS, MAX_RESULTS, search, searchStack } from './core.js';
4
+ import { generateDesignSystem } from './design_system.js';
5
+
6
+ // ============ ARG PARSER ============
7
+
8
+ function parseArgs(argv) {
9
+ const args = { query: null, maxResults: MAX_RESULTS, format: 'ascii' };
10
+ let i = 2;
11
+ while (i < argv.length) {
12
+ const a = argv[i];
13
+ if (a === '--domain' || a === '-d') { args.domain = argv[++i]; }
14
+ else if (a === '--stack' || a === '-s') { args.stack = argv[++i]; }
15
+ else if (a === '--max-results' || a === '-n') { args.maxResults = parseInt(argv[++i], 10); }
16
+ else if (a === '--json') { args.json = true; }
17
+ else if (a === '--design-system' || a === '-ds') { args.designSystem = true; }
18
+ else if (a === '--project-name' || a === '-p') { args.projectName = argv[++i]; }
19
+ else if (a === '--format' || a === '-f') { args.format = argv[++i]; }
20
+ else if (a === '--persist') { args.persist = true; }
21
+ else if (a === '--page') { args.page = argv[++i]; }
22
+ else if (a === '--output-dir' || a === '-o') { args.outputDir = argv[++i]; }
23
+ else if (!a.startsWith('-') && !args.query) { args.query = a; }
24
+ i++;
25
+ }
26
+ return args;
27
+ }
28
+
29
+ // ============ FORMATTER ============
30
+
31
+ function formatOutput(result) {
32
+ if (result.error) return `Error: ${result.error}`;
33
+
34
+ const lines = [];
35
+ if (result.stack) {
36
+ lines.push('## UI Pro Max Stack Guidelines');
37
+ lines.push(`**Stack:** ${result.stack} | **Query:** ${result.query}`);
38
+ } else {
39
+ lines.push('## UI Pro Max Search Results');
40
+ lines.push(`**Domain:** ${result.domain} | **Query:** ${result.query}`);
41
+ }
42
+ lines.push(`**Source:** ${result.file} | **Found:** ${result.count} results\n`);
43
+
44
+ (result.results || []).forEach((row, i) => {
45
+ lines.push(`### Result ${i + 1}`);
46
+ for (const [key, value] of Object.entries(row)) {
47
+ const v = String(value);
48
+ lines.push(`- **${key}:** ${v.length > 300 ? v.slice(0, 300) + '...' : v}`);
49
+ }
50
+ lines.push('');
51
+ });
52
+
53
+ return lines.join('\n');
54
+ }
55
+
56
+ // ============ MAIN ============
57
+
58
+ const args = parseArgs(process.argv);
59
+
60
+ if (!args.query) {
61
+ console.error('Usage: node search.js "<query>" [--domain <d>] [--stack <s>] [--design-system] [-p "Name"]');
62
+ console.error(`Domains: ${Object.keys(CSV_CONFIG).join(', ')}`);
63
+ console.error(`Stacks: ${AVAILABLE_STACKS.join(', ')}`);
64
+ process.exit(1);
65
+ }
66
+
67
+ if (args.designSystem) {
68
+ const result = generateDesignSystem(
69
+ args.query,
70
+ args.projectName,
71
+ args.format,
72
+ !!args.persist,
73
+ args.page || null,
74
+ args.outputDir || null
75
+ );
76
+ console.log(result);
77
+
78
+ if (args.persist) {
79
+ const slug = args.projectName ? args.projectName.toLowerCase().replace(/\s+/g, '-') : 'default';
80
+ console.log('\n' + '='.repeat(60));
81
+ console.log(`✅ Design system persisted to design-system/${slug}/`);
82
+ console.log(` 📄 design-system/${slug}/MASTER.md (Global Source of Truth)`);
83
+ if (args.page) {
84
+ const pageSlug = args.page.toLowerCase().replace(/\s+/g, '-');
85
+ console.log(` 📄 design-system/${slug}/pages/${pageSlug}.md (Page Overrides)`);
86
+ }
87
+ console.log('');
88
+ console.log(`📖 Usage: When building a page, check design-system/${slug}/pages/[page].md first.`);
89
+ console.log(` If exists, its rules override MASTER.md. Otherwise, use MASTER.md.`);
90
+ console.log('='.repeat(60));
91
+ }
92
+ } else if (args.stack) {
93
+ const result = searchStack(args.query, args.stack, args.maxResults);
94
+ console.log(args.json ? JSON.stringify(result, null, 2) : formatOutput(result));
95
+ } else {
96
+ const result = search(args.query, args.domain, args.maxResults);
97
+ console.log(args.json ? JSON.stringify(result, null, 2) : formatOutput(result));
98
+ }
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: webapp-unsplash-images
3
+ description: Adds high-quality Unsplash images to React pages. Use when the user asks to add a hero image, background image, placeholder image, stock photo, decorative image, or any Unsplash-sourced imagery to the web application.
4
+ ---
5
+
6
+ # Unsplash Images
7
+
8
+ ## When to Use
9
+
10
+ Use this skill when:
11
+ - Adding hero banners, section backgrounds, or decorative images
12
+ - The user asks for stock photography or placeholder images
13
+ - A page needs visual appeal without custom assets
14
+
15
+ ---
16
+
17
+ ## Step 1 — Determine image purpose
18
+
19
+ Identify what the image is for:
20
+
21
+ - **Hero / banner** — full-width background behind text or a CTA
22
+ - **Section accent** — smaller image alongside content (stats, testimonials, features)
23
+ - **Card thumbnail** — image inside a card component
24
+ - **Background texture** — subtle decorative background
25
+
26
+ If unclear, ask:
27
+
28
+ > "Where should the image appear — as a hero banner, a section accent, or a card thumbnail?"
29
+
30
+ ---
31
+
32
+ ## Step 2 — Select the right Unsplash URL format
33
+
34
+ Read `implementation/usage.md` for the full reference. Key rules:
35
+
36
+ 1. **Always use `images.unsplash.com/photo-{id}` format** with explicit `w` and `q` parameters.
37
+ 2. **Never use `source.unsplash.com`** — it is deprecated and returns 404s.
38
+ 3. **Pin every image by its photo ID** — never rely on random or search endpoints.
39
+
40
+ ---
41
+
42
+ ## Step 3 — Validate image URLs
43
+
44
+ Before using any Unsplash URL in code:
45
+
46
+ 1. Open the URL in a browser or fetch it to confirm it returns a 200 status and a valid image.
47
+ 2. If the URL returns a 404, redirect loop, or broken image, **discard it** and pick a different photo ID.
48
+ 3. Never ship a URL you have not personally verified.
49
+
50
+ ---
51
+
52
+ ## Step 4 — Implementation
53
+
54
+ Read `implementation/usage.md` and follow the instructions there.
55
+
56
+ ---
57
+
58
+ ## Verification
59
+
60
+ Before completing:
61
+
62
+ 1. Confirm every Unsplash URL loads a valid image (no 404, no redirect loops).
63
+ 2. Confirm `alt` text is set appropriately (empty `alt=""` for decorative, descriptive for meaningful).
64
+ 3. Run from the web app directory:
65
+
66
+ ```bash
67
+ cd force-app/main/default/webapplications/<appName> && npm run lint && npm run build
68
+ ```
69
+
70
+ - **Lint:** MUST result in 0 errors.
71
+ - **Build:** MUST succeed.
@@ -0,0 +1,159 @@
1
+ # Unsplash Images — Implementation Guide
2
+
3
+ ## URL Format
4
+
5
+ Always use the direct `images.unsplash.com` format with explicit sizing:
6
+
7
+ ```
8
+ https://images.unsplash.com/photo-{PHOTO_ID}?w={WIDTH}&q={QUALITY}
9
+ ```
10
+
11
+ | Parameter | Purpose | Recommended values |
12
+ |-----------|---------|--------------------|
13
+ | `w` | Pixel width served by the CDN | `600` card, `800` section, `1200` hero, `1920` full-bleed |
14
+ | `q` | JPEG quality 1–100 | `80`–`85` (good balance of quality vs size) |
15
+
16
+ ### Deprecated / broken formats — do NOT use
17
+
18
+ | Format | Why it fails |
19
+ |--------|-------------|
20
+ | `source.unsplash.com/random` | Deprecated; returns 404 |
21
+ | `source.unsplash.com/{WIDTH}x{HEIGHT}` | Deprecated; returns 404 |
22
+ | `source.unsplash.com/featured/?{query}` | Deprecated; returns 404 |
23
+
24
+ ---
25
+
26
+ ## How to find a valid photo ID
27
+
28
+ 1. Go to [unsplash.com](https://unsplash.com) and search for the subject (e.g. "modern apartment").
29
+ 2. Open a photo. The URL will look like `unsplash.com/photos/{slug}-{PHOTO_ID}` or `unsplash.com/photos/{PHOTO_ID}`.
30
+ 3. The `PHOTO_ID` is the last hyphen-separated segment (e.g. `photo-1600596542815-ffad4c1539a9`).
31
+ 4. Build your URL: `https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=1200&q=85`
32
+ 5. **Test the URL** in a browser before committing.
33
+
34
+ ---
35
+
36
+ ## Declaring image constants
37
+
38
+ Define all Unsplash URLs as named constants at the top of the file. Never inline URLs in JSX.
39
+
40
+ ```tsx
41
+ const HERO_IMAGE = "https://images.unsplash.com/photo-1600596542815-ffad4c1539a9?w=1200&q=85";
42
+ const SECTION_IMAGE = "https://images.unsplash.com/photo-1514565131-fce0801e5785?w=800&q=85";
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Rendering images in JSX
48
+
49
+ ### Hero / banner (decorative — empty alt)
50
+
51
+ ```tsx
52
+ <div className="relative w-full overflow-hidden rounded-2xl">
53
+ <div className="relative aspect-[21/9] min-h-[280px] w-full md:aspect-[3/1]">
54
+ <img
55
+ src={HERO_IMAGE}
56
+ alt=""
57
+ className="h-full w-full object-cover"
58
+ loading="eager"
59
+ fetchPriority="high"
60
+ />
61
+ <div className="absolute inset-0 bg-black/40" />
62
+ <div className="absolute inset-0 flex flex-col items-center justify-center px-4">
63
+ {/* overlay content */}
64
+ </div>
65
+ </div>
66
+ </div>
67
+ ```
68
+
69
+ Key points:
70
+ - `alt=""` for decorative images (screen readers skip them).
71
+ - `loading="eager"` and `fetchPriority="high"` for above-the-fold heroes.
72
+ - `object-cover` prevents stretching.
73
+ - Semi-transparent overlay (`bg-black/40`) ensures text readability.
74
+
75
+ ### Section accent (meaningful — descriptive alt)
76
+
77
+ ```tsx
78
+ <div className="relative min-h-[240px] overflow-hidden rounded-2xl">
79
+ <img src={SECTION_IMAGE} alt="City skyline at sunset" className="h-full w-full object-cover" />
80
+ <div className="absolute inset-0 bg-gradient-to-r from-black/20 to-transparent" />
81
+ </div>
82
+ ```
83
+
84
+ ### Card thumbnail
85
+
86
+ ```tsx
87
+ <div className="aspect-[4/3] overflow-hidden bg-muted">
88
+ <img
89
+ src={imageUrl}
90
+ alt=""
91
+ className="h-full w-full object-cover transition-transform hover:scale-105"
92
+ loading="lazy"
93
+ />
94
+ </div>
95
+ ```
96
+
97
+ Key points:
98
+ - `loading="lazy"` for below-the-fold images.
99
+ - `hover:scale-105` subtle zoom on hover.
100
+ - `bg-muted` fallback color while loading.
101
+
102
+ ---
103
+
104
+ ## Fallback when no image is available
105
+
106
+ Always provide a placeholder when the image URL may be null:
107
+
108
+ ```tsx
109
+ {imageUrl ? (
110
+ <img src={imageUrl} alt="" className="h-full w-full object-cover" />
111
+ ) : (
112
+ <div className="flex h-full items-center justify-center text-muted-foreground">
113
+ No image
114
+ </div>
115
+ )}
116
+ ```
117
+
118
+ ---
119
+
120
+ ## Content Security Policy (CSP)
121
+
122
+ If the application enforces CSP headers, add `images.unsplash.com` to `img-src`:
123
+
124
+ ```
125
+ img-src 'self' https://images.unsplash.com;
126
+ ```
127
+
128
+ Other commonly needed origins for stock images:
129
+
130
+ | Origin | Purpose |
131
+ |--------|---------|
132
+ | `images.unsplash.com` | Unsplash photos |
133
+ | `images.pexels.com` | Pexels photos |
134
+ | `fonts.googleapis.com` | Google Fonts CSS |
135
+ | `fonts.gstatic.com` | Google Fonts files |
136
+
137
+ ---
138
+
139
+ ## Accessibility checklist
140
+
141
+ - [ ] Decorative images have `alt=""`
142
+ - [ ] Meaningful images have descriptive `alt` text
143
+ - [ ] Hero images use `loading="eager"` and `fetchPriority="high"`
144
+ - [ ] Below-fold images use `loading="lazy"`
145
+ - [ ] Text over images has sufficient contrast (use overlay like `bg-black/40`)
146
+ - [ ] All URLs verified to return a valid image (no 404s)
147
+
148
+ ---
149
+
150
+ ## Common mistakes
151
+
152
+ | Mistake | Fix |
153
+ |---------|-----|
154
+ | Using `source.unsplash.com` | Replace with `images.unsplash.com/photo-{id}?w=…&q=…` |
155
+ | Hardcoding an unverified URL | Open URL in browser first; replace if broken |
156
+ | Missing `w` parameter | Always set width — CDN returns full-res (5000px+) otherwise |
157
+ | `loading="lazy"` on hero | Use `loading="eager"` for above-the-fold images |
158
+ | No fallback for nullable URLs | Wrap in conditional with placeholder div |
159
+ | Inline URLs in JSX | Extract to named constants at file top |
@@ -1,26 +1,65 @@
1
1
  ---
2
- description: No node -e - use replace_in_file or write_to_file only
2
+ description: No complex node -e one-liners use temp .js files or sed/awk instead
3
3
  paths:
4
4
  - "force-app/main/default/webapplications/**/*"
5
5
  ---
6
6
 
7
- # A4D Enforcement: No node -e
7
+ # A4D Enforcement: No `node -e` One-Liners
8
8
 
9
- This project forbids using "node -e" for any operation (file manipulation, string replacement, reading/writing configs, shell automation).
9
+ This project **forbids** using `node -e` (or `node -p`, `node --eval`) one-liners for any operationfile manipulation, string replacement, reading/writing configs, or shell automation.
10
10
 
11
- Policy:
12
- - Never use "node -e" one-liners.
13
- - Use replace_in_file or write_to_file for code/config edits.
14
- - Use jq/sed/awk cautiously when needed; prefer replace_in_file for deterministic edits.
15
- - For JSON edits: prefer write_to_file after reading, or replace_in_file with precise diffs.
16
- - For ESLint/TS config changes: edit files directly via write_to_file or replace_in_file.
11
+ ## Why This Exists
17
12
 
18
- Rationale:
19
- - Ensures reproducibility and auditability.
20
- - Avoids shell escaping bugs and cross-platform inconsistencies.
21
- - Aligns with project reliability protocol.
13
+ Complex `node -e '...'` one-liners **silently break in Zsh** (the default macOS shell) because of:
22
14
 
23
- Violation handling:
24
- - If any prior step used "node -e", revert and redo using write_to_file or replace_in_file.
15
+ - **`!` (history expansion):** Zsh interprets `!` inside double quotes as history expansion, causing `event not found` errors or silent corruption.
16
+ - **Backtick interpolation:** Template literals (`` ` ``) are interpreted as command substitution by the shell before Node.js ever sees them.
17
+ - **Nested quoting:** Multi-line JS crammed into a single shell string requires fragile quote escaping that differs between Bash and Zsh.
18
+
19
+ These failures are **silent and intermittent**—the command may appear to succeed while producing corrupt output.
20
+
21
+ ## What To Do Instead
22
+
23
+ ### For multi-line file edits or transforms
24
+
25
+ 1. **Write a temporary `.js` script**, run it, then delete it:
26
+
27
+ ```bash
28
+ cat > /tmp/_transform.js << 'SCRIPT'
29
+ const fs = require('fs');
30
+ const data = JSON.parse(fs.readFileSync('package.json', 'utf8'));
31
+ data.name = 'my-app';
32
+ fs.writeFileSync('package.json', JSON.stringify(data, null, 2) + '\n');
33
+ SCRIPT
34
+ node /tmp/_transform.js && rm /tmp/_transform.js
35
+ ```
36
+
37
+ 2. **Use `sed` or `awk`** for simple, single-pattern replacements with careful escaping:
38
+
39
+ ```bash
40
+ sed -i '' 's/old-value/new-value/g' path/to/file
41
+ ```
42
+
43
+ 3. **Use `jq`** for JSON edits:
44
+
45
+ ```bash
46
+ jq '.name = "my-app"' package.json > tmp.json && mv tmp.json package.json
47
+ ```
48
+
49
+ 4. **Use the IDE/agent file-editing tools** (replace_in_file, write_to_file, StrReplace, Write) whenever available—these bypass the shell entirely.
50
+
51
+ ### For simple, truly one-line expressions
52
+
53
+ A trivial `node -e "console.log(1+1)"` with no special characters is acceptable, but **if the expression contains any of these, use a temp file instead:**
54
+ - Template literals (backticks)
55
+ - `!` characters
56
+ - Nested quotes
57
+ - Multi-line strings
58
+ - `fs` read/write operations
59
+
60
+ ## Violation Handling
61
+
62
+ - If any prior step used a complex `node -e` one-liner, **revert and redo** using one of the approved methods above.
63
+ - If a shell command fails with `event not found`, `unexpected token`, or produces garbled output, check for a `node -e` violation first.
25
64
 
26
65
  **Cross-reference:** This rule is also summarized in **webapp.md** (MUST FOLLOW #1). Both apply.
@@ -45,21 +45,20 @@ Use standard web APIs and npm packages only.
45
45
 
46
46
  ## Data Access (CRITICAL)
47
47
 
48
- ### Use DataSDK for All Salesforce API Calls
48
+ All Salesforce API calls **must** go through the DataSDK (`@salesforce/sdk-data`). Do NOT use `axios` or raw `fetch` — the SDK handles authentication and CSRF.
49
49
 
50
- ```typescript
51
- import { getDataSDK } from '@salesforce/sdk-data';
50
+ ### GraphQL (Preferred)
52
51
 
53
- const sdk = await getDataSDK();
54
- // Use sdk.graphql?.() or sdk.fetch!() for API calls
55
- ```
52
+ For queries and mutations, follow the **`graphql-data-access`** skill in `feature-graphql`. It covers schema exploration, query patterns, codegen, type generation, and guardrails.
56
53
 
57
- Do NOT use `axios` or raw `fetch` for Salesforce APIs. The SDK handles authentication and CSRF.
54
+ ### UI API (Fallback)
58
55
 
59
- ### Data Access Priority
56
+ When GraphQL cannot cover the use case, use `sdk.fetch!()` for UI API endpoints:
60
57
 
61
- 1. **GraphQL** (preferred) — queries & mutations via `sdk.graphql?.()`
62
- 2. **UI API** via `sdk.fetch!()` for `/services/data/v62.0/ui-api/*`
58
+ ```typescript
59
+ const sdk = await getDataSDK();
60
+ const resp = await sdk.fetch!('/services/data/v62.0/ui-api/records/{recordId}');
61
+ ```
63
62
 
64
63
  ### Apex REST is NOT Available
65
64
 
@@ -0,0 +1,26 @@
1
+ ---
2
+ description: Always search for and read relevant skills before starting any task
3
+ paths:
4
+ - "force-app/main/default/webapplications/**/*"
5
+ ---
6
+
7
+ # Skills-First Protocol (MUST FOLLOW)
8
+
9
+ **Before writing any code or executing any command**, search for relevant skills that may already provide guidance, patterns, or step-by-step instructions for the task at hand.
10
+
11
+ ## Core Directive
12
+ Before planning, executing a task, generating code, or running terminal commands, you MUST explicitly check if an existing Skill is available to handle the request. Do not default to manual implementation if a specialized domain Skill exists.
13
+
14
+ ## Pre-Task Sequence
15
+ 1. **Skill Discovery:** Review the names and descriptions of all available/loaded Skills in your current context.
16
+ 2. **Match Analysis:** Evaluate if the user's current task aligns with any Skill's described use case (e.g., code reviews, PR generation, database migrations, specific framework debugging).
17
+ 3. **Explicit Declaration:** If a matching Skill is found, your first output MUST be:
18
+ > "Skill identified: [Skill Name]. Executing via Skill instructions..."
19
+ You must then strictly adhere to the instructions defined in that specific Skill.
20
+
21
+ ## Prohibited Actions
22
+ * Do not write custom utility scripts or complex bash commands for a workflow that is already covered by a loaded Skill.
23
+ * Do not bypass or ignore the loaded `SKILL.md` instructions if a relevant Skill is triggered.
24
+
25
+ ## Manual Fallback
26
+ Only proceed with standard/manual execution if you have actively evaluated your available Skills and confirmed that no relevant Skill exists for the current prompt.
@@ -4,6 +4,10 @@ paths:
4
4
  - "force-app/main/default/webapplications/**/*"
5
5
  ---
6
6
 
7
+ # Skills-First (MUST FOLLOW)
8
+
9
+ **Before writing any code or running any command**, search for relevant skills (`SKILL.md` files) that cover your task. Read the full skill and follow its instructions. Skills live in `.a4drules/skills/` and `feature/*/skills/`. See **webapp-skills-first.md** for the full protocol and a task-to-skill lookup table.
10
+
7
11
  # Web App Generation
8
12
 
9
13
  ## Before `sf webapp generate`
@@ -75,6 +79,10 @@ Agents consistently miss these. **You must not leave them default.**
75
79
  - **Motion:** Use high-impact motion (e.g. staggered reveals).
76
80
  - **Depth:** Add atmosphere/depth in backgrounds.
77
81
 
82
+ # Shell Command Safety (MUST FOLLOW)
83
+
84
+ **Never use complex `node -e` one-liners** for file edits or multi-line transforms. They break in Zsh due to `!` history expansion and backtick interpolation. Use a temporary `.js` file, `sed`/`awk`, `jq`, or IDE file-editing tools instead. See **webapp-no-node-e.md** for full details and approved alternatives.
85
+
78
86
  # Development Cycle
79
87
 
80
88
  - Execute tasks continuously until all planned items complete in the current iteration.
package/dist/AGENT.md CHANGED
@@ -26,6 +26,8 @@ Used for SFDX metadata (LWC, Aura, etc.). Scripts here are for the base SFDX tem
26
26
  | `npm run prettier` | Format supported metadata files |
27
27
  | `npm run prettier:verify` | Check Prettier |
28
28
 
29
+ **One-command setup:** From project root run `node scripts/setup-cli.mjs --target-org <alias>` to run login (if needed), deploy, optional permset/data import, GraphQL schema/codegen, web app build, and optionally the dev server. Use `node scripts/setup-cli.mjs --help` for options (e.g. `--skip-login`, `--skip-data`, `--webapp-name`).
30
+
29
31
  Root **does not** run the React app. The root `npm run build` is a no-op for the base SFDX project.
30
32
 
31
33
  ### 2. React web app (where you do most work)
package/dist/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.84.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.83.0...v1.84.0) (2026-03-09)
7
+
8
+
9
+ ### Features
10
+
11
+ * **template:** add setup-cli and prepare-import-unique-fields scripts ([#240](https://github.com/salesforce-experience-platform-emu/webapps/issues/240)) ([5cad14c](https://github.com/salesforce-experience-platform-emu/webapps/commit/5cad14c9be8176b2faf2429fe8e8a56383aac1ae))
12
+
13
+
14
+
15
+
16
+
17
+ # [1.83.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.82.0...v1.83.0) (2026-03-09)
18
+
19
+
20
+ ### Features
21
+
22
+ * dedupe with feature skills, rename to webapp-react-* where relevant @W-21338965@ ([#233](https://github.com/salesforce-experience-platform-emu/webapps/issues/233)) ([9e4e4d8](https://github.com/salesforce-experience-platform-emu/webapps/commit/9e4e4d80f4a33575412e1940a8cbfaae6c035a12))
23
+
24
+
25
+
26
+
27
+
6
28
  # [1.82.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.81.0...v1.82.0) (2026-03-09)
7
29
 
8
30
  **Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
@@ -15,9 +15,9 @@
15
15
  "graphql:schema": "node scripts/get-graphql-schema.mjs"
16
16
  },
17
17
  "dependencies": {
18
- "@salesforce/agentforce-conversation-client": "^1.82.0",
19
- "@salesforce/sdk-data": "^1.82.0",
20
- "@salesforce/webapp-experimental": "^1.82.0",
18
+ "@salesforce/agentforce-conversation-client": "^1.84.0",
19
+ "@salesforce/sdk-data": "^1.84.0",
20
+ "@salesforce/webapp-experimental": "^1.84.0",
21
21
  "@tailwindcss/vite": "^4.1.17",
22
22
  "@tanstack/react-form": "^1.28.4",
23
23
  "class-variance-authority": "^0.7.1",
@@ -42,7 +42,7 @@
42
42
  "@graphql-eslint/eslint-plugin": "^4.1.0",
43
43
  "@graphql-tools/utils": "^11.0.0",
44
44
  "@playwright/test": "^1.49.0",
45
- "@salesforce/vite-plugin-webapp-experimental": "^1.82.0",
45
+ "@salesforce/vite-plugin-webapp-experimental": "^1.84.0",
46
46
  "@testing-library/jest-dom": "^6.6.3",
47
47
  "@testing-library/react": "^16.1.0",
48
48
  "@testing-library/user-event": "^14.5.2",
@@ -2,6 +2,6 @@
2
2
  "outputDir": "dist",
3
3
  "routing": {
4
4
  "trailingSlash": "never",
5
- "fallback": "/index.html"
5
+ "fallback": "index.html"
6
6
  }
7
7
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/webapp-template-base-sfdx-project-experimental",
3
- "version": "1.82.0",
3
+ "version": "1.84.0",
4
4
  "description": "Base SFDX project template",
5
5
  "private": true,
6
6
  "files": [
@@ -18,7 +18,8 @@
18
18
  "test:unit:coverage": "sfdx-lwc-jest --coverage",
19
19
  "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
20
20
  "prettier:verify": "prettier --check \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
21
- "precommit": "lint-staged"
21
+ "precommit": "lint-staged",
22
+ "setup": "node scripts/setup-cli.mjs"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@lwc/eslint-plugin-lwc": "^2.0.0",