@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.
Files changed (127) hide show
  1. package/README.md +61 -0
  2. package/package.json +2 -2
  3. package/ts-dist/mocks/init-theme/.claude/CLAUDE.md +6 -0
  4. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/SKILL.md +242 -0
  5. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/figma.md +81 -0
  6. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/screenshot.md +54 -0
  7. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/url.md +88 -0
  8. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/spec-table.md +102 -0
  9. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/accessibility.md +110 -0
  10. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/performance.md +127 -0
  11. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/tokens.md +87 -0
  12. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/visual-diff.md +123 -0
  13. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/SKILL.md +605 -0
  14. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/design-tokens.md +105 -0
  15. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/page-json-contract.md +58 -0
  16. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/qa-accessibility.md +35 -0
  17. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/reference-lookup.md +94 -0
  18. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/section-anatomy.md +109 -0
  19. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/SKILL.md +313 -0
  20. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/agent-hierarchy.md +142 -0
  21. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/ask-developer.md +113 -0
  22. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/bootstrap.md +260 -0
  23. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/build-metrics.md +89 -0
  24. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/code-quality.md +186 -0
  25. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/common-pages-agent.md +97 -0
  26. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/dev-server-and-urls.md +127 -0
  27. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/exemplars.md +79 -0
  28. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-discovery.md +138 -0
  29. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-extraction.md +132 -0
  30. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/image-sources.md +84 -0
  31. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/inputs/guidelines-frame.md +178 -0
  32. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-builder.md +322 -0
  33. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-orchestrator.md +199 -0
  34. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/parallel-fanout.md +152 -0
  35. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/a11y.mjs +129 -0
  36. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/lint-section.mjs +502 -0
  37. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/perf.mjs +134 -0
  38. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/pixel-diff.mjs +206 -0
  39. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/record-build-metrics.mjs +118 -0
  40. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/section-builder.md +131 -0
  41. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/subagent-escalation.md +75 -0
  42. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/transcription-rules.md +98 -0
  43. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/verification.md +227 -0
  44. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/visual-verify-loop.md +117 -0
  45. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/_index.md +4 -0
  46. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/assets.md +105 -0
  47. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/best-practices.md +212 -0
  48. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/custom-scripts.md +294 -0
  49. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/i18n.md +155 -0
  50. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/introduction.md +91 -0
  51. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/layouts.md +158 -0
  52. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/pages.md +156 -0
  53. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/_index.md +4 -0
  54. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/filters.md +419 -0
  55. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/global-objects.md +415 -0
  56. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/schema-types.md +926 -0
  57. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/tags.md +259 -0
  58. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/sections.md +203 -0
  59. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/setup-guide.md +424 -0
  60. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/snippets.md +70 -0
  61. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/theme-structure.md +252 -0
  62. package/ts-dist/mocks/init-theme/.cursor/PLAYBOOK.md +144 -0
  63. package/ts-dist/mocks/init-theme/.cursor/README.md +6 -0
  64. package/ts-dist/mocks/init-theme/.cursor/agents/figma-desktop-mobile-parallel.md +48 -0
  65. package/ts-dist/mocks/init-theme/.cursor/agents/visual-compare.md +221 -0
  66. package/ts-dist/mocks/init-theme/.cursor/commands/add-field.md +83 -0
  67. package/ts-dist/mocks/init-theme/.cursor/commands/add-theme-setting.md +200 -0
  68. package/ts-dist/mocks/init-theme/.cursor/commands/assemble-page.md +72 -0
  69. package/ts-dist/mocks/init-theme/.cursor/commands/audit-page.md +57 -0
  70. package/ts-dist/mocks/init-theme/.cursor/commands/build-page-sections.md +110 -0
  71. package/ts-dist/mocks/init-theme/.cursor/commands/build-section.md +418 -0
  72. package/ts-dist/mocks/init-theme/.cursor/commands/build-theme.md +307 -0
  73. package/ts-dist/mocks/init-theme/.cursor/commands/compare-section.md +358 -0
  74. package/ts-dist/mocks/init-theme/.cursor/commands/create-theme.md +77 -0
  75. package/ts-dist/mocks/init-theme/.cursor/commands/extract-tokens.md +43 -0
  76. package/ts-dist/mocks/init-theme/.cursor/commands/fix-section.md +92 -0
  77. package/ts-dist/mocks/init-theme/.cursor/commands/impact.md +50 -0
  78. package/ts-dist/mocks/init-theme/.cursor/commands/qa-a11y.md +66 -0
  79. package/ts-dist/mocks/init-theme/.cursor/commands/qa-i18n.md +110 -0
  80. package/ts-dist/mocks/init-theme/.cursor/commands/qa-layout.md +127 -0
  81. package/ts-dist/mocks/init-theme/.cursor/commands/qa-performance.md +72 -0
  82. package/ts-dist/mocks/init-theme/.cursor/commands/qa-section.md +84 -0
  83. package/ts-dist/mocks/init-theme/.cursor/commands/qa-sections.md +48 -0
  84. package/ts-dist/mocks/init-theme/.cursor/commands/qa-theme.md +85 -0
  85. package/ts-dist/mocks/init-theme/.cursor/commands/redesign-section.md +177 -0
  86. package/ts-dist/mocks/init-theme/.cursor/commands/refactor-section.md +185 -0
  87. package/ts-dist/mocks/init-theme/.cursor/commands/sync-theme-settings.md +132 -0
  88. package/ts-dist/mocks/init-theme/.cursor/commands/validate-page.md +60 -0
  89. package/ts-dist/mocks/init-theme/.cursor/commands/validate-section-group.md +88 -0
  90. package/ts-dist/mocks/init-theme/.cursor/commands/validate-theme-settings.md +119 -0
  91. package/ts-dist/mocks/init-theme/.cursor/examples/design-instructions-template.md +151 -0
  92. package/ts-dist/mocks/init-theme/.cursor/mcp.json +18 -0
  93. package/ts-dist/mocks/init-theme/.cursor/rules/README.md +160 -0
  94. package/ts-dist/mocks/init-theme/.cursor/rules/accessibility.mdc +24 -0
  95. package/ts-dist/mocks/init-theme/.cursor/rules/add-field.mdc +222 -0
  96. package/ts-dist/mocks/init-theme/.cursor/rules/add-theme-setting.mdc +39 -0
  97. package/ts-dist/mocks/init-theme/.cursor/rules/assemble-page.mdc +130 -0
  98. package/ts-dist/mocks/init-theme/.cursor/rules/audit-page.mdc +92 -0
  99. package/ts-dist/mocks/init-theme/.cursor/rules/build-section.mdc +178 -0
  100. package/ts-dist/mocks/init-theme/.cursor/rules/build-theme.mdc +47 -0
  101. package/ts-dist/mocks/init-theme/.cursor/rules/compare-section.mdc +94 -0
  102. package/ts-dist/mocks/init-theme/.cursor/rules/create-theme.mdc +78 -0
  103. package/ts-dist/mocks/init-theme/.cursor/rules/css.mdc +137 -0
  104. package/ts-dist/mocks/init-theme/.cursor/rules/design-spec-extraction.mdc +255 -0
  105. package/ts-dist/mocks/init-theme/.cursor/rules/extract-tokens.mdc +43 -0
  106. package/ts-dist/mocks/init-theme/.cursor/rules/figma-mcp-resolution.mdc +40 -0
  107. package/ts-dist/mocks/init-theme/.cursor/rules/fix-section.mdc +154 -0
  108. package/ts-dist/mocks/init-theme/.cursor/rules/general.mdc +30 -0
  109. package/ts-dist/mocks/init-theme/.cursor/rules/i18n.mdc +85 -0
  110. package/ts-dist/mocks/init-theme/.cursor/rules/javascript.mdc +85 -0
  111. package/ts-dist/mocks/init-theme/.cursor/rules/liquid-no-hardcoded-strings.mdc +42 -0
  112. package/ts-dist/mocks/init-theme/.cursor/rules/liquid.mdc +171 -0
  113. package/ts-dist/mocks/init-theme/.cursor/rules/mobile-desktop-setting-meta.mdc +34 -0
  114. package/ts-dist/mocks/init-theme/.cursor/rules/naming-convention.mdc +64 -0
  115. package/ts-dist/mocks/init-theme/.cursor/rules/pages.mdc +120 -0
  116. package/ts-dist/mocks/init-theme/.cursor/rules/performance.mdc +51 -0
  117. package/ts-dist/mocks/init-theme/.cursor/rules/qa-section.mdc +134 -0
  118. package/ts-dist/mocks/init-theme/.cursor/rules/redesign-section.mdc +147 -0
  119. package/ts-dist/mocks/init-theme/.cursor/rules/schema-sync.mdc +110 -0
  120. package/ts-dist/mocks/init-theme/.cursor/rules/schema.mdc +360 -0
  121. package/ts-dist/mocks/init-theme/.cursor/rules/share-urls.mdc +68 -0
  122. package/ts-dist/mocks/init-theme/.cursor/skills/browser-verify.md +128 -0
  123. package/ts-dist/mocks/init-theme/.cursor/skills/design-tokens.md +105 -0
  124. package/ts-dist/mocks/init-theme/.cursor/skills/page-json-contract.md +87 -0
  125. package/ts-dist/mocks/init-theme/.cursor/skills/qa-accessibility.md +35 -0
  126. package/ts-dist/mocks/init-theme/.cursor/skills/reference-lookup.md +88 -0
  127. package/ts-dist/mocks/init-theme/.cursor/skills/section-anatomy.md +173 -0
@@ -0,0 +1,360 @@
1
+ ---
2
+ description: Custom schema syntax rules — applies to all themes
3
+ globs: ["sections/*.liquid", "blocks/*.liquid", "pages/*.json"]
4
+ ---
5
+
6
+ # Custom Schema Syntax — b2bizmart Theme
7
+ This project uses CUSTOM schema syntax. It is NOT standard Shopify schema.
8
+ NEVER use standard Shopify schema syntax. Always use the patterns below.
9
+
10
+ ---
11
+
12
+ ## ✅ URL Type
13
+ ```jsonc
14
+ {
15
+ "type": "url",
16
+ "id": "my_url",
17
+ "label": "t:sections.section_name.settings.my_url.label",
18
+ "default": { "display_name": "t:sections.section_name.settings.my_url.default", "handle": "/path" }
19
+ }
20
+ ```
21
+ - `display_name` → always a `t:` translation key
22
+ - `handle` → the actual URL path string (e.g. `"home"`, `"/categories"`, `"/bulk-orders"`)
23
+ - ❌ NEVER use: `"default": "/path"` (standard Shopify format)
24
+
25
+ ### Render in Liquid
26
+ ```liquid
27
+ {{ section.settings.my_url.handle }}
28
+ {{ section.settings.my_url.display_name }}
29
+ ```
30
+
31
+ ---
32
+
33
+ ## ✅ Image Picker Type
34
+ ```jsonc
35
+ {
36
+ "type": "image_picker",
37
+ "id": "desktop_banner_img",
38
+ "label": "t:sections.section_name.settings.desktop_banner_img.label",
39
+ "default": { "url": "filename.webp", "enable_customisation": true }
40
+ }
41
+ ```
42
+ - `url` → filename string (e.g. `"banner1.webp"`, `"hero.jpg"`)
43
+ - `enable_customisation` → always `true`
44
+ - ❌ NEVER use: `"default": "/image.jpg"` (standard Shopify format)
45
+
46
+ ### Render in Liquid
47
+ ```liquid
48
+ {{ section.settings.desktop_banner_img.url }}
49
+ ```
50
+
51
+ ---
52
+
53
+ ## ✅ Media Picker Type (Video)
54
+ ```jsonc
55
+ {
56
+ "type": "media_picker",
57
+ "id": "video_media",
58
+ "label": "t:sections.section_name.settings.video_media.label",
59
+ "default": { "url": "video.mp4", "is_video": true }
60
+ }
61
+ ```
62
+ - `url` → video filename string (e.g. `"intro.mp4"`, `"hero-video.mp4"`)
63
+ - `is_video` → always `true` for video media
64
+
65
+ ### Render in Liquid
66
+ ```liquid
67
+ {{ section.settings.video_media.url }}
68
+ {{ section.settings.video_media.is_video }}
69
+ ```
70
+
71
+ ---
72
+
73
+ ## ✅ Select Type
74
+ ```jsonc
75
+ {
76
+ "type": "select",
77
+ "id": "layout_type",
78
+ "label": "t:sections.section_name.settings.layout_type.label",
79
+ "options": [
80
+ { "label": "t:sections.section_name.settings.layout_type.option__1.label", "value": "left-alignment" },
81
+ { "label": "t:sections.section_name.settings.layout_type.option__2.label", "value": "right-alignment" }
82
+ ],
83
+ "default": { "display_name": "t:sections.section_name.settings.layout_type.default", "value": "left-alignment" }
84
+ }
85
+ ```
86
+ - `default` is an object `{ "display_name": "t:...", "value": "..." }`
87
+ - `display_name` → always a `t:` translation key
88
+ - ❌ NEVER use: `"default": "left-alignment"` (standard Shopify format)
89
+
90
+ ### Render in Liquid
91
+ ```liquid
92
+ {{ section.settings.layout_type.value }}
93
+ {{ section.settings.layout_type.display_name }}
94
+ ```
95
+
96
+ ---
97
+
98
+ ## ✅ Menu Type
99
+ ```jsonc
100
+ {
101
+ "type": "menu",
102
+ "id": "footer_menu",
103
+ "label": "t:sections.section_name.settings.footer_menu.label",
104
+ "default": { "display_name": "t:sections.section_name.settings.footer_menu.default", "handle": "" }
105
+ }
106
+ ```
107
+ - `display_name` → always a `t:` translation key
108
+ - `handle` → menu handle string or empty string `""`
109
+ - ❌ NEVER use standard Shopify `linklists` or `linklist` objects
110
+
111
+ ### Render in Liquid
112
+ ```liquid
113
+ {{ section.settings.footer_menu.handle }}
114
+ {{ section.settings.footer_menu.display_name }}
115
+ ```
116
+
117
+ ---
118
+
119
+ ## ✅ Text Type
120
+ ```jsonc
121
+ {
122
+ "type": "text",
123
+ "id": "heading",
124
+ "label": "t:sections.section_name.settings.heading.label",
125
+ "default": "t:sections.section_name.settings.heading.default"
126
+ }
127
+ ```
128
+ - `default` → always a `t:` translation key string
129
+ - ❌ NEVER use hardcoded English strings as defaults
130
+
131
+ ### Render in Liquid
132
+ ```liquid
133
+ {{ section.settings.heading | escape }}
134
+ ```
135
+
136
+ **Use `text` for all headings and short labels** — section titles, card titles, eyebrows, badge text, button/CTA labels, and any field rendered in `<h1>`–`<h6>`. Never use `richtext` for heading blocks or heading fields.
137
+
138
+ ---
139
+
140
+ ## ✅ Richtext Type
141
+ ```jsonc
142
+ {
143
+ "type": "richtext",
144
+ "id": "description",
145
+ "label": "t:sections.section_name.settings.description.label",
146
+ "default": "<p>t:sections.section_name.settings.description.default</p>"
147
+ }
148
+ ```
149
+ - `default` → HTML string (use `t:` keys inside tags when the default is translatable)
150
+ - Use only for **body copy** — paragraphs, descriptions, answers, multi-line content where merchants may need bold, links, or lists
151
+ - ❌ NEVER use `richtext` for headings, titles, eyebrows, or button labels
152
+
153
+ ### Render in Liquid
154
+ ```liquid
155
+ {{ section.settings.description | raw }}
156
+ ```
157
+
158
+ ---
159
+
160
+ ## ✅ Heading vs content — field type rule
161
+
162
+ | Renders as | Schema type | Liquid output |
163
+ |---|---|---|
164
+ | `<h1>`–`<h6>`, title, eyebrow, badge, button label | `text` | `{{ field \| escape }}` |
165
+ | `<p>`, body copy, description, FAQ answer | `richtext` | `{{ field \| raw }}` |
166
+
167
+ Block types named `heading`, `title`, or similar → settings inside must use `text`, not `richtext`.
168
+
169
+ ---
170
+
171
+ ## ✅ Range Type
172
+ ```jsonc
173
+ {
174
+ "type": "range",
175
+ "id": "logo_width",
176
+ "min": 32,
177
+ "max": 56,
178
+ "step": 2,
179
+ "unit": "px",
180
+ "default": 40,
181
+ "label": "t:sections.section_name.settings.logo_width.label"
182
+ }
183
+ ```
184
+ - `default` → plain number (not an object)
185
+ - `unit` → optional string like `"px"`, `"%"`
186
+
187
+ ### Render in Liquid
188
+ ```liquid
189
+ {{ section.settings.logo_width }}
190
+ ```
191
+
192
+ ---
193
+
194
+ ## ✅ Checkbox Type
195
+ ```jsonc
196
+ {
197
+ "type": "checkbox",
198
+ "id": "show_banner_image",
199
+ "label": "t:sections.section_name.settings.show_banner_image.label",
200
+ "default": false
201
+ }
202
+ ```
203
+ - `default` → plain boolean `true` or `false`
204
+
205
+ ### Render in Liquid
206
+ ```liquid
207
+ {% if section.settings.show_banner_image %}...{% endif %}
208
+ ```
209
+
210
+ ---
211
+
212
+ ## ✅ Color Type
213
+ ```jsonc
214
+ {
215
+ "type": "color",
216
+ "id": "overlay_color",
217
+ "label": "t:sections.section_name.settings.overlay_color.label",
218
+ "default": "#000000"
219
+ }
220
+ ```
221
+ - `default` → hex color string
222
+
223
+ ### Render in Liquid
224
+ ```liquid
225
+ {{ section.settings.overlay_color }}
226
+ ```
227
+
228
+ ---
229
+
230
+ ## ✅ Header Type (UI divider, no id)
231
+ ```jsonc
232
+ {
233
+ "type": "header",
234
+ "content": "t:sections.section_name.settings.my_header.content"
235
+ }
236
+ ```
237
+ - No `id` field
238
+ - `content` → always a `t:` translation key
239
+
240
+ ---
241
+
242
+ ## ✅ Blocks
243
+
244
+ There are **two block models**. A section may use one or both.
245
+
246
+ ### 1. Local blocks (section-scoped)
247
+
248
+ Defined inline in the section's `{% schema %}` with full `settings`. Page JSON `type` is the bare block type name (e.g. `"badge"`).
249
+
250
+ ```jsonc
251
+ // In section schema
252
+ "blocks": [
253
+ {
254
+ "type": "block-type-name",
255
+ "name": "t:sections.section_name.blocks.block_type.name",
256
+ "limit": 3,
257
+ "settings": [ ...settings using above patterns... ]
258
+ }
259
+ ]
260
+ ```
261
+
262
+ Render in the section with a `{% for block in section.blocks %}` loop and inline markup (or `{% case block.type %}`).
263
+
264
+ ### 2. Theme blocks (reusable, theme-scoped)
265
+
266
+ Live as standalone files at `blocks/<name>.liquid`, each with its own `{% schema %}`. A section **opts in** by listing them in its schema `blocks` array:
267
+
268
+ ```jsonc
269
+ // Offer ALL theme blocks in the picker
270
+ { "type": "@theme" }
271
+
272
+ // Offer specific theme blocks only (preferred when mixing with local blocks)
273
+ { "type": "zc_theme__text", "name": "t:blocks.text.name" },
274
+ { "type": "zc_theme__button", "name": "t:blocks.button.name", "limit": 2 }
275
+ ```
276
+
277
+ - Runtime type prefix: `zc_theme__` + file name (`blocks/text.liquid` → `zc_theme__text`)
278
+ - i18n keys: `t:blocks.<name>.*` (not `t:sections.*.blocks.*`)
279
+ - Theme block files must include `"presets": [ { "name": "t:blocks.<name>.presets.default.name" } ]` so they appear in the editor picker
280
+ - Theme blocks see only `block`, `section`, and globals — not section-local `{% liquid %}` assigns
281
+ - Nesting: a theme block may declare its own `"blocks"` array and render children with `{% render_blocks %}` (max depth 5)
282
+
283
+ ```liquid
284
+ // Pure theme-block section
285
+ {% render_blocks %}
286
+
287
+ // Filtered slot (e.g. heading area only)
288
+ {% render_blocks type: "zc_theme__text" %}
289
+
290
+ // Mixed section — local + theme blocks
291
+ {% for block in section.blocks %}
292
+ {% case block.type %}
293
+ {% when 'badge' %}
294
+ {%- comment -%} inline local block markup {%- endcomment -%}
295
+ {% else %}
296
+ {% render block %}
297
+ {% endcase %}
298
+ {% endfor %}
299
+ ```
300
+
301
+ ### Page JSON (both models)
302
+
303
+ ```jsonc
304
+ "blocks": {
305
+ "heading-block": {
306
+ "type": "zc_theme__text",
307
+ "settings": {
308
+ "text": "<p>Welcome</p>",
309
+ "desktop_text_size": { "display_name": "Large", "value": "text-2xl" }
310
+ }
311
+ },
312
+ "badge-1": {
313
+ "type": "badge",
314
+ "settings": {
315
+ "select_field": { "display_name": "Left", "value": "left" },
316
+ "image_field": { "url": "image.webp", "enable_customisation": true },
317
+ "url_field": { "display_name": "Home", "handle": "/home" },
318
+ "checkbox_field": false,
319
+ "range_field": 48,
320
+ "color_field": "#000000",
321
+ "video_field": { "url": "video.mp4", "is_video": true }
322
+ }
323
+ }
324
+ },
325
+ "block_order": ["heading-block", "badge-1"]
326
+ ```
327
+
328
+ - Local block `type` → bare name defined in section schema
329
+ - Theme block `type` → `zc_theme__<name>` matching `blocks/<name>.liquid`
330
+ - Block `settings` keys must match the schema for that block type (section schema for local; `blocks/<name>.liquid` schema for theme)
331
+
332
+ ---
333
+
334
+ ## ✅ Full Section Schema Template
335
+ ```jsonc
336
+ {% schema %}
337
+ {
338
+ "name": "t:sections.section_name.name",
339
+ "tag": "section",
340
+ "class": "section",
341
+ "settings": [],
342
+ "blocks": [],
343
+ "presets": [
344
+ {
345
+ "name": "t:sections.section_name.presets.default.name"
346
+ }
347
+ ]
348
+ }
349
+ {% endschema %}
350
+ ```
351
+
352
+ ---
353
+
354
+ ## ❌ Never Use These (Standard Shopify Patterns)
355
+ - `"default": "/some-url"` → use `{ "display_name": "t:...", "handle": "/some-url" }`
356
+ - `"default": "option-value"` for selects → use `{ "display_name": "t:...", "value": "option-value" }`
357
+ - `{{ section.settings.image | img_url }}` → use `{{ section.settings.image.url }}`
358
+ - Video in image_picker → use `media_picker` with `{ "url": "video.mp4", "is_video": true }`
359
+ - `{{ section.settings.menu }}` for menus → use `{{ section.settings.menu.handle }}`
360
+ - Hardcoded English in `label`, `default`, `content` → always use `t:` keys
@@ -0,0 +1,68 @@
1
+ ---
2
+ description: Social share URL patterns for product pages — use when adding share links to any section
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Share URL Logic
7
+
8
+ When building social share icons on a product page, use these URL patterns. No JavaScript — pure `<a>` links only.
9
+
10
+ ## Variable assignments
11
+
12
+ Always compute share variables before rendering links:
13
+
14
+ ```liquid
15
+ {% liquid
16
+ assign pdp_share_origin = page_info.origin | default: storefrontRootUrl | default: storefrontHomeUrl | default: ''
17
+ assign pdp_share_url = product.url
18
+ if pdp_share_origin != blank
19
+ assign pdp_share_url = pdp_share_origin | append: product.url
20
+ endif
21
+ assign pdp_share_title = product.title | url_encode
22
+ assign pdp_share_url_encoded = pdp_share_url | url_encode
23
+ assign pdp_share_image = ''
24
+ if product.images and product.images.size > 0
25
+ assign pdp_share_image = product.images | first | image_url | url_encode
26
+ endif
27
+ assign pdp_share_desc = product.short_description | default: product.title | url_encode
28
+ %}
29
+ ```
30
+
31
+ ## URLs
32
+
33
+ | Platform | URL |
34
+ |------------|---------------------------------------------------------------------------------------------|
35
+ | Copy link | `{{ pdp_share_url }}` |
36
+ | Facebook | `https://www.facebook.com/sharer/sharer.php?u={{ pdp_share_url_encoded }}` |
37
+ | Pinterest | `https://pinterest.com/pin/create/button/?url={{ pdp_share_url_encoded }}{% if pdp_share_image != blank %}&media={{ pdp_share_image }}{% endif %}&description={{ pdp_share_desc }}` |
38
+ | Instagram | `https://www.instagram.com/` |
39
+ | X (Twitter)| `https://x.com/intent/tweet?url={{ pdp_share_url_encoded }}&text={{ pdp_share_title }}` |
40
+
41
+ ## Markup pattern
42
+
43
+ ```liquid
44
+ <a href="<share-url>" target="_blank" rel="noopener noreferrer"
45
+ class="flex items-center justify-center w-6 h-6 [&>svg]:w-full [&>svg]:h-full"
46
+ aria-label="{{ 'product_details.share_<platform>' | t }}">
47
+ {% render 'icon-<platform>' %}
48
+ </a>
49
+ ```
50
+
51
+ ## Icon snippets
52
+
53
+ - `icon-link` — chain link (copy/share URL)
54
+ - `icon-facebook`
55
+ - `icon-pinterest`
56
+ - `icon-instagram`
57
+ - `icon-x` — X / Twitter
58
+
59
+ ## i18n keys (runtime — `en.json`)
60
+
61
+ ```json
62
+ "share_label": "Share",
63
+ "share_copy_link": "Copy link",
64
+ "share_facebook": "Share on Facebook",
65
+ "share_pinterest": "Share on Pinterest",
66
+ "share_instagram": "Share on Instagram",
67
+ "share_x": "Share on X"
68
+ ```
@@ -0,0 +1,128 @@
1
+ # Browser verification — Chrome DevTools MCP
2
+
3
+ Single source of truth for browser automation during theme development.
4
+
5
+ **MCP config:** `.cursor/mcp.json`
6
+ **Used by:** `/build-theme`, `/compare-section --visual`, section-builder, page-orchestrator
7
+ **Fallback:** `cursor-ide-browser` only if `chrome-devtools` MCP is unavailable
8
+
9
+ ---
10
+
11
+ ## Preconditions
12
+
13
+ 1. **Developer confirmed `storeUrl`** — recorded in `.claude/scratchpad/<theme>/dev-config.json`
14
+ 2. **Developer confirmed page URLs** — same file, `confirmed_by_developer: true`
15
+ 3. Dev server running: `yarn run dev --storeUrl=<store_url>` (developer starts OR agent starts and notifies)
16
+ 4. Chrome DevTools MCP connected
17
+ 5. Figma node ID known for visual compare
18
+
19
+ **Do not navigate until URLs are confirmed.** If any fail → ask developer. Never invent a "verified pass."
20
+
21
+ See `.claude/skills/theme-from-figma/dev-server-and-urls.md`.
22
+
23
+ ---
24
+
25
+ ## Page URLs (defaults — always confirm with developer)
26
+
27
+ | Page | Typical URL (verify!) |
28
+ |---|---|
29
+ | Home | `http://localhost:3000/home` |
30
+ | Product | `http://localhost:3000/products/item-1` |
31
+ | Collection | `http://localhost:3000/collections/all-products` |
32
+ | Blog list | ask developer |
33
+ | Blog detail | ask developer |
34
+
35
+ Read confirmed URLs from `dev-config.json` — never hardcode.
36
+
37
+ ---
38
+
39
+ ## Tool map — use the full toolkit
40
+
41
+ | Task | Tool |
42
+ |---|---|
43
+ | Open tab | `list_pages` → `select_page` or `new_page` |
44
+ | Navigate | `navigate_page` |
45
+ | Viewport | `emulate` → `1440x900` or `375x812,mobile,touch` |
46
+ | Scroll to section | `evaluate_script` → `scrollIntoView` |
47
+ | Screenshot | `take_screenshot` + `filePath` to scratchpad |
48
+ | DOM / a11y tree | `take_snapshot` |
49
+ | Console | `list_console_messages` types `["error","issue"]` |
50
+ | Network / 404 images | `list_network_requests` |
51
+ | **A11y audit** | `lighthouse_audit` mode `navigation` device `mobile` |
52
+ | **Perf audit** | `lighthouse_audit` (baseline) + `performance_start_trace` → `performance_stop_trace` → `performance_analyze_insight` for LCP |
53
+ | Computed styles | `evaluate_script` |
54
+
55
+ ---
56
+
57
+ ## Standard 3-gate workflow (section or page)
58
+
59
+ ```
60
+ GATE 1 — VISUAL
61
+ emulate desktop → navigate → scroll section → take_screenshot
62
+ emulate mobile → take_screenshot
63
+ Figma MCP get_screenshot (same node, desktop + mobile)
64
+ Agent vision → visual-diff.md (CRITICAL / MINOR / SUGGESTION)
65
+ list_network_requests → flag image 404s (check asset_url — see image-sources.md)
66
+
67
+ GATE 2 — A11Y
68
+ lighthouse_audit mode:navigation device:mobile
69
+ list_console_messages types:["error","issue"]
70
+ Pass: a11y score ≥ 90, no critical console issues affecting section
71
+
72
+ GATE 3 — PERF (pages; spot-check heavy sections)
73
+ lighthouse_audit device:mobile on page URL
74
+ If LCP poor: performance_start_trace → navigate → performance_stop_trace → analyze
75
+ Pass: perf score ≥ 85 mobile (pages), CLS < 0.1
76
+ ```
77
+
78
+ Run Gate 1 desktop + mobile screenshots **in parallel** with Figma `get_screenshot` when possible.
79
+
80
+ ---
81
+
82
+ ## Parallel subagents
83
+
84
+ 1. `new_page` per subagent
85
+ 2. Pass `pageId` on every subsequent call
86
+ 3. `close_page` when done
87
+
88
+ ---
89
+
90
+ ## Screenshot paths
91
+
92
+ ```
93
+ .claude/scratchpad/<theme>/pages/<page>/sections/<section>/rendered-desktop.png
94
+ .claude/scratchpad/<theme>/pages/<page>/sections/<section>/rendered-mobile.png
95
+ .claude/scratchpad/<theme>/pages/<page>/rendered-desktop.png
96
+ .claude/scratchpad/<theme>/pages/<page>/rendered-mobile.png
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Image 404 debugging (common visual failure)
102
+
103
+ ```js
104
+ // evaluate_script — list broken images in section
105
+ () => {
106
+ const root = document.querySelector('#section-section_main') || document.body;
107
+ return [...root.querySelectorAll('img')].map(img => ({
108
+ src: img.src.slice(-80),
109
+ naturalWidth: img.naturalWidth,
110
+ broken: img.complete && img.naturalWidth === 0
111
+ })).filter(i => i.broken);
112
+ }
113
+ ```
114
+
115
+ Fix: theme assets need `| asset_url`; product images need `?organization_id={{ organizationId }}`.
116
+
117
+ ---
118
+
119
+ ## Release vs dev loop
120
+
121
+ | Gate | Dev loop (MCP) | Optional release script |
122
+ |---|---|---|
123
+ | Visual | Agent vision + screenshots | `scripts/pixel-diff.mjs` |
124
+ | A11y | `lighthouse_audit` | `scripts/a11y.mjs` |
125
+ | Perf | `lighthouse_audit` + trace | `scripts/perf.mjs` |
126
+ | Lint | `lint-section.mjs` | same |
127
+
128
+ **MCP results drive fixes.** Scripts produce JSON artefacts for CI if needed.
@@ -0,0 +1,105 @@
1
+ # SKILL: Design Tokens
2
+ # Save this as a Cursor Notepad named: design-tokens
3
+ # Usage in chat: @design-tokens
4
+
5
+ How to correctly map Figma values to Tailwind classes and CSS variables in this theme system.
6
+ Always use this when reading Figma output — never use raw values inline.
7
+
8
+ ---
9
+
10
+ ## Figma MCP variable resolution (do this first)
11
+ When using **Figma MCP** (e.g. get_design_context), the response contains `var(--variable-name, fallback)`. The fallback may be from a different mode (e.g. TWICE). To use the theme’s mode (e.g. B2BIZMART):
12
+
13
+ 1. **Look up** the variable name in `figma-variables.json`: split the name on `/` and traverse (e.g. `radius/xl` → `json["radius"]["xl"]`).
14
+ 2. If the node has **`$value`**, use that value.
15
+ 3. If not found, use the **fallback** from the MCP response.
16
+ 4. Then map this **resolved** value to Tailwind/CSS using the tables below.
17
+
18
+ See `.cursor/rules/figma-mcp-resolution.mdc` for the full rule.
19
+
20
+ ---
21
+
22
+ ## The Rule
23
+ ❌ Never output: `style="font-size: 48px; color: #1a1a1a"`
24
+ ✅ Always output: `class="text-5xl" style="color: var(--color-heading)"`
25
+
26
+ ---
27
+
28
+ ## CSS Variables (always use these for color)
29
+ | Role | Variable |
30
+ |------|----------|
31
+ | Primary brand | `var(--color-primary)` |
32
+ | Text on primary bg | `var(--color-on-primary)` |
33
+ | Headings / dark text | `var(--color-heading)` |
34
+ | Page / card background | `var(--color-background)` |
35
+ | Border / divider | `var(--color-border)` |
36
+ | Header bar background | `var(--color-header-bg)` |
37
+ | Section horizontal padding | `var(--section-padding-x, 16px)` |
38
+
39
+ For theme-specific colors not in this list → check `figma-variables.json` in the current theme folder (and resolve Figma MCP vars from it first when using MCP).
40
+
41
+ ---
42
+
43
+ ## Typography → Tailwind
44
+ | Figma px | Tailwind | Use for |
45
+ |----------|----------|---------|
46
+ | 12px | `text-xs` | Labels, captions |
47
+ | 14px | `text-sm` | Secondary text, meta |
48
+ | 16px | `text-base` | Body text |
49
+ | 18px | `text-lg` | Large body |
50
+ | 20px | `text-xl` | Small headings |
51
+ | 24px | `text-2xl` | Sub-headings |
52
+ | 30px | `text-3xl` | Section headings |
53
+ | 36px | `text-4xl` | Page headings |
54
+ | 48px | `text-5xl` | Hero headings |
55
+ | 60px | `text-6xl` | Display headings |
56
+ | 72px+ | `text-7xl` | Giant display |
57
+
58
+ Font weight:
59
+ | Figma | Tailwind |
60
+ |-------|----------|
61
+ | 400 | `font-normal` |
62
+ | 500 | `font-medium` |
63
+ | 600 | `font-semibold` |
64
+ | 700 | `font-bold` |
65
+ | 800 | `font-extrabold` |
66
+
67
+ ---
68
+
69
+ ## Spacing → Tailwind (1 unit = 4px)
70
+ | Figma px | Tailwind gap/p/m |
71
+ |----------|-----------------|
72
+ | 4px | `gap-1` / `p-1` |
73
+ | 8px | `gap-2` / `p-2` |
74
+ | 12px | `gap-3` / `p-3` |
75
+ | 16px | `gap-4` / `p-4` |
76
+ | 20px | `gap-5` / `p-5` |
77
+ | 24px | `gap-6` / `p-6` |
78
+ | 32px | `gap-8` / `p-8` |
79
+ | 40px | `gap-10` / `p-10` |
80
+ | 48px | `gap-12` / `p-12` |
81
+ | 64px | `gap-16` / `p-16` |
82
+ | 80px | `gap-20` / `p-20` |
83
+
84
+ ---
85
+
86
+ ## Border Radius → Tailwind
87
+ | Figma px | Tailwind |
88
+ |----------|----------|
89
+ | 2px | `rounded-sm` |
90
+ | 4px | `rounded` |
91
+ | 6px | `rounded-md` |
92
+ | 8px | `rounded-lg` |
93
+ | 12px | `rounded-xl` |
94
+ | 16px | `rounded-2xl` |
95
+ | 24px | `rounded-3xl` |
96
+ | 9999px | `rounded-full` |
97
+
98
+ ---
99
+
100
+ ## When a Value is Not in This Map
101
+ 1. If from Figma MCP, resolve via `figma-variables.json` first (use `$value` if present).
102
+ 2. Check `figma-variables.json` in the current theme folder for other mappings.
103
+ 3. Use Tailwind arbitrary value: `text-[22px]` or `gap-[18px]`
104
+ 4. Add a comment: `{{-- ⚠️ unmapped token: 22px --}}`
105
+ 5. Report it in the build output so it can be added to the token map if needed.