@zohofinance/commerce 1.0.0 → 1.1.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.
- package/README.md +59 -0
- package/package.json +2 -2
- package/ts-dist/mocks/init-theme/.claude/CLAUDE.md +6 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/SKILL.md +242 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/figma.md +81 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/screenshot.md +54 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/url.md +88 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/spec-table.md +102 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/accessibility.md +110 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/performance.md +127 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/tokens.md +87 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/visual-diff.md +123 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/SKILL.md +605 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/design-tokens.md +105 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/page-json-contract.md +58 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/qa-accessibility.md +35 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/reference-lookup.md +94 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/section-anatomy.md +109 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/SKILL.md +313 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/agent-hierarchy.md +142 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/ask-developer.md +113 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/bootstrap.md +260 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/build-metrics.md +89 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/code-quality.md +186 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/common-pages-agent.md +97 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/dev-server-and-urls.md +136 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/exemplars.md +79 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-discovery.md +138 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-extraction.md +132 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/image-sources.md +84 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/inputs/guidelines-frame.md +178 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-builder.md +322 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-orchestrator.md +199 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/parallel-fanout.md +152 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/a11y.mjs +129 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/lint-section.mjs +502 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/perf.mjs +134 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/pixel-diff.mjs +206 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/record-build-metrics.mjs +118 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/section-builder.md +131 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/subagent-escalation.md +75 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/transcription-rules.md +98 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/verification.md +227 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/visual-verify-loop.md +117 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/_index.md +4 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/assets.md +105 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/best-practices.md +212 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/custom-scripts.md +294 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/i18n.md +155 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/introduction.md +91 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/layouts.md +158 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/pages.md +156 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/_index.md +4 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/filters.md +419 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/global-objects.md +415 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/schema-types.md +926 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/tags.md +259 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/sections.md +203 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/setup-guide.md +424 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/snippets.md +70 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/theme-structure.md +252 -0
- package/ts-dist/mocks/init-theme/.cursor/PLAYBOOK.md +144 -0
- package/ts-dist/mocks/init-theme/.cursor/README.md +6 -0
- package/ts-dist/mocks/init-theme/.cursor/agents/figma-desktop-mobile-parallel.md +48 -0
- package/ts-dist/mocks/init-theme/.cursor/agents/visual-compare.md +221 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/add-field.md +83 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/add-theme-setting.md +200 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/assemble-page.md +72 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/audit-page.md +57 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-page-sections.md +110 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-section.md +418 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-theme.md +307 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/compare-section.md +358 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/create-theme.md +77 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/extract-tokens.md +43 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/fix-section.md +92 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/impact.md +50 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-a11y.md +66 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-i18n.md +110 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-layout.md +127 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-performance.md +72 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-section.md +84 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-sections.md +48 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-theme.md +85 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/redesign-section.md +177 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/refactor-section.md +185 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/sync-theme-settings.md +132 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-page.md +60 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-section-group.md +88 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-theme-settings.md +119 -0
- package/ts-dist/mocks/init-theme/.cursor/examples/design-instructions-template.md +151 -0
- package/ts-dist/mocks/init-theme/.cursor/mcp.json +18 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/README.md +160 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/accessibility.mdc +24 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/add-field.mdc +222 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/add-theme-setting.mdc +39 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/assemble-page.mdc +130 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/audit-page.mdc +92 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/build-section.mdc +178 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/build-theme.mdc +47 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/compare-section.mdc +94 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/create-theme.mdc +78 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/css.mdc +137 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/design-spec-extraction.mdc +255 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/extract-tokens.mdc +43 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/figma-mcp-resolution.mdc +40 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/fix-section.mdc +154 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/general.mdc +30 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/i18n.mdc +85 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/javascript.mdc +85 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/liquid-no-hardcoded-strings.mdc +42 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/liquid.mdc +171 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/mobile-desktop-setting-meta.mdc +34 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/naming-convention.mdc +64 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/pages.mdc +120 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/performance.mdc +51 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/qa-section.mdc +134 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/redesign-section.mdc +147 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/schema-sync.mdc +110 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/schema.mdc +360 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/share-urls.mdc +68 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/browser-verify.md +128 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/design-tokens.md +105 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/page-json-contract.md +87 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/qa-accessibility.md +35 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/reference-lookup.md +88 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/section-anatomy.md +173 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Dev server + page URLs — ask before you browse
|
|
2
|
+
|
|
3
|
+
**Read this before any Chrome DevTools MCP `navigate_page` call during `/build-theme`.**
|
|
4
|
+
|
|
5
|
+
URL paths vary by store and dev setup. **Never assume** `/` is home or `/collections/all` is the collection page.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Step 1 — Collect `storeUrl` from the developer (mandatory)
|
|
10
|
+
|
|
11
|
+
Before starting or requesting the dev server, ask:
|
|
12
|
+
|
|
13
|
+
> What is your **storeUrl** for local dev?
|
|
14
|
+
> Example: `<your store url>`
|
|
15
|
+
|
|
16
|
+
Record it in scratchpad:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
// .claude/scratchpad/<theme>/dev-config.json
|
|
20
|
+
{
|
|
21
|
+
"store_url": "<your store url>",
|
|
22
|
+
"dev_server_port": 3000,
|
|
23
|
+
"page_urls": {},
|
|
24
|
+
"confirmed_by_developer": false
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Do not hardcode a demo store URL unless the developer confirms it.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Step 2 — Dev server (ask or start)
|
|
33
|
+
|
|
34
|
+
Pass the developer's store URL into `theme dev` via `--storeUrl`. Without it, the preview uses mock data only.
|
|
35
|
+
|
|
36
|
+
Use the value from Step 1 (`dev-config.json` → `store_url`) as `<your store url>`.
|
|
37
|
+
|
|
38
|
+
**Option A — Developer starts it (preferred if already running):**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
cd <theme_name>
|
|
42
|
+
npx @zohofinance/commerce theme dev --storeUrl=<your store url>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Ask: *"Is the dev server already running on port 3000? If not, please start it with the command above (or tell me to start it)."*
|
|
46
|
+
|
|
47
|
+
**Option B — Agent starts it:**
|
|
48
|
+
|
|
49
|
+
1. Check: `lsof -i :3000`
|
|
50
|
+
2. If not running, start in background from the theme folder:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx @zohofinance/commerce theme dev --storeUrl=<your store url>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
3. Wait for "Preview theme in http://localhost:3000" (up to 30s)
|
|
57
|
+
4. Tell the developer: *"Dev server started with your storeUrl."*
|
|
58
|
+
|
|
59
|
+
If the server fails to start → stop and ask the developer to fix CLI/network issues. Do not proceed to visual verify.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Step 3 — Confirm page URLs with the developer (mandatory before browse)
|
|
64
|
+
|
|
65
|
+
Present the URLs you plan to use and **wait for confirmation** (or correction):
|
|
66
|
+
|
|
67
|
+
| Page | Default guess (verify!) | Example confirmed |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| Home | `http://localhost:3000/home` | `http://localhost:3000/home` |
|
|
70
|
+
| Product | `http://localhost:3000/products/<handle>` | `http://localhost:3000/products/item-1` |
|
|
71
|
+
| Collection | `http://localhost:3000/collections/<handle>` | `http://localhost:3000/collections/all-products` |
|
|
72
|
+
| Blog list | `http://localhost:3000/blogs` or `/blog` | ask developer |
|
|
73
|
+
| Blog detail | `http://localhost:3000/blogs/<handle>` | ask developer |
|
|
74
|
+
|
|
75
|
+
**Ask once per build** (main orchestrator), not per subagent:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
Before I run visual verify in the browser, please confirm these page URLs:
|
|
79
|
+
|
|
80
|
+
Home: http://localhost:3000/home
|
|
81
|
+
Product: http://localhost:3000/products/item-1
|
|
82
|
+
Collection: http://localhost:3000/collections/all-products
|
|
83
|
+
Blog list: ?
|
|
84
|
+
Blog detail: ?
|
|
85
|
+
|
|
86
|
+
Reply with corrections or YES to proceed.
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
After confirmation, write to `dev-config.json`:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"page_urls": {
|
|
94
|
+
"index": "http://localhost:3000/home",
|
|
95
|
+
"product": "http://localhost:3000/products/item-1",
|
|
96
|
+
"collection": "http://localhost:3000/collections/all-products"
|
|
97
|
+
},
|
|
98
|
+
"confirmed_by_developer": true,
|
|
99
|
+
"confirmed_at": "<ISO8601>"
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Subagents and section builders MUST read `dev-config.json`** — they do not guess URLs.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Step 4 — Navigate only after confirmation
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
✅ dev-config.json exists AND confirmed_by_developer === true
|
|
111
|
+
✅ dev server responding on localhost:3000
|
|
112
|
+
→ navigate_page to the confirmed URL for that page
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If `confirmed_by_developer` is false → **do not open the browser**. Ask the main orchestrator to collect URLs from the developer.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Common mistakes
|
|
120
|
+
|
|
121
|
+
| Wrong | Right |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `http://localhost:3000/` for home | `http://localhost:3000/home` (after developer confirms) |
|
|
124
|
+
| `/product/sample-product` | `/products/item-1` (handle varies by store) |
|
|
125
|
+
| `/collections/all` | `/collections/all-products` (handle varies) |
|
|
126
|
+
| Hardcoded demo storeUrl | Value from developer in `dev-config.json` |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Who asks what
|
|
131
|
+
|
|
132
|
+
| Role | Responsibility |
|
|
133
|
+
|---|---|
|
|
134
|
+
| **Main orchestrator** | Collect `storeUrl` + confirm all page URLs once at Stage 0/1 |
|
|
135
|
+
| **Page orchestrator** | Read `dev-config.json`; never invent URLs |
|
|
136
|
+
| **Section subagent** | Read `dev-config.json`; if missing, write `needs-developer.md` and escalate |
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# LOGIC patterns — build from docs (no sibling themes available)
|
|
2
|
+
|
|
3
|
+
When a page agent builds a section, it does NOT pick one exemplar file and stay close to it. It **reads the official ZCommerce docs**, synthesizes the required logic patterns, then writes **fresh code** for the new theme.
|
|
4
|
+
|
|
5
|
+
There is no anchor. There is no sibling theme to reference. There is only doc-based pattern synthesis → fresh write.
|
|
6
|
+
|
|
7
|
+
## Why docs, not sibling themes
|
|
8
|
+
|
|
9
|
+
No sibling themes are available in this standalone setup. Every section must be built from the official ZCommerce documentation:
|
|
10
|
+
|
|
11
|
+
- `zcommerce-docs/sections.md` — section structure, schema rules, block patterns.
|
|
12
|
+
- `zcommerce-docs/reference/schema-types.md` — all valid schema field types.
|
|
13
|
+
- `zcommerce-docs/snippets.md` — snippet variable scoping.
|
|
14
|
+
- `zcommerce-docs/reference/filters.md` and `tags.md` — valid Liquid primitives.
|
|
15
|
+
|
|
16
|
+
The output is a clean, fresh implementation that follows the documented patterns without copying from any existing source.
|
|
17
|
+
|
|
18
|
+
## The protocol
|
|
19
|
+
|
|
20
|
+
For each section archetype the agent needs to build:
|
|
21
|
+
|
|
22
|
+
1. **Read the docs.** Consult `zcommerce-docs/sections.md` and `zcommerce-docs/reference/schema-types.md` for the required structure.
|
|
23
|
+
2. **Plan the schema.** Identify which schema field types (text, richtext, image_picker, url, etc.) are appropriate for each visible element.
|
|
24
|
+
3. **Identify patterns.** From the docs, determine:
|
|
25
|
+
- Schema field types and IDs to use
|
|
26
|
+
- Liquid loop and conditional patterns
|
|
27
|
+
- Web component usage (`<add-to-cart>`, `<expand-accordion>`, etc.)
|
|
28
|
+
- Edge case handling (empty states, missing data, accessibility hooks)
|
|
29
|
+
4. **Plan fresh code.** Sketch the new section's DOM + schema using the documented patterns AND design values (Tailwind classes, colors, fonts, spacing) from the Figma + theme tokens.
|
|
30
|
+
5. **Write fresh.** No `cp` commands. No copy-paste of multi-line blocks. The agent types the new file.
|
|
31
|
+
6. **Lint.** `verify-theme.mjs` will catch structural problems. If the lint fails, fix and re-run.
|
|
32
|
+
|
|
33
|
+
## Archetype → how to build
|
|
34
|
+
|
|
35
|
+
For each archetype below, build from the ZCommerce docs. No sibling themes are available.
|
|
36
|
+
|
|
37
|
+
| Archetype | How to build |
|
|
38
|
+
|---|---|
|
|
39
|
+
| Hero banner | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
40
|
+
| Multi-image hero | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
41
|
+
| Promo banner / advertisement strip | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
42
|
+
| Product collection / listing grid | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
43
|
+
| Product card snippet | build from docs (zcommerce-docs/snippets.md) — no sibling themes available |
|
|
44
|
+
| Product detail page (PDP) | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
45
|
+
| Variant picker | build from docs (zcommerce-docs/snippets.md) — no sibling themes available |
|
|
46
|
+
| Cart list | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
47
|
+
| Cart popup / mini-cart | build from docs (zcommerce-docs/sections.md, zcommerce-docs/snippets.md) — no sibling themes available |
|
|
48
|
+
| Checkout | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
49
|
+
| Account: profile / address / order / order-status | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
50
|
+
| Account: quote (B2B) | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
51
|
+
| CTA cards / promo grid | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
52
|
+
| Blog list / blog grid | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
53
|
+
| Blog detail / article | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
54
|
+
| Category header | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
55
|
+
| Filter rail | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
56
|
+
| Pagination snippet | build from docs (zcommerce-docs/snippets.md) — no sibling themes available |
|
|
57
|
+
| 404 | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
58
|
+
| Sign-in / sign-up / forgot-password | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
59
|
+
| Generic page | build from docs (zcommerce-docs/sections.md) — no sibling themes available |
|
|
60
|
+
|
|
61
|
+
If no doc covers the archetype, build from the schema-types docs + best-practices docs (no inherited logic).
|
|
62
|
+
|
|
63
|
+
## Anti-exemplars — patterns to avoid
|
|
64
|
+
|
|
65
|
+
These code-quality failures must be avoided when writing new sections:
|
|
66
|
+
|
|
67
|
+
- Hero-banner sections exceeding 600 lines (deeply nested conditionals)
|
|
68
|
+
- Collection-grid sections exceeding 900 lines (6-level nesting)
|
|
69
|
+
- Product-details sections exceeding 1600 lines (longest in any repo)
|
|
70
|
+
- Header sections exceeding 500 lines (megamenu permutation bloat)
|
|
71
|
+
- Product-card snippets exceeding 250 lines (B2B-specific logic not stripped for B2C)
|
|
72
|
+
|
|
73
|
+
If the agent's planned section starts looking like these in line count or nesting depth, re-plan by simplifying the structure.
|
|
74
|
+
|
|
75
|
+
## Hard rule
|
|
76
|
+
|
|
77
|
+
The agent must build each archetype fresh from the official docs (`zcommerce-docs/sections.md`, `zcommerce-docs/snippets.md`). No sibling themes are available to read from.
|
|
78
|
+
|
|
79
|
+
The lint and `verify-theme.mjs` catch structural problems. Build from docs to write cleanly.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Figma discovery — auto-find pages (do NOT ask for URLs first)
|
|
2
|
+
|
|
3
|
+
When the developer runs `/build-theme <theme> <figma_file_key>`, the agent **discovers pages itself**. Asking for per-page Figma URLs is a **fallback only**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What the developer provides
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
/build-theme my_theme <figma_file_key>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Optional: root canvas node ID (e.g. `<root_node_id>` for the theme canvas).
|
|
14
|
+
|
|
15
|
+
**They do NOT need to paste 5 page URLs** if the file follows the standard Commerce Theme layout.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Why selecting one frame is not enough
|
|
20
|
+
|
|
21
|
+
Selecting a single frame in Figma (e.g. Product Detail Page) gives MCP context for **that node only**. It does not expose:
|
|
22
|
+
|
|
23
|
+
- The full **Website View** / **Mobile View** trees
|
|
24
|
+
- Sibling pages (index, collection, blogs, …)
|
|
25
|
+
- The **Guidelines** frame for tokens
|
|
26
|
+
|
|
27
|
+
The agent must **walk up** to the theme canvas and call `get_metadata` / `get_design_context` on the root — not treat the selected frame as the only input.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Discovery protocol (Phase 0 — mandatory before asking developer)
|
|
32
|
+
|
|
33
|
+
### Step 1 — Resolve file key and root node
|
|
34
|
+
|
|
35
|
+
From command args or the developer's Figma URL:
|
|
36
|
+
|
|
37
|
+
- `fileKey`: e.g. `<figma_file_key>`
|
|
38
|
+
- `rootNodeId`: optional; if omitted, call `get_metadata` on the file canvas and find the theme canvas (e.g. the named theme frame)
|
|
39
|
+
|
|
40
|
+
### Step 2 — Fetch structure
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Figma MCP: get_metadata
|
|
44
|
+
fileKey: <fileKey>
|
|
45
|
+
nodeId: <rootNodeId or canvas id>
|
|
46
|
+
|
|
47
|
+
Figma MCP: get_design_context (if metadata is sparse)
|
|
48
|
+
fileKey: <fileKey>
|
|
49
|
+
nodeId: <Website View frame id>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Look for these top-level children under the theme canvas:
|
|
53
|
+
|
|
54
|
+
| Frame name (typical) | Contains |
|
|
55
|
+
|---|---|
|
|
56
|
+
| Guidelines | Tokens — fonts, colors, components |
|
|
57
|
+
| Website View | Desktop page frames (~1496px wide) |
|
|
58
|
+
| Mobile View | Mobile page frames (~390px wide) |
|
|
59
|
+
|
|
60
|
+
### Step 3 — Build page map
|
|
61
|
+
|
|
62
|
+
For each direct child of **Website View**, record name + node ID. Match to **Mobile View** by page name:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
PAGE MAP (auto-discovered)
|
|
66
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
67
|
+
Page Name | Desktop Node | Mobile Node | Page JSON
|
|
68
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
69
|
+
Home Page | 2613:146 | 2375:4029 | index.json
|
|
70
|
+
Product Detail Page | 2321:4829 | 2560:1012 | product.json
|
|
71
|
+
...
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Map names → standard JSON filenames:
|
|
75
|
+
|
|
76
|
+
| Figma name contains | JSON file |
|
|
77
|
+
|---|---|
|
|
78
|
+
| Home, Index | `index.json` |
|
|
79
|
+
| Product | `product.json` |
|
|
80
|
+
| Collection, Listing, Category | `collection.json` |
|
|
81
|
+
| Blog Page, Blog List | `blogs.json` |
|
|
82
|
+
| Blog Detail, Article | `blog.json` |
|
|
83
|
+
|
|
84
|
+
### Step 4 — Present map to developer (approval gate)
|
|
85
|
+
|
|
86
|
+
Show the discovered map. Ask:
|
|
87
|
+
|
|
88
|
+
> I found these pages in Figma. Does this look correct? Reply YES / EDIT / SKIP.
|
|
89
|
+
|
|
90
|
+
**Do not ask for Figma URLs** if discovery succeeded.
|
|
91
|
+
|
|
92
|
+
### Step 5 — Save artefacts
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
.claude/scratchpad/<theme>/figma-discovery.json
|
|
96
|
+
.claude/scratchpad/<theme>/bootstrap/guidelines-extraction.md
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"file_key": "<figma_file_key>",
|
|
102
|
+
"root_node_id": "2193:766",
|
|
103
|
+
"pages": {
|
|
104
|
+
"index": { "desktop": "2613:146", "mobile": "2375:4029" },
|
|
105
|
+
"product": { "desktop": "2321:4829", "mobile": "2560:1012" }
|
|
106
|
+
},
|
|
107
|
+
"discovered_at": "<ISO8601>",
|
|
108
|
+
"source": "get_metadata"
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Page orchestrators read node IDs from this file — not from developer-pasted URLs.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## When to ask the developer for URLs (fallback only)
|
|
117
|
+
|
|
118
|
+
| Condition | Action |
|
|
119
|
+
|---|---|
|
|
120
|
+
| `get_metadata` / `get_design_context` fails | Ask for file URL + root node, or open Figma desktop |
|
|
121
|
+
| No "Website View" / "Mobile View" in file | Ask which frames are desktop/mobile for each page |
|
|
122
|
+
| Ambiguous duplicate page names | Ask which frame is canonical |
|
|
123
|
+
| Developer passed **only** a single-page URL (not full build) | Scope to that page; don't ask for other 4 pages |
|
|
124
|
+
| File is non-standard (no guidelines frame) | Ask for guidelines URL OR use `get_variable_defs` |
|
|
125
|
+
|
|
126
|
+
**Never ask for all 5 page URLs when `figma_file_key` was provided and discovery returned a valid map.**
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Selected frame in Figma desktop
|
|
131
|
+
|
|
132
|
+
If the developer selected a frame before running the command:
|
|
133
|
+
|
|
134
|
+
1. Use that node's `fileKey` + `nodeId` as a **hint** (which page they're focused on)
|
|
135
|
+
2. Still run discovery from the **parent theme canvas** to find all pages
|
|
136
|
+
3. Do not assume the selected frame is the only page to build
|
|
137
|
+
|
|
138
|
+
Example: selected `2321:4829` (Product) → discovery finds it's under Website View → also find index, collection, blogs from siblings.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Per-element Figma extraction — the ONLY source of truth for visual values
|
|
2
|
+
|
|
3
|
+
The previous skill versions failed because agents generated section code from imagination (look at a screenshot, guess values, write code). This document fixes that. Every section file MUST be built from a **Figma Spec** — a structured JSON of every visible element's exact properties, extracted from `get_design_context` on the section's specific Figma node. No more guessing.
|
|
4
|
+
|
|
5
|
+
## Rule
|
|
6
|
+
|
|
7
|
+
Before writing a single line of section markup, the section-builder subagent MUST produce a Figma Spec at `<scratchpad>/sections/<section>/figma-spec.json`. The build phase reads this JSON and transcribes — it does NOT look at a screenshot and improvise.
|
|
8
|
+
|
|
9
|
+
The `verify-theme.mjs` `figma_spec_present` check fails the build if any non-common section is missing its `figma-spec.json`.
|
|
10
|
+
|
|
11
|
+
## Step 1 — Identify the section's Figma node
|
|
12
|
+
|
|
13
|
+
The page orchestrator gave you a node ID. If it didn't, ASK THE DEVELOPER (see `ask-developer.md`):
|
|
14
|
+
|
|
15
|
+
> "I need to build the {section_name} section but I don't have its Figma node ID. Can you give me the Figma URL with `?node-id=X-Y` pointing at this section's frame?"
|
|
16
|
+
|
|
17
|
+
Never proceed past this step without a confirmed node ID.
|
|
18
|
+
|
|
19
|
+
## Step 2 — Get the structured tree (SECTION NODE ONLY — Level B)
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Figma MCP: get_design_context
|
|
23
|
+
fileKey: <from discovery>
|
|
24
|
+
nodeId: <the SECTION's node ID from Level A sections.plan.md>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Never** pass the parent page frame node ID here. Level B agents that read the full page hallucinate styles from unrelated sections.
|
|
28
|
+
|
|
29
|
+
For each element, explicitly extract:
|
|
30
|
+
- `border_radius` — if 0 or missing, code must have **no** border-radius
|
|
31
|
+
- `background` / text `color` — exact hex before token mapping
|
|
32
|
+
- Image frames — `w`, `h`, `object_fit` for product card media boxes
|
|
33
|
+
|
|
34
|
+
Save raw response to `<scratchpad>/sections/<section>/design-context.raw.json`.
|
|
35
|
+
|
|
36
|
+
If `get_design_context` returns "nothing selected" or fails, fall back: `get_metadata` to walk children, then `get_screenshot` on each leaf — but **ask the developer to open Figma desktop and select the section** as the preferred recovery path.
|
|
37
|
+
|
|
38
|
+
## Step 3 — Walk the tree and build the Figma Spec
|
|
39
|
+
|
|
40
|
+
For every visible element, extract:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"id": "stable identifier within the section, e.g. 'hero-left-panel-image'",
|
|
45
|
+
"kind": "frame | text | image | vector | line | rectangle",
|
|
46
|
+
"position": { "x": 64, "y": 80, "w": 480, "h": 640 },
|
|
47
|
+
"layout": {
|
|
48
|
+
"type": "flex | grid | absolute",
|
|
49
|
+
"direction": "row | column",
|
|
50
|
+
"gap": 16,
|
|
51
|
+
"padding": { "top": 32, "right": 32, "bottom": 32, "left": 32 },
|
|
52
|
+
"align_items": "start | center | end | stretch",
|
|
53
|
+
"justify_content": "start | center | end | space-between"
|
|
54
|
+
},
|
|
55
|
+
"background": { "type": "solid | image | linear-gradient", "value": "#FFAB4A" },
|
|
56
|
+
"border": { "width": 1, "color": "#D1D1D1", "style": "solid" },
|
|
57
|
+
"border_radius": { "top_left": 24, "top_right": 24, "bottom_right": 24, "bottom_left": 24 },
|
|
58
|
+
"shadow": { "x": 0, "y": 4, "blur": 12, "spread": 0, "color": "rgba(0,0,0,0.08)" },
|
|
59
|
+
|
|
60
|
+
"text": {
|
|
61
|
+
"content": "Soft toys for your kiddo",
|
|
62
|
+
"font_family": "Oswald",
|
|
63
|
+
"font_weight": 600,
|
|
64
|
+
"font_size": 56,
|
|
65
|
+
"line_height": 56,
|
|
66
|
+
"letter_spacing": 0,
|
|
67
|
+
"color": "#000000",
|
|
68
|
+
"align": "left"
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
"image": {
|
|
72
|
+
"node_id": "2613:148",
|
|
73
|
+
"natural_w": 800,
|
|
74
|
+
"natural_h": 800,
|
|
75
|
+
"object_fit": "cover | contain",
|
|
76
|
+
"asset_filename_suggestion": "hero-banner-panel-left-penguin.png"
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
"children": [ ... recursive ... ]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Every field is exact (not "roughly 56px" — 56). Every color is the exact hex from the Figma fill. Every position is the exact pixel coordinate. Children are recursive.
|
|
84
|
+
|
|
85
|
+
For each top-level section, the Figma Spec is one root object containing the full hierarchy.
|
|
86
|
+
|
|
87
|
+
## Step 4 — Map Figma colors → theme tokens
|
|
88
|
+
|
|
89
|
+
For every color in the Figma Spec, look up the theme tokens in `settings/theme.json` and `figma-variables.json`. If a color exactly matches a token, replace the hex in the spec with the token name:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
"background": { "type": "solid", "value": "var(--color-primary)" }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If no token matches within ΔE 1.5, leave the hex AND flag in `<scratchpad>/sections/<section>/unmapped-colors.md` so the developer can decide whether to:
|
|
96
|
+
- Add a new theme token, OR
|
|
97
|
+
- Use the raw hex as a one-off (rare).
|
|
98
|
+
|
|
99
|
+
Same for spacing: if a Figma padding of 64 matches `--space-16`, use `var(--space-16)`. Otherwise log it.
|
|
100
|
+
|
|
101
|
+
Same for fonts: should always map to `--font-heading` or `--font-body`.
|
|
102
|
+
|
|
103
|
+
## Step 5 — Extract image assets
|
|
104
|
+
|
|
105
|
+
For every `image` node in the spec:
|
|
106
|
+
|
|
107
|
+
1. Call `mcp__32a68a89-...__get_screenshot` on the image's `node_id` with `maxDimension: 1600` and `enableBase64Response: true`.
|
|
108
|
+
2. Decode the base64 PNG and save it to `assets/<asset_filename_suggestion>` (the filename is auto-generated as `<section-name>-<purpose>.png`).
|
|
109
|
+
3. Update `assets/fingerprint.json` to include the new asset.
|
|
110
|
+
|
|
111
|
+
If `get_screenshot` returns an empty or non-PNG response, or if the sandbox can't decode it, ASK THE DEVELOPER:
|
|
112
|
+
|
|
113
|
+
> "I extracted the hero-banner left-panel image (Figma node 2613:148) but the result wasn't usable. Can you export this image manually from Figma and drop it in `assets/hero-banner-panel-left-penguin.png`?"
|
|
114
|
+
|
|
115
|
+
Once the developer confirms, continue.
|
|
116
|
+
|
|
117
|
+
**Never substitute a sibling theme's asset.** Never copy assets from another theme's folder. If extraction fails and developer hasn't provided, write to NEEDS_REVIEW and use a 1×1 transparent placeholder so the section still renders.
|
|
118
|
+
|
|
119
|
+
## Step 6 — Save the Figma Spec
|
|
120
|
+
|
|
121
|
+
Save to `<scratchpad>/sections/<section>/figma-spec.json`. This is the build contract. The next phase (Liquid build) transcribes this directly.
|
|
122
|
+
|
|
123
|
+
## Step 7 — Hand off to the build phase
|
|
124
|
+
|
|
125
|
+
The build phase reads `figma-spec.json` and produces the Liquid file by transcription. Every element in the spec must appear in the markup. Every text content goes into the schema as a setting default (or the page JSON if it's block-instance content). Every measurement either becomes a Tailwind class (if a token matches) or inline CSS via `{% style %}`.
|
|
126
|
+
|
|
127
|
+
## Key principles
|
|
128
|
+
|
|
129
|
+
- **No imagination.** If the value isn't in the Figma Spec, don't put it in the code.
|
|
130
|
+
- **No screenshot-only guesses.** Screenshots are for human visual diff after the build, not for measurement extraction during the build.
|
|
131
|
+
- **Ask the developer** when extraction fails, when an asset can't be downloaded, when a Figma node isn't accessible, when a token doesn't match.
|
|
132
|
+
- **Save everything** to scratchpad. The Figma Spec is auditable — if a build produces wrong output, the developer can diff the Spec against the rendered page and see exactly where the divergence happened.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Image sources — dev server vs deploy
|
|
2
|
+
|
|
3
|
+
One rule that causes visual mismatch when wrong: **how image `src` is built depends on where the URL comes from.**
|
|
4
|
+
|
|
5
|
+
## Quick reference
|
|
6
|
+
|
|
7
|
+
| Source | Stored as | Liquid pattern | Notes |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| Theme static asset (`assets/hero.png`) | filename in schema JSON | `{{ 'hero.png' \| asset_url }}` | Always use `asset_url` |
|
|
10
|
+
| Schema `image_picker` default | `{ "url": "hero.png" }` | `{{ section.settings.image.url \| asset_url }}` | **Required in dev** — JSON stores filename only |
|
|
11
|
+
| Schema `image_picker` admin upload | full CDN URL | `{{ section.settings.image.url }}` | Already absolute — do NOT pipe `asset_url` |
|
|
12
|
+
| Product / collection media | CDN URL from API | `{{ image.url }}?organization_id={{ organizationId }}` | Live store data — not `asset_url` |
|
|
13
|
+
| Figma-extracted decorative PNG | `assets/<section>-<role>.png` | `{{ '<file>.png' \| asset_url }}` | Saved during build |
|
|
14
|
+
|
|
15
|
+
## The dev-server catch (most common visual bug)
|
|
16
|
+
|
|
17
|
+
In the **local dev server**, page JSON and schema defaults store image values as **filenames** (e.g. `"hero-banner-left.png"`). The dev proxy does not resolve bare filenames — you must pipe through `asset_url`:
|
|
18
|
+
|
|
19
|
+
```liquid
|
|
20
|
+
{% comment %} ✅ Theme asset from schema JSON default {% endcomment %}
|
|
21
|
+
<img
|
|
22
|
+
src="{{ section.settings.panel_image.url | asset_url }}"
|
|
23
|
+
alt="{{ section.settings.panel_image.alt | default: section.settings.heading | escape }}"
|
|
24
|
+
width="668"
|
|
25
|
+
height="400"
|
|
26
|
+
loading="lazy"
|
|
27
|
+
>
|
|
28
|
+
|
|
29
|
+
{% comment %} ✅ Theme asset with known filename {% endcomment %}
|
|
30
|
+
<img src="{{ 'icon-heart.png' | asset_url }}" alt="" width="48" height="48">
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```liquid
|
|
34
|
+
{% comment %} ❌ Broken in dev — filename not resolved {% endcomment %}
|
|
35
|
+
<img src="{{ section.settings.panel_image.url }}">
|
|
36
|
+
|
|
37
|
+
{% comment %} ❌ Wrong filter — product CDN URL is not a theme asset {% endcomment %}
|
|
38
|
+
<img src="{{ product.featured_image.url | asset_url }}">
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
When the theme is **packaged and deployed**, the platform may resolve some paths differently — but **always write `asset_url` for theme assets**. One pattern works in dev and production.
|
|
42
|
+
|
|
43
|
+
## Safe image helper pattern
|
|
44
|
+
|
|
45
|
+
Keep it simple — no extra abstractions:
|
|
46
|
+
|
|
47
|
+
```liquid
|
|
48
|
+
{% liquid
|
|
49
|
+
assign img_url = section.settings.image.url
|
|
50
|
+
if img_url != blank
|
|
51
|
+
unless img_url contains '://'
|
|
52
|
+
assign img_url = img_url | asset_url
|
|
53
|
+
endunless
|
|
54
|
+
endif
|
|
55
|
+
%}
|
|
56
|
+
{% if img_url != blank %}
|
|
57
|
+
<img src="{{ img_url }}" alt="{{ section.settings.image.alt | escape }}" width="400" height="300" loading="lazy">
|
|
58
|
+
{% endif %}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Use this when a setting can be either a theme filename (dev/defaults) or a CDN URL (admin upload).
|
|
62
|
+
|
|
63
|
+
## Product / collection images (PDP, cards, cart)
|
|
64
|
+
|
|
65
|
+
```liquid
|
|
66
|
+
<img
|
|
67
|
+
src="{{ image.url }}?organization_id={{ organizationId }}"
|
|
68
|
+
alt="{{ product.title | escape }}"
|
|
69
|
+
width="{{ image.width | default: 400 }}"
|
|
70
|
+
height="{{ image.height | default: 400 }}"
|
|
71
|
+
loading="lazy"
|
|
72
|
+
>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Do not use `asset_url` for `product.images`, `product.media`, or `collection.image`.
|
|
76
|
+
|
|
77
|
+
## Visual verify checklist for images
|
|
78
|
+
|
|
79
|
+
During Chrome DevTools MCP visual compare, if Figma shows an image but the browser shows empty/broken:
|
|
80
|
+
|
|
81
|
+
1. `list_network_requests` — look for 404 on image URLs
|
|
82
|
+
2. Confirm `asset_url` is used for theme assets from JSON defaults
|
|
83
|
+
3. Confirm file exists in `assets/`
|
|
84
|
+
4. Confirm `pages/<page>.json` block settings reference the correct filename
|