@zohofinance/commerce 1.0.0 → 1.0.1
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 +61 -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 +127 -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,260 @@
|
|
|
1
|
+
# Stage 0 — Bootstrap
|
|
2
|
+
|
|
3
|
+
Serial, single agent, runs once at the start. ~30s budget.
|
|
4
|
+
|
|
5
|
+
**Read first:** `zcommerce-docs/theme-structure.md` (required folder layout, naming conventions) and `zcommerce-docs/setup-guide.md` (CLI commands, `?format=json` data inspection tip). The folder structure bootstrap creates must match exactly what these docs prescribe.
|
|
6
|
+
|
|
7
|
+
**Start the build clock** — write `.claude/scratchpad/<theme>/build-started.json`:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{ "theme": "<theme_name>", "started_at": "<ISO8601>", "figma_file_key": "<key>" }
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Ask developer for dev config** — before any browser work, collect `storeUrl` and confirm page URLs. Write `.claude/scratchpad/<theme>/dev-config.json`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"store_url": "",
|
|
18
|
+
"page_urls": {},
|
|
19
|
+
"confirmed_by_developer": false
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
See `dev-server-and-urls.md`. Do not navigate until `confirmed_by_developer` is true.
|
|
24
|
+
|
|
25
|
+
Stage 2 runs `record-build-metrics.mjs` against build-started.json. See `build-metrics.md`.
|
|
26
|
+
|
|
27
|
+
## Core principle
|
|
28
|
+
|
|
29
|
+
Bootstrap creates an **empty theme**. It does NOT copy any `.liquid` file, snippet, asset, image, or font from any existing theme. Every visual artefact in the finished theme is either:
|
|
30
|
+
|
|
31
|
+
1. Generated from the developer's guidelines frame (tokens), or
|
|
32
|
+
2. Extracted from the developer's per-page Figma frames (sections, assets), or
|
|
33
|
+
3. Written fresh by the page agents and the common-pages agent (Liquid markup, snippets) from the official docs — never copied from another theme.
|
|
34
|
+
|
|
35
|
+
There is no base theme to copy from. Agents build fresh code for this theme from the official ZCommerce docs (`zcommerce-docs/`).
|
|
36
|
+
|
|
37
|
+
## What bootstrap produces
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
<theme_name>/
|
|
41
|
+
assets/
|
|
42
|
+
fingerprint.json (empty {} — populated by agents from Figma assets)
|
|
43
|
+
main.css (Tailwind entry — @import theme-settings.css + @tailwind directives)
|
|
44
|
+
theme-settings.css (utility classes for tokens — sr-only, font-heading, etc.)
|
|
45
|
+
i18n/
|
|
46
|
+
en.json ({} — keys appended by agents during build)
|
|
47
|
+
en.schema.json ({} — keys appended by agents during build)
|
|
48
|
+
layouts/
|
|
49
|
+
theme.liquid (written fresh — see step 3)
|
|
50
|
+
accounts.liquid (written fresh — see step 3)
|
|
51
|
+
sitemap.liquid (written fresh — see step 3)
|
|
52
|
+
pages/ (empty — page JSONs written by page agents + common-pages agent)
|
|
53
|
+
sections/ (empty — section .liquid files written by agents)
|
|
54
|
+
snippets/ (empty — snippets written by agents when needed)
|
|
55
|
+
settings/
|
|
56
|
+
schema.json (generated from guidelines frame)
|
|
57
|
+
theme.json (generated from guidelines frame)
|
|
58
|
+
figma-variables.json (generated from guidelines frame)
|
|
59
|
+
tailwind.config.js (generated from guidelines frame)
|
|
60
|
+
postcss.config.js (generated from a standard template)
|
|
61
|
+
package.json (generated with new theme name)
|
|
62
|
+
project.json (generated with new theme name)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Steps
|
|
66
|
+
|
|
67
|
+
### 1. Validate inputs
|
|
68
|
+
|
|
69
|
+
- Theme name (snake-case, no existing folder with this name).
|
|
70
|
+
- `figma_file_key` from command (required for full theme build).
|
|
71
|
+
- Page map from **auto-discovery** (`figma-discovery.md`) — NOT from developer-pasted URLs unless discovery failed.
|
|
72
|
+
- Guidelines tokens from Guidelines frame inside the discovered file (see `inputs/guidelines-frame.md`).
|
|
73
|
+
|
|
74
|
+
If `figma_file_key` was provided, run discovery first. Only ask for page URLs when discovery fails. Never ask which theme to use as a template.
|
|
75
|
+
|
|
76
|
+
### 2. Create folder structure
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
THEME=<theme_name> # snake-case, e.g. orange_market
|
|
80
|
+
THEME_KEBAB="${THEME//_/-}"
|
|
81
|
+
|
|
82
|
+
mkdir -p $THEME/{assets,i18n,layouts,sections,snippets,settings,pages,thumbnail_images}
|
|
83
|
+
|
|
84
|
+
# Empty files that need to exist for the build pipeline
|
|
85
|
+
echo '{}' > $THEME/assets/fingerprint.json
|
|
86
|
+
echo '{}' > $THEME/i18n/en.json
|
|
87
|
+
echo '{}' > $THEME/i18n/en.schema.json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Notice: **no `cp` commands.** Bootstrap copies nothing from any theme.
|
|
91
|
+
|
|
92
|
+
### 3. Synthesize layout files
|
|
93
|
+
|
|
94
|
+
Layout files (`theme.liquid`, `accounts.liquid`, `sitemap.liquid`) are mostly identical across themes by convention — they're HTML wrappers that handle `<head>`, asset/font loading, the `content_for_*` hooks, and footer scripts.
|
|
95
|
+
|
|
96
|
+
Bootstrap synthesizes these by:
|
|
97
|
+
1. Reading `zcommerce-docs/layouts.md` for the required structure (what `content_for_header` / `content_for_layout` / `content_for_footer` do, where they must go).
|
|
98
|
+
2. Writing a fresh `layouts/theme.liquid` using the new theme's tokens (font preloads from `theme.json`, asset URLs via `asset_url` filter, semantic HTML).
|
|
99
|
+
|
|
100
|
+
The result must follow the documented layout conventions. The agent reads for *what content goes where* from the docs, not from any other theme file.
|
|
101
|
+
|
|
102
|
+
Same for `accounts.liquid` and `sitemap.liquid`.
|
|
103
|
+
|
|
104
|
+
### 4. Extract tokens from the guidelines frame
|
|
105
|
+
|
|
106
|
+
Follow `inputs/guidelines-frame.md` end to end:
|
|
107
|
+
1. Call `get_screenshot` on the guidelines node at `maxDimension: 2400` with `enableBase64Response: true`.
|
|
108
|
+
2. Read the rendered image with vision — extract fonts, colors, button states, component specs.
|
|
109
|
+
3. Map names to schema keys (PRIMARY → `color_primary`, BOARDER typo → `color_border`, etc.).
|
|
110
|
+
4. Derive on-colors via WCAG contrast math.
|
|
111
|
+
5. Write to `settings/theme.json`, `settings/schema.json`, `figma-variables.json`.
|
|
112
|
+
|
|
113
|
+
### 5. Generate tailwind.config.js
|
|
114
|
+
|
|
115
|
+
Write a fresh `tailwind.config.js` extending Tailwind with CSS variables for every token in `theme.json`:
|
|
116
|
+
- `theme.extend.colors.primary` → `var(--color-primary)` (and so on for each color)
|
|
117
|
+
- `theme.extend.spacing` for each space token
|
|
118
|
+
- `theme.extend.borderRadius` for each radius
|
|
119
|
+
- `theme.extend.fontFamily.heading` and `.body` from the guidelines frame
|
|
120
|
+
|
|
121
|
+
The content paths array must point at the new theme's directories (paths are relative to the theme root):
|
|
122
|
+
```js
|
|
123
|
+
content: [
|
|
124
|
+
'./pages/*.liquid',
|
|
125
|
+
'./sections/*.liquid',
|
|
126
|
+
'./snippets/*.liquid',
|
|
127
|
+
'./layouts/*.liquid',
|
|
128
|
+
'./assets/*.js',
|
|
129
|
+
],
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Use Tailwind v3 conventions (the project's standard).
|
|
133
|
+
|
|
134
|
+
### 6. Generate postcss.config.js, assets/main.css, package.json, project.json
|
|
135
|
+
|
|
136
|
+
Match the standard multi-theme pattern — do not use bare `npx @zohofinance/commerce` stubs.
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
// postcss.config.js
|
|
140
|
+
module.exports = {
|
|
141
|
+
plugins: { tailwindcss: {}, autoprefixer: {} },
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
```css
|
|
146
|
+
/* assets/main.css */
|
|
147
|
+
@import 'theme-settings.css';
|
|
148
|
+
|
|
149
|
+
@tailwind base;
|
|
150
|
+
@tailwind components;
|
|
151
|
+
@tailwind utilities;
|
|
152
|
+
|
|
153
|
+
html, body { height: 100%; display: flex; flex-direction: column; }
|
|
154
|
+
footer { margin-top: auto; }
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```css
|
|
158
|
+
/* assets/theme-settings.css — minimal utilities; agents may extend */
|
|
159
|
+
.font-heading { font-family: var(--font-heading); }
|
|
160
|
+
.font-body { font-family: var(--font-body); }
|
|
161
|
+
.max-w-container-theme { max-width: var(--page-width); }
|
|
162
|
+
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border-width: 0; }
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Naming convention:**
|
|
166
|
+
- `package.json` → `"name": "<theme_name>"` (snake_case folder name, e.g. `my_theme`)
|
|
167
|
+
- `project.json` → `"name": "<theme-kebab>"` (underscores → hyphens, e.g. `my-theme`)
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
// package.json — replace <theme_name> with the folder name
|
|
171
|
+
{
|
|
172
|
+
"name": "<theme_name>",
|
|
173
|
+
"version": "1.0.0",
|
|
174
|
+
"type": "module",
|
|
175
|
+
"zcommerce": {
|
|
176
|
+
"thumbnail_images": {
|
|
177
|
+
"desktop_image": "thumbnail_images/desktop.png",
|
|
178
|
+
"mobile_image": "thumbnail_images/mobile.png"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"scripts": {
|
|
182
|
+
"prebuild:dev": "tailwindcss -i ./assets/main.css -o ./assets/style.css",
|
|
183
|
+
"dev": "yarn prebuild:dev && npx @zohofinance/commerce theme dev",
|
|
184
|
+
"build": "npx @zohofinance/commerce theme build"
|
|
185
|
+
},
|
|
186
|
+
"dependencies": {
|
|
187
|
+
"@tailwindcss/typography": "^0.5.16",
|
|
188
|
+
"@zohofinance/commerce": "latest",
|
|
189
|
+
"postcss": "^8.4.38"
|
|
190
|
+
},
|
|
191
|
+
"devDependencies": {
|
|
192
|
+
"autoprefixer": "^10.4.19",
|
|
193
|
+
"tailwindcss": "^3.4.3"
|
|
194
|
+
},
|
|
195
|
+
"volta": {
|
|
196
|
+
"node": "18.20.4",
|
|
197
|
+
"yarn": "1.22.10"
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Also create `thumbnail_images/` (empty — designer adds desktop.png / mobile.png before deploy).
|
|
203
|
+
|
|
204
|
+
### 7. Hard assertions before handing off
|
|
205
|
+
|
|
206
|
+
Bootstrap MUST exit with `FATAL` if any of these are violated:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# No .liquid files copied from anywhere
|
|
210
|
+
test "$(find $THEME -name '*.liquid' -not -path '*/layouts/*' | wc -l)" -eq 0 || \
|
|
211
|
+
{ echo "FATAL: .liquid files exist outside layouts/ — bootstrap should not create sections/snippets" >&2; exit 1; }
|
|
212
|
+
|
|
213
|
+
# layouts/ has exactly the three expected files
|
|
214
|
+
test "$(ls $THEME/layouts/ | wc -l)" -eq 3 || \
|
|
215
|
+
{ echo "FATAL: layouts/ should contain exactly theme.liquid, accounts.liquid, sitemap.liquid" >&2; exit 1; }
|
|
216
|
+
|
|
217
|
+
# assets/ has only bootstrap stubs (no images/fonts copied from sibling themes)
|
|
218
|
+
ALLOWED_ASSETS='^(fingerprint\.json|main\.css|theme-settings\.css)$'
|
|
219
|
+
test "$(ls $THEME/assets/ | grep -Ev "$ALLOWED_ASSETS" | wc -l)" -eq 0 || \
|
|
220
|
+
{ echo "FATAL: assets/ should only contain fingerprint.json, main.css, theme-settings.css at bootstrap" >&2; ls $THEME/assets/; exit 1; }
|
|
221
|
+
|
|
222
|
+
# pages/ is empty (page agents create them)
|
|
223
|
+
test "$(ls $THEME/pages/ 2>/dev/null | wc -l)" -eq 0 || \
|
|
224
|
+
{ echo "FATAL: pages/ should be empty after bootstrap" >&2; exit 1; }
|
|
225
|
+
|
|
226
|
+
# project.json + package.json have the new name (package = folder, project = kebab)
|
|
227
|
+
grep -q "\"name\": \"$THEME\"" $THEME/package.json || \
|
|
228
|
+
{ echo "FATAL: package.json name must be $THEME" >&2; exit 1; }
|
|
229
|
+
grep -q "\"name\": \"$THEME_KEBAB\"" $THEME/project.json || \
|
|
230
|
+
{ echo "FATAL: project.json name must be $THEME_KEBAB" >&2; exit 1; }
|
|
231
|
+
|
|
232
|
+
# Tailwind entry exists
|
|
233
|
+
test -f $THEME/assets/main.css || \
|
|
234
|
+
{ echo "FATAL: assets/main.css missing" >&2; exit 1; }
|
|
235
|
+
|
|
236
|
+
# theme.json reflects guidelines frame tokens (sanity-check primary is set)
|
|
237
|
+
python3 -c "import json; d=json.load(open('$THEME/settings/theme.json')); assert d['presets']['default']['color_primary'].startswith('#'), 'primary color not set'" \
|
|
238
|
+
|| { echo "FATAL: theme.json tokens not populated from guidelines frame" >&2; exit 1; }
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 8. Emit a stage-0 report
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
Stage 0 — Bootstrap complete (32s)
|
|
245
|
+
├─ theme: orange_market
|
|
246
|
+
├─ folders created: 8 (all empty except config + tokens)
|
|
247
|
+
├─ tokens: 47 extracted from guidelines frame
|
|
248
|
+
├─ layouts: 3 written fresh (synthesized from docs)
|
|
249
|
+
├─ tailwind.config.js + theme.json + figma-variables.json generated
|
|
250
|
+
└─ pages/, sections/, snippets/, assets/ all empty — agents build them
|
|
251
|
+
|
|
252
|
+
Next: stage 1 — index agent (builds header + footer + index sections)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Failure modes
|
|
256
|
+
|
|
257
|
+
- **Guidelines frame URL missing or unreadable** → ask developer once. Without the guidelines frame, the skill cannot produce a theme.
|
|
258
|
+
- **Theme name already exists** → ask whether to overwrite. Never silently overwrite — the developer might lose work.
|
|
259
|
+
- **Sandbox can't reach Figma** → fall back to base64 mode for screenshots, surface specific assets the developer needs to export manually.
|
|
260
|
+
- **Hex codes unreadable in the guidelines screenshot** → re-render at `maxDimension: 3600`. If still unreadable, ask developer for the hex values once.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Build metrics — mandatory end-of-run report
|
|
2
|
+
|
|
3
|
+
Every `/build-theme` run MUST end with a metrics block in `.claude/scratchpad/<theme>/report.md`.
|
|
4
|
+
|
|
5
|
+
## Record start time (Stage 0)
|
|
6
|
+
|
|
7
|
+
At bootstrap, write:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
// .claude/scratchpad/<theme>/build-started.json
|
|
11
|
+
{
|
|
12
|
+
"theme": "<theme_name>",
|
|
13
|
+
"started_at": "2026-06-10T14:32:00.000Z",
|
|
14
|
+
"figma_file_key": "<figma_file_key>"
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Collect metrics (Stage 2)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
node .claude/skills/theme-from-figma/scripts/record-build-metrics.mjs <theme_name>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Paste the script output into `report.md` under `## Build metrics`.
|
|
25
|
+
|
|
26
|
+
## Report template (append to report.md)
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
## Build metrics
|
|
30
|
+
|
|
31
|
+
| Metric | Value |
|
|
32
|
+
|---|---|
|
|
33
|
+
| Wall-clock duration | 42m 18s |
|
|
34
|
+
| Bootstrap | 28s |
|
|
35
|
+
| Page builds (parallel) | 38m 52s (slowest: product) |
|
|
36
|
+
| Consolidation | 2m 58s |
|
|
37
|
+
| Sections built | 23 |
|
|
38
|
+
| Snippets built | 14 |
|
|
39
|
+
| Visual verify loops | 31 (avg 1.4 iterations/section) |
|
|
40
|
+
| Sections with 0 CRITICAL after verify | 21/23 |
|
|
41
|
+
| Pages visually verified (desktop+mobile) | 5/5 |
|
|
42
|
+
| Lighthouse a11y (pages) | 5 pass / 0 fail |
|
|
43
|
+
| Lighthouse perf mobile (pages) | avg 91 |
|
|
44
|
+
| Lint failures fixed during build | 6 |
|
|
45
|
+
| verify-theme.mjs | PASS / FAIL |
|
|
46
|
+
|
|
47
|
+
### Token estimate (approximate)
|
|
48
|
+
|
|
49
|
+
Cursor does not expose per-run token counts to agents. Provide a **range estimate** based on run complexity:
|
|
50
|
+
|
|
51
|
+
| Build profile | Typical agent turns | Approx. tokens |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| Small theme (≤15 sections, 1 iteration each) | 80–120 | 800K–1.5M |
|
|
54
|
+
| Medium theme (20–30 sections, 1–2 iterations) | 150–250 | 1.5M–3M |
|
|
55
|
+
| Large theme (30+ sections, visual re-loops) | 250–400+ | 3M–6M+ |
|
|
56
|
+
|
|
57
|
+
Record what you observe:
|
|
58
|
+
- **Estimated input tokens:** ~2.8M (based on 5 page orchestrators + 23 section subagents + consolidation)
|
|
59
|
+
- **Estimated output tokens:** ~420K
|
|
60
|
+
- **Confidence:** low / medium / high
|
|
61
|
+
|
|
62
|
+
Factors that increase cost: visual re-loops (>2 per section), stalled subagents, whole-page fixes, large Figma frames.
|
|
63
|
+
|
|
64
|
+
### Cost / time insights for developers
|
|
65
|
+
|
|
66
|
+
- **Parallel page agents** save wall-clock (~5× vs serial) but do not reduce total tokens.
|
|
67
|
+
- **Per-section Chrome DevTools verify** is the highest-ROI step for Figma fidelity — skipping it is why output drifted.
|
|
68
|
+
- **First-time builds** average 35–60 min wall-clock for a 5-page theme.
|
|
69
|
+
- **Re-runs** on a single page after feedback: 5–15 min.
|
|
70
|
+
|
|
71
|
+
### Per-page breakdown
|
|
72
|
+
|
|
73
|
+
| Page | Sections | Wall time | Visual iters | CRITICAL remaining |
|
|
74
|
+
|---|---|---|---|---|
|
|
75
|
+
| index | 8 | 12m 04s | 9 | 0 |
|
|
76
|
+
| product | 2 | 8m 22s | 4 | 0 |
|
|
77
|
+
| collection | 2 | 6m 15s | 3 | 0 |
|
|
78
|
+
| blog_list | 2 | 4m 48s | 2 | 0 |
|
|
79
|
+
| blog_detail | 2 | 5m 10s | 2 | 0 |
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Who writes what
|
|
83
|
+
|
|
84
|
+
| Agent | Writes |
|
|
85
|
+
|---|---|
|
|
86
|
+
| Bootstrap (Stage 0) | `build-started.json` |
|
|
87
|
+
| Section subagent | `pages/<page>/sections/<section>/visual-diff.md` with iteration count |
|
|
88
|
+
| Page orchestrator | `pages/<page>/report.md` with page wall time |
|
|
89
|
+
| Consolidator (Stage 2) | Runs `record-build-metrics.mjs`, final `report.md` |
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Code quality — strict budgets, enforced at write time
|
|
2
|
+
|
|
3
|
+
The single biggest source of past iterations was AI-generated code being structurally heavier than necessary. This document defines hard budgets and the write-time lint that enforces them. **The lint script (`scripts/lint-section.mjs`) is the source of truth — these rules describe what it checks.**
|
|
4
|
+
|
|
5
|
+
**Read also:** `zcommerce-docs/best-practices.md` — the official ZCommerce best-practices doc covering performance (minify, defer JS, async, preload), security (escape user output, avoid inline scripts from settings, use `json` filter for data), and accessibility (semantic HTML, alt text, form labels, heading hierarchy). The lint catches the syntactic violations of these rules; the doc explains the reasoning.
|
|
6
|
+
|
|
7
|
+
## Budgets (calibrated to existing exemplars)
|
|
8
|
+
|
|
9
|
+
| Metric | Budget | Why | Exemplar reference |
|
|
10
|
+
|---|---:|---|---|
|
|
11
|
+
| Tailwind utility classes per element | **≤ 12** | More than ~12 = unreadable class soup; extract to `{% style %}` block. | hero-banner.liquid (max 14 was top of range; we tighten to 12). |
|
|
12
|
+
| DOM nesting depth per section | **≤ 6** | Anything deeper indicates redundant wrappers. | All exemplars are 3–6. |
|
|
13
|
+
| Section file total lines | **≤ 250** | Section files over ~250 lines should be split into snippets. | Largest exemplar is 238 (blog-list); typical 80–170. |
|
|
14
|
+
| Empty wrapper `<div>`s | **0** | A wrapper that contains a single element with no layout role is removable. | All exemplars have zero. |
|
|
15
|
+
| `{% if %}` nesting depth | **≤ 2** | Three-deep `if` chains indicate a `case` is needed. | Exemplars use `case` for branching. |
|
|
16
|
+
| Top-level `{% liquid %}` block | **1** | All `assign`s in one block at the top, not scattered. | Standard hero-banner pattern across themes. |
|
|
17
|
+
| Inline `onclick=` / `onload=` etc. | **0** | All JS via `data-*` + external script. | CLAUDE.md rule. |
|
|
18
|
+
| Hardcoded hex colors | **0** | Always a theme token. | CLAUDE.md rule. |
|
|
19
|
+
| Hardcoded px font-size in inline `style=` | **0** | Use Tailwind class or `{% style %}` block. | CLAUDE.md rule. |
|
|
20
|
+
| Schema fields not wired to markup | **0** | Every `id` in `{% schema %}` settings is referenced by the markup. | The most common build error. |
|
|
21
|
+
| `rounded-*` without spec radius | **0** | Only if `figma-spec.json` has `border_radius > 0` for that element. | `transcription-rules.md` |
|
|
22
|
+
| Product grid images without fixed media box | **flag** | Cards must use spec `w`×`h` + `object-fit` — not natural img height. | Uneven card heights bug |
|
|
23
|
+
|
|
24
|
+
## Soft signals (warn, don't block)
|
|
25
|
+
|
|
26
|
+
| Signal | Threshold | Comment |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| Sections that look like header/footer | should never go to `sections/header.liquid` etc — those are locked | If you find yourself wanting to write header content, you took the wrong work. |
|
|
29
|
+
| Use of arbitrary Tailwind values `text-[19px]` | > 3 per section | Means the design isn't on the token grid. Consider adding a token. |
|
|
30
|
+
| `<div>` to `<div class="...">` ratio | > 30% bare divs | Likely missing semantic elements (`<section>`, `<article>`, `<nav>`). |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Pre-write checklist (run mentally before writing each section file)
|
|
35
|
+
|
|
36
|
+
The agent must answer each before writing:
|
|
37
|
+
|
|
38
|
+
1. **Anchor exemplar identified?** What's the closest match in `exemplars.md` and what are its metrics?
|
|
39
|
+
2. **Element count?** Roughly how many DOM elements will this section have? If > 1.5× the exemplar's, why?
|
|
40
|
+
3. **Max class count per element?** Mentally count classes on the most-styled element. If > 12, plan to move them to `{% style %}`.
|
|
41
|
+
4. **DOM depth?** Sketch the hierarchy. If > 6 levels deep, identify the redundant wrappers.
|
|
42
|
+
5. **Schema field count?** List the fields you'll define. For each, where will it appear in markup?
|
|
43
|
+
6. **Liquid logic complexity?** Any `if` inside `if` inside `for`? Refactor before writing.
|
|
44
|
+
|
|
45
|
+
If any answer is suspicious, **re-plan, don't write**. Bad code is harder to delete than to never write.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Write-time lint (run by the agent after writing each section, automated)
|
|
50
|
+
|
|
51
|
+
The agent runs:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
node .claude/skills/theme-from-figma/scripts/lint-section.mjs \
|
|
55
|
+
sections/<section_name>.liquid
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The script outputs a JSON report:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"file": "lush_market/sections/hero-banner.liquid",
|
|
63
|
+
"lines": 98,
|
|
64
|
+
"checks": {
|
|
65
|
+
"lines_under_250": { "pass": true, "actual": 98 },
|
|
66
|
+
"max_classes_per_el": { "pass": true, "actual": 11, "budget": 12, "elementHint": "<a class=\"...\">" },
|
|
67
|
+
"max_dom_depth": { "pass": true, "actual": 5, "budget": 6 },
|
|
68
|
+
"empty_wrappers": { "pass": true, "count": 0 },
|
|
69
|
+
"if_nesting_depth": { "pass": true, "actual": 1, "budget": 2 },
|
|
70
|
+
"single_liquid_block": { "pass": true, "actual": 1 },
|
|
71
|
+
"inline_event_handlers":{ "pass": true, "count": 0 },
|
|
72
|
+
"hardcoded_hex": { "pass": true, "count": 0 },
|
|
73
|
+
"hardcoded_inline_px": { "pass": true, "count": 0 },
|
|
74
|
+
"schema_fields_wired": { "pass": false, "unused": ["unused_subtext"], "wired": 8, "total": 9 },
|
|
75
|
+
"render_not_include": { "pass": true, "count_include": 0 },
|
|
76
|
+
"escape_user_output": { "pass": true, "warnings": [] }
|
|
77
|
+
},
|
|
78
|
+
"verdict": "FAIL"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If `verdict === "FAIL"`, the agent **must fix** before continuing. The agent is not allowed to silence a check.
|
|
83
|
+
|
|
84
|
+
## Common rejections and how to fix
|
|
85
|
+
|
|
86
|
+
### `max_classes_per_el` failure
|
|
87
|
+
|
|
88
|
+
The lint shows the offending element. Move repeating utility classes into a `{% style %}` block:
|
|
89
|
+
|
|
90
|
+
```liquid
|
|
91
|
+
<!-- BEFORE: 18 classes -->
|
|
92
|
+
<a class="inline-flex items-center justify-center px-theme-8 py-theme-3 bg-primary text-on-primary font-semibold rounded-theme-button hover:bg-primary-hover focus:ring-2 focus:ring-offset-2 transition-colors text-base md:text-lg">
|
|
93
|
+
{{ block.settings.button_label }}
|
|
94
|
+
</a>
|
|
95
|
+
|
|
96
|
+
<!-- AFTER: 1 class, 1 attribute -->
|
|
97
|
+
<a class="cta-btn" href="{{ block.settings.button_link.handle }}">{{ block.settings.button_label }}</a>
|
|
98
|
+
|
|
99
|
+
{% style %}
|
|
100
|
+
#section-{{ section.id }} .cta-btn {
|
|
101
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
102
|
+
padding: var(--space-3) var(--space-8);
|
|
103
|
+
background: var(--color-primary); color: var(--color-on-primary);
|
|
104
|
+
font-weight: 600; border-radius: var(--radius-button);
|
|
105
|
+
transition: background 0.15s ease;
|
|
106
|
+
}
|
|
107
|
+
#section-{{ section.id }} .cta-btn:hover { background: var(--color-accent); }
|
|
108
|
+
{% endstyle %}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `max_dom_depth` failure
|
|
112
|
+
|
|
113
|
+
Walk the tree and find redundant wrappers:
|
|
114
|
+
|
|
115
|
+
```liquid
|
|
116
|
+
<!-- BEFORE: depth 8 -->
|
|
117
|
+
<section>
|
|
118
|
+
<div>
|
|
119
|
+
<div class="container">
|
|
120
|
+
<div class="row">
|
|
121
|
+
<div class="col">
|
|
122
|
+
<div class="card">
|
|
123
|
+
<div class="card-body">
|
|
124
|
+
<h2>...</h2>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</section>
|
|
132
|
+
|
|
133
|
+
<!-- AFTER: depth 4 -->
|
|
134
|
+
<section id="section-{{ section.id }}" class="hero-section">
|
|
135
|
+
<div class="max-w-container-theme mx-auto px-theme-4">
|
|
136
|
+
<article class="hero-card">
|
|
137
|
+
<h2>...</h2>
|
|
138
|
+
</article>
|
|
139
|
+
</div>
|
|
140
|
+
</section>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### `empty_wrappers` failure
|
|
144
|
+
|
|
145
|
+
A `<div>` whose only child is another single element with no layout role:
|
|
146
|
+
|
|
147
|
+
```liquid
|
|
148
|
+
<!-- BEFORE -->
|
|
149
|
+
<div>
|
|
150
|
+
<div class="text-center">
|
|
151
|
+
<h2>{{ heading }}</h2>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<!-- AFTER -->
|
|
156
|
+
<h2 class="text-center">{{ heading }}</h2>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `schema_fields_wired` failure
|
|
160
|
+
|
|
161
|
+
The schema declares a setting but the markup never references it. Either wire it or remove it:
|
|
162
|
+
|
|
163
|
+
```liquid
|
|
164
|
+
{% schema %}
|
|
165
|
+
{
|
|
166
|
+
"settings": [
|
|
167
|
+
{ "type": "text", "id": "heading", "default": "..." },
|
|
168
|
+
{ "type": "text", "id": "subheading", "default": "..." } ← never referenced!
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
{% endschema %}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Remove `subheading` from the schema, or add `{{ section.settings.subheading }}` somewhere.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## What the lint does NOT check
|
|
179
|
+
|
|
180
|
+
- Visual fidelity → that's the pixel-diff gate (`verification.md`).
|
|
181
|
+
- Accessibility violations → that's the a11y gate.
|
|
182
|
+
- Performance → that's the perf gate.
|
|
183
|
+
- Semantic correctness (does `<article>` make sense here?) → human judgment.
|
|
184
|
+
- Typos in copy → not the lint's job.
|
|
185
|
+
|
|
186
|
+
The lint exists for structural code quality. The four gates exist for behavioral correctness. Both layers run.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Common-pages agent (Stage 1c)
|
|
2
|
+
|
|
3
|
+
While the index agent and four parallel page agents build the Figma-driven pages, a sixth agent handles the **common pages** that have no Figma: cart, checkout, account flows, 404, signin, signup, forgotpassword, custom-page, payment, sitemap, orders.
|
|
4
|
+
|
|
5
|
+
These pages exist in every theme but don't have per-theme designs in the input. The agent's job: read multiple themes' implementations to learn the LOGIC, then write fresh code that applies the new theme's tokens.
|
|
6
|
+
|
|
7
|
+
## Why a separate agent
|
|
8
|
+
|
|
9
|
+
Common pages have business logic (cart calculations, checkout steps, account form validation) that the index/page agents don't need to know. Isolating them in one agent:
|
|
10
|
+
1. Keeps the page agents focused on Figma-driven sections.
|
|
11
|
+
2. Lets the common-pages agent specialize in reading across many themes for any one archetype.
|
|
12
|
+
3. Allows parallel work — common-pages agent runs alongside the page agents.
|
|
13
|
+
|
|
14
|
+
## When it runs
|
|
15
|
+
|
|
16
|
+
Stage 1c runs **in parallel with** Stage 1b (the four page agents that wait for the header-footer-ready marker). It does NOT wait for the marker because the common pages don't render the header/footer during the agent's own per-section verification (those layouts wrap them, but per-section gates use just the section's HTML).
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Stage 1a: index agent (header + footer + index sections) ████████████ ~4min
|
|
20
|
+
Stage 1b: listing ─────────────████ ~3min
|
|
21
|
+
product ─────────────█████ ~5min
|
|
22
|
+
blog_list ─────────────███ ~2min
|
|
23
|
+
blog_detail ─────────────███ ~2min
|
|
24
|
+
Stage 1c: common-pages agent (cart, checkout, etc.) ─────────████████ ~5min
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Inputs
|
|
28
|
+
|
|
29
|
+
From the orchestrator:
|
|
30
|
+
- Theme folder path.
|
|
31
|
+
- Scratchpad path at `.claude/scratchpad/<theme>/common-pages/`.
|
|
32
|
+
- Locked files: `theme.json`, `tailwind.config.js`, `figma-variables.json` (no header/footer lock — they don't exist yet when this agent starts; the agent waits for the header-footer-ready marker before its own per-page verification step, not before writing).
|
|
33
|
+
|
|
34
|
+
## Pages it owns
|
|
35
|
+
|
|
36
|
+
| Page route | Page JSON | Section files this agent writes |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `/cart` | `pages/cart.json` | `cart-list.liquid`, `cart-popup.liquid`, `cart-empty.liquid` snippet |
|
|
39
|
+
| `/checkout` | `pages/checkout.json` | `checkout.liquid` + `checkout-steps.liquid` snippet |
|
|
40
|
+
| `/account/profile` | `pages/account-profile.json` | `account-profile.liquid` + `account-tab-navigation.liquid` |
|
|
41
|
+
| `/account/address` | `pages/account-address.json` | `account-address.liquid` + `account-address-card.liquid` snippet |
|
|
42
|
+
| `/account/orders` | `pages/account-order.json` | `account-order.liquid` |
|
|
43
|
+
| `/account/order/<id>` | `pages/account-order-detail.json` | `accounts-order-details.liquid` |
|
|
44
|
+
| `/account/order/<id>/status` | `pages/account-order-status.json` | `account-order-status.liquid` |
|
|
45
|
+
| `/orders` | `pages/orders.json` | `orders.liquid` |
|
|
46
|
+
| `/payment/<status>` | `pages/payment.json` | (status sections) |
|
|
47
|
+
| `/signin` | `pages/signin.json` | `signin.liquid` |
|
|
48
|
+
| `/signup` | `pages/signup.json` | `signup.liquid` |
|
|
49
|
+
| `/forgotpassword` | `pages/forgotpassword.json` | `forgotpassword.liquid` |
|
|
50
|
+
| `/404` | `pages/404.json` | `404.liquid` |
|
|
51
|
+
| `/page/<slug>` | `pages/page.json` | `page.liquid` |
|
|
52
|
+
| `/sitemap` | `pages/sitemap.json` | (uses `layouts/sitemap.liquid`) |
|
|
53
|
+
|
|
54
|
+
## Workflow per archetype
|
|
55
|
+
|
|
56
|
+
For each archetype above:
|
|
57
|
+
|
|
58
|
+
1. **Explore.** Read every theme's implementation of this archetype (per `exemplars.md` § "Archetype → candidate themes"). Read minimum three; ideally all that have one.
|
|
59
|
+
2. **Synthesize logic.** Identify common patterns:
|
|
60
|
+
- Cart: line-item rendering, quantity controls, totals, coupon, checkout CTA, empty state.
|
|
61
|
+
- Checkout: step navigation, address forms, shipping/payment selection, order summary.
|
|
62
|
+
- Account: tabbed nav, form fields per page, edit/save states.
|
|
63
|
+
3. **Plan fresh markup.** Sketch DOM, schema fields, snippet decomposition. Apply the new theme's tokens (`var(--color-*)`, `var(--space-*)`, `var(--radius-*)`, `var(--font-*)`).
|
|
64
|
+
4. **Write fresh.** Each section file goes through the same lint as page agents (`lint-section.mjs`). All lint rules apply — i18n keys, tag validity, filter validity, scope sanity, no hardcoded design.
|
|
65
|
+
5. **Update page JSON.** Wire the new section into the corresponding `pages/<page>.json`.
|
|
66
|
+
6. **Append translation keys.** Runtime keys to `en.json`, schema labels to `en.schema.json`.
|
|
67
|
+
7. **Per-page verify.** Once header/footer-ready marker exists, run the gates against each common page:
|
|
68
|
+
- Pixel-diff: **no Figma to compare against**. Skip this gate for common pages, OR compare against a deterministic baseline (the same rendered page after a no-op rebuild — sanity check, not pixel-accuracy).
|
|
69
|
+
- a11y: MANDATORY. Axe must pass on every common page.
|
|
70
|
+
- Lighthouse: MANDATORY. Perf score ≥ 85 mobile.
|
|
71
|
+
8. **Iterate** up to 3 passes per page on a11y or perf failures.
|
|
72
|
+
9. **Report.**
|
|
73
|
+
|
|
74
|
+
## Hard rules
|
|
75
|
+
|
|
76
|
+
- **No `cp` from any theme.** Every line typed fresh.
|
|
77
|
+
- **Read every available implementation** before writing. If you find yourself ready to write after reading only one, stop and read more.
|
|
78
|
+
- **Common pages use the same design tokens as Figma-driven pages.** The cart on the orange theme has orange CTAs, Lato body font, Oswald headings — derived from `theme.json`, not from any sibling theme's cart styling.
|
|
79
|
+
- **Snippets shared between common pages and page-agent pages** (like `pagination`, `product-card` if cart uses it) — coordinate via filename. If the common-pages agent needs `product-card`, it writes a fresh version OR waits for the listing/product agent (whichever finishes first) and uses theirs. The orchestrator coordinates this by giving the common-pages agent visibility into which snippets the other agents are writing.
|
|
80
|
+
|
|
81
|
+
## Output
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
PAGE: cart ✓ 1m22s (3 sections, lint pass, axe pass, perf 91)
|
|
85
|
+
PAGE: checkout ✓ 2m05s (1 section + checkout-steps snippet, all gates pass)
|
|
86
|
+
PAGE: account-profile ✓ 0m48s (1 section + account-tab-navigation, all gates pass)
|
|
87
|
+
PAGE: account-address ✓ 0m45s
|
|
88
|
+
PAGE: account-order ✓ 0m32s
|
|
89
|
+
... (etc for all common pages)
|
|
90
|
+
|
|
91
|
+
SECTIONS WRITTEN: 14
|
|
92
|
+
SNIPPETS WRITTEN: 6
|
|
93
|
+
ITERATIONS: 2 (one a11y fix on checkout, one perf fix on account-order)
|
|
94
|
+
|
|
95
|
+
NEEDS_REVIEW:
|
|
96
|
+
- checkout/checkout-steps: stepper accent contrast 4.5:1 at WCAG AA minimum
|
|
97
|
+
```
|