@wix/agent-skills 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/skills/wix-app/SKILL.md +49 -42
  4. package/skills/wix-app/references/BACKEND_EVENT.md +10 -65
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +101 -406
  6. package/skills/wix-app/references/DASHBOARD_MENU_PLUGIN.md +14 -111
  7. package/skills/wix-app/references/DASHBOARD_MODAL.md +56 -205
  8. package/skills/wix-app/references/DASHBOARD_PAGE.md +19 -98
  9. package/skills/wix-app/references/DASHBOARD_PLUGIN.md +6 -108
  10. package/skills/wix-app/references/DATA_COLLECTION.md +113 -198
  11. package/skills/wix-app/references/EMBEDDED_SCRIPT.md +41 -268
  12. package/skills/wix-app/references/EXTENSION_REGISTRATION.md +27 -76
  13. package/skills/wix-app/references/SERVICE_PLUGIN.md +35 -188
  14. package/skills/wix-app/references/SITE_PLUGIN.md +8 -92
  15. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +0 -44
  16. package/skills/wix-app/references/custom-element-widget/SETTINGS_PANEL.md +19 -330
  17. package/skills/wix-app/references/dashboard-menu-plugin/bookings-slots.md +0 -12
  18. package/skills/wix-app/references/dashboard-menu-plugin/ecommerce-slots.md +7 -0
  19. package/skills/wix-app/references/dashboard-menu-plugin/restaurants-slots.md +0 -12
  20. package/skills/wix-app/references/dashboard-plugin/SLOTS.md +3 -15
  21. package/skills/wix-app/references/service-plugin/ADDITIONAL-FEES.md +2 -18
  22. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +2 -42
  23. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +1 -11
  24. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +1 -11
  25. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +2 -40
  26. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +2 -19
  27. package/skills/wix-app/references/service-plugin/VALIDATIONS.md +2 -18
  28. package/skills/wix-app/references/site-plugin/SLOTS.md +17 -68
  29. package/skills/wix-headless/SKILL.md +111 -389
  30. package/skills/wix-headless/references/BUILD.md +307 -0
  31. package/skills/wix-headless/references/DESIGN_SYSTEM.md +115 -0
  32. package/skills/wix-headless/references/DISCOVERY.md +237 -112
  33. package/skills/wix-headless/references/PLAN.md +82 -0
  34. package/skills/wix-headless/references/SEED.md +205 -0
  35. package/skills/wix-headless/references/SETUP.md +140 -134
  36. package/skills/wix-headless/references/astro/COMPOSE.md +142 -0
  37. package/skills/wix-headless/references/{blog → astro/blog}/BLOG_PAGES.md +1 -1
  38. package/skills/wix-headless/references/{blog → astro/blog}/BLOG_SETUP.md +2 -2
  39. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +214 -0
  40. package/skills/wix-headless/references/{cms → astro/cms}/FAQ_KNOWLEDGE_BASE.md +6 -4
  41. package/skills/wix-headless/references/{cms → astro/cms}/PORTFOLIO.md +5 -5
  42. package/skills/wix-headless/references/{cms → astro/cms}/RESOURCE_LIBRARY.md +5 -5
  43. package/skills/wix-headless/references/{cms → astro/cms}/TEAM_DIRECTORY.md +5 -5
  44. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +331 -0
  45. package/skills/wix-headless/references/{ecom → astro/ecom}/CART_PAGES.md +1 -1
  46. package/skills/wix-headless/references/{ecom → astro/ecom}/CART_WIRING.md +1 -1
  47. package/skills/wix-headless/references/{ecom → astro/ecom}/COMPONENTS_CSS.md +3 -3
  48. package/skills/wix-headless/references/{forms → astro/forms}/CONTACT_FORM.md +13 -13
  49. package/skills/wix-headless/references/{gift-cards → astro/gift-cards}/COMPONENTS.md +1 -1
  50. package/skills/wix-headless/references/{gift-cards → astro/gift-cards}/PAGES.md +1 -1
  51. package/skills/wix-headless/references/{stores → astro/stores}/BACK_IN_STOCK.md +1 -1
  52. package/skills/wix-headless/references/{stores → astro/stores}/CATEGORY_PAGES.md +12 -13
  53. package/skills/wix-headless/references/{stores → astro/stores}/COMPONENTS_CSS.md +4 -4
  54. package/skills/wix-headless/references/{stores → astro/stores}/HOME_AND_NAV.md +11 -9
  55. package/skills/wix-headless/references/{stores → astro/stores}/PRODUCT_PAGES.md +5 -3
  56. package/skills/wix-headless/references/{stores → astro/stores}/SHARED_WIRING.md +3 -3
  57. package/skills/wix-headless/references/astro/templates/Footer.astro +27 -0
  58. package/skills/wix-headless/references/astro/templates/Layout.astro +132 -0
  59. package/skills/wix-headless/references/astro/templates/Navigation.astro +38 -0
  60. package/skills/wix-headless/references/astro/templates/astro.config.mjs +41 -0
  61. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +302 -0
  62. package/skills/wix-headless/references/astro/templates/global.css +286 -0
  63. package/skills/wix-headless/references/astro/templates/index.astro +56 -0
  64. package/skills/wix-headless/{templates → references/astro/templates}/stores/back-in-stock.ts +1 -1
  65. package/skills/wix-headless/{templates → references/astro/templates}/stores/components-stores.css +138 -33
  66. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +10 -11
  67. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +5 -5
  68. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +31 -230
  69. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +13 -8
  70. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +38 -0
  71. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +10 -10
  72. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +5 -5
  73. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +11 -11
  74. package/skills/wix-headless/references/images/INSTRUCTIONS.md +47 -50
  75. package/skills/wix-headless/references/seed-recipes.md +49 -0
  76. package/skills/wix-headless/references/shared/AUTHENTICATION.md +110 -0
  77. package/skills/wix-headless/references/shared/BUILD_NOISE.md +2 -2
  78. package/skills/wix-headless/references/shared/DOCS_SEARCH.md +41 -0
  79. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +17 -17
  80. package/skills/wix-headless/references/shared/IMPLEMENTER.md +20 -29
  81. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +1 -1
  82. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +25 -16
  83. package/skills/wix-headless/references/shared/STYLING.md +47 -10
  84. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +25 -25
  85. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +17 -17
  86. package/skills/wix-headless/references/verticals/_schema.json +31 -117
  87. package/skills/wix-headless/references/verticals/_schema.md +60 -150
  88. package/skills/wix-headless/references/verticals/blog.md +5 -99
  89. package/skills/wix-headless/references/verticals/cms.md +9 -100
  90. package/skills/wix-headless/references/verticals/ecom.md +5 -76
  91. package/skills/wix-headless/references/verticals/forms.md +5 -85
  92. package/skills/wix-headless/references/verticals/gift-cards.md +6 -103
  93. package/skills/wix-headless/references/verticals/stores.md +10 -144
  94. package/skills/wix-headless/scripts/check-manifest.mjs +5 -5
  95. package/skills/wix-headless/scripts/emit-design-tokens.mjs +29 -23
  96. package/skills/wix-headless/scripts/init-site-json.mjs +59 -21
  97. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +67 -43
  98. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +3 -3
  99. package/skills/wix-headless/scripts/preview.sh +3 -3
  100. package/skills/wix-headless/scripts/release.sh +4 -4
  101. package/skills/wix-headless/scripts/scaffold.sh +75 -20
  102. package/skills/wix-headless/scripts/seed-utilities.sh +50 -12
  103. package/skills/wix-manage/SKILL.md +4 -8
  104. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +2 -0
  105. package/skills/wix-manage/references/cms/cms-data-items-crud.md +4 -0
  106. package/skills/wix-manage/references/cms/cms-references-and-relationships.md +2 -0
  107. package/skills/wix-manage/references/cms/cms-schema-management.md +4 -0
  108. package/skills/wix-manage/references/ecommerce/api-shipping.md +443 -0
  109. package/skills/wix-manage/references/ecommerce/flow-add-free-shipping.md +5 -6
  110. package/skills/wix-manage/references/ecommerce/flow-fix-coverage-gaps.md +4 -5
  111. package/skills/wix-manage/references/ecommerce/flow-optimize-shipping-rates.md +4 -5
  112. package/skills/wix-manage/references/ecommerce/goal-increase-aov.md +1 -1
  113. package/skills/wix-manage/references/ecommerce/goal-reduce-cart-abandonment.md +1 -2
  114. package/skills/wix-manage/references/ecommerce/guardrail-shipping-health.md +2 -2
  115. package/skills/wix-manage/references/ecommerce/recipe-apply-shipping-recommendations.md +4 -5
  116. package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +7 -7
  117. package/skills/wix-manage/references/ecommerce/setup-discount-rules.md +209 -72
  118. package/skills/wix-manage/references/ecommerce/setup-store-pickup-location.md +9 -10
  119. package/skills/wix-manage/references/ecommerce/skill-graph.md +4 -4
  120. package/skills/wix-manage/references/forms/create-form.md +2 -0
  121. package/skills/wix-manage/references/stores/bulk-create-products-with-options.md +2 -0
  122. package/skills/wix-manage/references/stores/create-product-from-image.md +91 -38
  123. package/skills/wix-manage/references/stores/setup-online-store-catalog-v3.md +2 -0
  124. package/skills/wix-app/references/custom-element-widget/default-thumbnail.png +0 -0
  125. package/skills/wix-app/references/data-collection/extension-template.ts +0 -107
  126. package/skills/wix-headless/references/ORCHESTRATION.md +0 -269
  127. package/skills/wix-headless/references/commands/install-app.md +0 -42
  128. package/skills/wix-headless/references/commands/mcp-bootstrap.md +0 -28
  129. package/skills/wix-headless/references/designer/INSTRUCTIONS.md +0 -828
  130. package/skills/wix-headless/references/shared/MCP_PREFIX.md +0 -105
  131. package/skills/wix-headless/scripts/copy-utility-templates.mjs +0 -153
  132. package/skills/wix-headless/templates/ecom/components-ecom.css +0 -215
  133. package/skills/wix-manage/references/events/list-events.md +0 -203
  134. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/CartBadge.tsx +0 -0
  135. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/CartView.tsx +0 -0
  136. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/cart.astro +0 -0
  137. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/discounts.ts +0 -0
  138. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/thank-you.astro +0 -0
  139. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/GiftCardPurchase.tsx +0 -0
  140. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/_home-teaser-snippet.astro +0 -0
  141. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/_nav-snippet.astro +0 -0
  142. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/components-gift-cards.css +0 -0
  143. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/gift-cards.astro +0 -0
  144. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/gift-cards.ts +0 -0
  145. /package/skills/wix-headless/{templates → references/astro/templates}/stores/AddToCartButton.tsx +0 -0
  146. /package/skills/wix-headless/{templates → references/astro/templates}/stores/BackInStockForm.tsx +0 -0
  147. /package/skills/wix-headless/{templates → references/astro/templates}/stores/CategoryRail.astro +0 -0
  148. /package/skills/wix-headless/{templates → references/astro/templates}/stores/ProductCard.astro +0 -0
  149. /package/skills/wix-headless/{templates → references/astro/templates}/stores/ProductPurchase.tsx +0 -0
  150. /package/skills/wix-headless/{templates → references/astro/templates}/stores/SeoTags.astro +0 -0
  151. /package/skills/wix-headless/{templates → references/astro/templates}/stores/categories.ts +0 -0
  152. /package/skills/wix-headless/{templates → references/astro/templates}/stores/category/[slug].astro +0 -0
  153. /package/skills/wix-headless/{templates → references/astro/templates}/stores/products/[slug].astro +0 -0
  154. /package/skills/wix-headless/{templates → references/astro/templates}/stores/products/index.astro +0 -0
@@ -1,6 +1,8 @@
1
1
  # Phase 4 Home Page + Nav — Stores
2
2
 
3
- Scope: `pages-home-and-nav`. Launched in **Step 7** after `pages-categories` has written the shared rail and `categories.ts` helper. Patches the home page's stores-related placeholder data with live `productsV3` queries AND inserts the Shop submenu (categories list) into the persisted Navigation.
3
+ Scope: `pages-home-and-nav`. Launched in **Step 7**; imports the orchestrator-pre-copied `categories.ts` helper (and the rail `pages-categories` writes — resolved at build time). Patches the home page's stores-related placeholder data with live `productsV3` queries AND inserts the Shop submenu (categories list) into the persisted Navigation.
4
+
5
+ > **You patch the shared `Navigation.astro` + `index.astro` shells**, which other packs (e.g. gift-cards) also patch at their own markers. **Touch only your markers and preserve every other scope's siblings — never rewrite either file.** (Flow is the conductor's job: it serializes shell-patching scopes so concurrent marker edits don't collide — BUILD.md Step 7.)
4
6
 
5
7
  ## Scope
6
8
 
@@ -12,14 +14,14 @@ Files this agent PATCHES (does NOT rewrite):
12
14
  Files this agent MUST NOT touch:
13
15
  - Any other part of `index.astro` — hero, copy, newsletter, decorative ornaments are designer-owned
14
16
  - Any part of `Navigation.astro` outside the `<!-- nav:links -->` marker — designer/ecom-owned (the marker model lets multiple verticals contribute siblings without conflict)
15
- - `src/utils/categories.ts`, `src/components/CategoryRail.astro`, `src/pages/category/[slug].astro` — owned by `pages-categories`; this scope only **imports** `listStoreCategories` from `categories.ts`
17
+ - `src/utils/categories.ts` — pre-copied by the orchestrator; this scope only **imports** `listStoreCategories` from it. `src/components/CategoryRail.astro`, `src/pages/category/[slug].astro` — owned by `pages-categories`
16
18
  - Any other component, page, or CSS
17
19
  - `global.css`
18
20
 
19
21
  ## Inputs (from parent prompt)
20
22
 
21
23
  - **Phase 1 stores return** — `products: [{id, name, slug, ...}]`. Needed for live query on home page; also useful for deciding how many to feature.
22
- - **Design tokens** — read `.wix/site.json.designTokens` for the published color/spacing/typography vocabulary; compose Tailwind utilities derived from those tokens at the call site rather than inventing semantic classes. See `references/shared/STYLING.md` for the three styling categories.
24
+ - **Design tokens** — the full `designTokens` JSON is inlined in your prompt for the published color/spacing/typography vocabulary; compose Tailwind utilities derived from those tokens at the call site rather than inventing semantic classes. See `references/shared/STYLING.md` for the three styling categories.
23
25
  - **Designer output summary** — path of `src/pages/index.astro` and `src/components/Navigation.astro`, with notes on what placeholder data exists.
24
26
  - **Categories (lookup)** — if the designer used category links with hardcoded slugs, call `categoriesV3` SDK to discover real category slugs and rewrite `href`s.
25
27
 
@@ -28,7 +30,7 @@ Files this agent MUST NOT touch:
28
30
  1. **Surgical edits only.** Use `Edit` tool, not `Write`. Preserve everything the designer wrote — hero, copy, decorative elements, section structure, class names.
29
31
  2. **Do NOT restructure layout.** If the designer didn't include featured products, don't add it.
30
32
  3. **Do NOT mutate categories in the catalog.** Read-only. Match designer's category slugs against real ones; rewrite `href` if matched; fall back to `/products` if not.
31
- 4. **Never improvise category endpoint URLs.** Use `categoriesV3` SDK. If the SDK isn't available, fall back to `<prefix>CallWixSiteAPI` with `POST /categories/v1/categories/query` body `{"query":{}}`. Improvised `/stores/v3/categories/...` URLs caused a multi-minute stall historically.
33
+ 4. **Never improvise category endpoint URLs.** Use `categoriesV3` SDK. If the SDK isn't available, fall back to `curl` with `POST /categories/v1/categories/query` body `{"query":{}}`. Improvised `/stores/v3/categories/...` URLs cause a multi-minute stall.
32
34
  5. **If another agent already wired the home page** (e.g., a previous run), leave it alone and note this in the return.
33
35
  6. **ProductCard is a template** — always accepts `{ product }`. Pass raw SDK product objects, never flat-map. See § 1a.
34
36
 
@@ -72,7 +74,7 @@ try {
72
74
  ---
73
75
  ```
74
76
 
75
- Then pass each raw product to `ProductCard`. The ribbon is fetched inside ProductCard itself — pages no longer wire offers:
77
+ Then pass each raw product to `ProductCard`. The ribbon is fetched inside ProductCard itself — pages don't wire offers:
76
78
  ```astro
77
79
  {featured.map((p) => <ProductCard product={p} />)}
78
80
  ```
@@ -116,7 +118,7 @@ Handle this:
116
118
  import { categoriesV3 } from "@wix/stores";
117
119
  const { items: categories } = await categoriesV3.queryCategories().find();
118
120
  ```
119
- Fall back to `CallWixSiteAPI` with `POST /categories/v1/categories/query` body `{"query":{}}` if the SDK module is unavailable.
121
+ Fall back to `curl` with `POST https://www.wixapis.com/categories/v1/categories/query` body `{"query":{}}` if the SDK module is unavailable (headers per `AUTHENTICATION.md`).
120
122
  2. **Match by name or slug** — case-insensitive substring match is fine (e.g., designer's "rubber" card matches a real category "Rubber Ducks").
121
123
  3. **If a match exists** → rewrite the `href` to use the real category slug (and optionally real category name).
122
124
  4. **If no match exists** → render the card with `/products` (no filter) rather than a dead filter URL. Keep the visual card intact.
@@ -128,7 +130,7 @@ Handle this:
128
130
 
129
131
  The designer scaffolds `Navigation.astro` with a `<!-- nav:links -->` marker that vertical packs replace with their primary nav contributions. Stores contributes the Shop link (always) and a hover/focus submenu listing the merchant's visible categories (when any exist — empty by default, since Phase 1 does not seed them).
130
132
 
131
- Read `src/utils/categories.ts` (already on disk — written by `pages-categories`) and import `listStoreCategories`. At the marker, insert:
133
+ Import `listStoreCategories` from `src/utils/categories.ts` (already on disk — pre-copied by the orchestrator). At the marker, insert:
132
134
 
133
135
  ```astro
134
136
  ---
@@ -213,7 +215,7 @@ Keep the marker comment immediately after the inserted `<li>` so other vertical
213
215
  - **Do NOT mutate** categories in the catalog — read-only.
214
216
  - **Do NOT touch** `Navigation.astro` outside the `<!-- nav:links -->` marker. Other vertical packs use the same marker model and write siblings.
215
217
  - **Do NOT touch** `CartBadge.tsx` or `CartView.tsx` — owned by ecom.
216
- - **Do NOT rewrite** `src/utils/categories.ts` or `src/components/CategoryRail.astro` — owned by `pages-categories`.
218
+ - **Do NOT rewrite** `src/utils/categories.ts` (pre-copied by the orchestrator — import only) or `src/components/CategoryRail.astro` (owned by `pages-categories`).
217
219
  - If home page already has a live query (another agent wired it), leave alone and note in return.
218
220
 
219
221
  ## Anti-patterns
@@ -224,4 +226,4 @@ Keep the marker comment immediately after the inserted `<li>` so other vertical
224
226
  | Call `/stores/v3/categories/query` | Use `categoriesV3` SDK, or fall back to `/categories/v1/categories/query` |
225
227
  | Invent category slugs that don't exist | Match real categories; fall back to `/products` for unmatched |
226
228
  | Pass flat props (`name={p.name}`) when ProductCard expects `product={...}` object | ProductCard is a template — always `<ProductCard product={p} />` with the raw SDK object |
227
- | `featured = products.map(p => ({name: p.name, ...}))` — flat-mapping SDK results | Store raw products: `featured = featuredProducts ?? []` as `any[]` |
229
+ | `featured = products.map(p => ({name: p.name, ...}))` — flat-mapping SDK results | Store raw products: `featured = featuredProducts ?? []` as `any[]` |
@@ -14,12 +14,14 @@ Files this agent MUST NOT touch:
14
14
  - `src/components/ProductPurchase.tsx`, `src/components/AddToCartButton.tsx` — owned by `components`
15
15
  - `src/pages/cart.astro`, `src/pages/thank-you.astro` — owned by `pages-cart-checkout`
16
16
  - `src/pages/index.astro`, `src/components/Navigation.astro` — owned by `pages-home-and-nav`
17
+ - `src/components/CategoryRail.astro` — owned by `pages-categories`. **Import** from `../../components/CategoryRail.astro`; never `Write` it. If it's not on disk yet when you go to mount it, that means the orchestrator dispatched scopes out of order — return `status: "partial"` with `errors: [{ code: "MISSING_PAGES_CATEGORIES_OUTPUT", path: "src/components/CategoryRail.astro" }]` (never defensively `Write` it yourself — `pages-categories` is the only writer, and racing it trips the harness staleness guard).
18
+ - `src/utils/categories.ts` — pre-copied by the orchestrator before Phase 4 (BUILD.md Step 7 pre-batch). **Import** `listStoreCategories`/etc. from `../../utils/categories`; never `Write` it.
17
19
  - `global.css`, any other `.astro` page, any other component — owned by designers
18
20
 
19
21
  ## Inputs (from parent prompt)
20
22
 
21
23
  - **Phase 1 return data** — `products: [{id, name, slug, variantId, price, inventory, sku}]` — use slugs when needed (rarely; `queryProducts` returns them already).
22
- - **Design tokens** — read `.wix/site.json.designTokens` for the published color/spacing/typography vocabulary; compose Tailwind utilities derived from those tokens (`class="py-4xl flex flex-col gap-md font-display"`) at the call site rather than inventing semantic classes for layout/spacing/typography. Retained global semantic classes are limited to compound patterns (`offer-callout`, `cart-summary`), interactive primitives (`btn-primary`, `product-card`), and JS targets — see `references/shared/STYLING.md`.
24
+ - **Design tokens** — the full `designTokens` JSON is inlined in your prompt for the published color/spacing/typography vocabulary; compose Tailwind utilities derived from those tokens (`class="py-4xl flex flex-col gap-md font-display"`) at the call site rather than inventing semantic classes for layout/spacing/typography. Retained global semantic classes are limited to compound patterns (`offer-callout`, `cart-summary`), interactive primitives (`btn-primary`, `product-card`), and JS targets — see `references/shared/STYLING.md`.
23
25
  - **Designer output summary** — paths of existing `products/index.astro`, `products/[slug].astro`, `ProductCard.astro` with placeholder data.
24
26
 
25
27
  ## Critical rules (all must be honored)
@@ -72,7 +74,7 @@ Preserves the designer's page structure (class names, layout) and replaces the p
72
74
 
73
75
  > **Page size 24** — multiple of the 2/3/4-column grid, well under Wix's per-request cap of 100. Do not change without updating `CATEGORY_PAGES.md` to match.
74
76
 
75
- > **No client-side filter.** The previous "ship every product, hide non-matching cards via JS" pattern is gone — it doesn't scale and breaks SEO. Do not reintroduce `data-category-ids` on `<ProductCard>` or any DOM-hide script. Filtering is done by navigating to `/category/<slug>` (a real route), and `<ClientRouter />` from the designer's Layout handles the swap.
77
+ > **No client-side filter.** Do not ship every product and hide non-matching cards via JS — it doesn't scale and breaks SEO. Do not add `data-category-ids` on `<ProductCard>` or any DOM-hide script. Filtering is done by navigating to `/category/<slug>` (a real route), and `<ClientRouter />` from the designer's Layout handles the swap.
76
78
 
77
79
  > **Why the double-script pattern:** Listing page is server-rendered but `AddProductImpression` must fire in the browser. The server-computed payload is serialized into an inert JSON `<script>` (`is:inline`) and read by a separate processed `<script>` (bundled by Astro — has ES `import`). `define:vars` + inline-script combinations cannot do ES imports.
78
80
 
@@ -210,4 +212,4 @@ If any of `wixMetadataExported`, `seoTagsMounted`, `useGetProductBySlug` ends up
210
212
  | Pass `"INVENTORY"` in the `fields` array | No such enum value exists for `productsV3`. Valid values: `URL`, `CURRENCY`, `INFO_SECTION`, `MERCHANT_DATA`, `PLAIN_DESCRIPTION`, `INFO_SECTION_PLAIN_DESCRIPTION`, `SUBSCRIPTION_PRICES_INFO`, `BREADCRUMBS_INFO`, `WEIGHT_MEASUREMENT_UNIT_INFO`, `VARIANT_OPTION_CHOICE_NAMES`, `MEDIA_ITEMS_INFO`, `DESCRIPTION`, `DIRECT_CATEGORIES_INFO`, `ALL_CATEGORIES_INFO`, `INFO_SECTION_DESCRIPTION`, `THUMBNAIL`, `PRODUCT_CHOICES_MEDIA_REFERENCES`. Passing an invalid value makes the query throw. |
211
213
  | Trust `variantsInfo[].inventoryStatus.inStock` as the OOS gate | It's a stale cached flag — a variant with real quantity 0 can still report `inStock: true`. Query `inventoryItemsV3.queryInventoryItems({ filter: { productId } })` at SSR and pass a `variantId → { quantity, trackQuantity, preorderEnabled }` map into `ProductPurchase`. The template already does this. |
212
214
  | Skip the `backInStockEnabled` prop on `<ProductPurchase>` | Always pass it (template already imports `getBackInStockEnabled`). When the prop is missing, the OOS subscribe form never renders even if the merchant has enabled collecting requests. |
213
- | Pass the formatted price string (`"$695"`) as `priceAmount` | Pass the numeric `priceAmount` already computed in frontmatter. The Wix back-in-stock service rejects formatted prices with `400 DECIMAL_GTE`. |
215
+ | Pass the formatted price string (`"$695"`) as `priceAmount` | Pass the numeric `priceAmount` already computed in frontmatter. The Wix back-in-stock service rejects formatted prices with `400 DECIMAL_GTE`. |
@@ -94,7 +94,7 @@ Handles variant selection, quantity selector, stock awareness, and wraps `AddToC
94
94
  <ProductPurchase client:load product={product} inventoryByVariant={inventoryByVariant} />
95
95
  ```
96
96
 
97
- **Prop contract — single `product` object.** The template accepts the full productsV3 product and destructures internally. This mirrors `ProductCard.astro`'s `{ product }` contract so both stores components take the same shape (prevents the regression observed in an earlier run where a fallback-written `[slug].astro` passed `product` as a whole when the component expected flat props).
97
+ **Prop contract — single `product` object.** The template accepts the full productsV3 product and destructures internally. This mirrors `ProductCard.astro`'s `{ product }` contract so both stores components take the same shape (prevents a shape mismatch where a fallback-written `[slug].astro` passes `product` as a whole while the component expects flat props).
98
98
 
99
99
  Key behaviors:
100
100
  - `hasMeaningfulOptions` — a product has meaningful options only when at least one option has >1 choice. Dummy single-choice options (e.g., "Type: Standard") are treated as no options.
@@ -159,6 +159,6 @@ Classes from contract (stores pack):
159
159
  | Default Tailwind color utilities on React islands (`bg-green-50`, `bg-blue-500`) | Brand `@theme` utilities (`bg-bark`, `text-cream`) or contract class names |
160
160
  | `<!--` HTML comments in `.astro` frontmatter | `//` or `/* */` — frontmatter is TypeScript |
161
161
  | Omit `WIX_STORES_APP_ID` constant | Hardcoded `215238eb-22a5-4c36-9e7b-e7c08025e04e` in AddToCartButton for `catalogReference.appId` |
162
- | Introspect `node_modules/@wix/*` | All symbols are documented here; if missing, call `<prefix>SearchWixSDKDocumentation` |
162
+ | Introspect `node_modules/@wix/*` | All symbols are documented here; if missing, use docs-search REST (see `DOCS_SEARCH.md`) |
163
163
  | Write `CartView.tsx`, `CartBadge.tsx`, or `analytics.ts` | Not owned by this scope — do not write |
164
- | Pass flat props to `ProductPurchase` (`productId`, `options`, `variantsInfo`, …) | Pass the whole product: `<ProductPurchase product={product} inventoryByVariant={inventoryByVariant} />` |
164
+ | Pass flat props to `ProductPurchase` (`productId`, `options`, `variantsInfo`, …) | Pass the whole product: `<ProductPurchase product={product} inventoryByVariant={inventoryByVariant} />` |
@@ -0,0 +1,27 @@
1
+ ---
2
+ // ── Composer skeleton: src/components/Footer.astro ────────────────────────────
3
+ // Substitutions (see COMPOSE.md § "5. Footer.astro"):
4
+ // {{brand.name}} — brand name for the wordmark + copyright.
5
+ // {{shell.footerTagline}} — short brand-voice tagline from data.shell.
6
+ // {{nav.links}} — same inlined Navigation links array (mirror/subset);
7
+ // one <a href={href}>{label}</a> per entry, labels VERBATIM. No cart,
8
+ // login, or account links.
9
+ // Fixed bulk (keep literal): transition:persist, the year expression.
10
+ const year = new Date().getFullYear();
11
+ ---
12
+ <footer class="site-footer" transition:persist="site-footer">
13
+ <div class="max-w-6xl mx-auto px-lg py-3xl flex flex-col md:flex-row md:items-start md:justify-between gap-xl">
14
+ <div class="flex flex-col gap-sm max-w-prose">
15
+ <span class="font-display text-lg text-ink">{{brand.name}}</span>
16
+ <p class="text-sm">{{shell.footerTagline}}</p>
17
+ </div>
18
+ <nav>
19
+ <ul class="flex flex-col gap-sm text-sm">
20
+ {{nav.links}}
21
+ </ul>
22
+ </nav>
23
+ </div>
24
+ <div class="max-w-6xl mx-auto px-lg pb-xl text-xs">
25
+ <p>© {year} {{brand.name}}. All rights reserved.</p>
26
+ </div>
27
+ </footer>
@@ -0,0 +1,132 @@
1
+ ---
2
+ // ── Composer skeleton: src/layouts/Layout.astro ──────────────────────────────
3
+ // Fully replaces the scaffold's bare stub. The <script> below and the View
4
+ // Transitions wiring are LITERAL fixed bulk — do not re-author. Composer's only
5
+ // substitutions (see COMPOSE.md § "3. Layout.astro"):
6
+ // {{components-css-imports}} — one `import '../styles/components-<pack>.css';`
7
+ // per pack in "Packs with components" (omit entirely when none).
8
+ // {{fonts.googleHref}} — the Google Fonts <link> href built from designTokens
9
+ // .fonts (display + body families). Omit the <link> if fonts are system.
10
+ // {{brand.name}} — default <title>.
11
+ import '../styles/global.css';
12
+ {{components-css-imports}}
13
+ import { ClientRouter } from 'astro:transitions';
14
+ import Navigation from '../components/Navigation.astro';
15
+ import Footer from '../components/Footer.astro';
16
+
17
+ interface Props {
18
+ title?: string;
19
+ description?: string;
20
+ hasSeoTags?: boolean;
21
+ }
22
+ const { title, description, hasSeoTags = false } = Astro.props;
23
+ ---
24
+ <!doctype html>
25
+ <html lang="en">
26
+ <head>
27
+ <meta charset="utf-8" />
28
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
29
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E" />
30
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
31
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
32
+ <link rel="stylesheet" href="{{fonts.googleHref}}" />
33
+ {!hasSeoTags && (
34
+ <>
35
+ <title>{title ? `${title} · {{brand.name}}` : "{{brand.name}}"}</title>
36
+ {description && <meta name="description" content={description} />}
37
+ </>
38
+ )}
39
+ <slot name="head" />
40
+ <ClientRouter />
41
+ </head>
42
+ <body>
43
+ <div class="nav-progress" data-nav-progress aria-hidden="true"></div>
44
+ <Navigation />
45
+ <main><slot /></main>
46
+ <Footer />
47
+ <script>
48
+ // Persisted rail aria-current sync + top loading bar + rail-anchored
49
+ // scroll across listing-to-listing navigation. Stores pack relies on
50
+ // all three; do not split into separate scripts.
51
+ function syncCategoryRail() {
52
+ const path = window.location.pathname;
53
+ const activeSlug = path.startsWith("/category/")
54
+ ? path.slice("/category/".length).replace(/\/$/, "")
55
+ : path === "/products" || path === "/products/"
56
+ ? ""
57
+ : null;
58
+ if (activeSlug === null) return;
59
+ const pills = document.querySelectorAll<HTMLAnchorElement>(
60
+ "[data-category-rail] .category-pill",
61
+ );
62
+ for (const pill of pills) {
63
+ const slug = pill.dataset.categorySlug ?? "";
64
+ if (slug === activeSlug) pill.setAttribute("aria-current", "page");
65
+ else pill.removeAttribute("aria-current");
66
+ }
67
+ }
68
+ // Eager click feedback — flip aria-current before the network call.
69
+ document.addEventListener("click", (event) => {
70
+ const target = event.target as HTMLElement | null;
71
+ const pill = target?.closest<HTMLAnchorElement>(
72
+ "[data-category-rail] .category-pill",
73
+ );
74
+ if (!pill) return;
75
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
76
+ const pills = document.querySelectorAll<HTMLAnchorElement>(
77
+ "[data-category-rail] .category-pill",
78
+ );
79
+ for (const p of pills) p.removeAttribute("aria-current");
80
+ pill.setAttribute("aria-current", "page");
81
+ }, true);
82
+ const progress = document.querySelector<HTMLElement>("[data-nav-progress]");
83
+ function startProgress() {
84
+ if (!progress) return;
85
+ progress.dataset.state = "loading";
86
+ document.body.dataset.navigating = "true";
87
+ }
88
+ function endProgress() {
89
+ if (!progress) return;
90
+ progress.dataset.state = "done";
91
+ delete document.body.dataset.navigating;
92
+ window.setTimeout(() => {
93
+ if (progress.dataset.state === "done") delete progress.dataset.state;
94
+ }, 320);
95
+ }
96
+ // Anchor the persisted rail across listing-to-listing navigation. The
97
+ // page-header above the rail differs between /products and /category/[slug]
98
+ // (breadcrumbs, lede, optional image), so naive scroll preservation reads
99
+ // as a jump. Capture rail.getBoundingClientRect().top before the swap and
100
+ // re-equalize after.
101
+ const isListing = (p: string) =>
102
+ p === "/products" || p === "/products/" || p.startsWith("/category/");
103
+ let railAnchorTop: number | null = null;
104
+ document.addEventListener("astro:before-preparation", (event: any) => {
105
+ const from = window.location.pathname;
106
+ const to = event?.to?.pathname ?? from;
107
+ const rail = document.querySelector<HTMLElement>("[data-category-rail]");
108
+ railAnchorTop =
109
+ rail && isListing(from) && isListing(to)
110
+ ? rail.getBoundingClientRect().top
111
+ : null;
112
+ startProgress();
113
+ });
114
+ document.addEventListener("astro:after-swap", () => {
115
+ syncCategoryRail();
116
+ if (railAnchorTop !== null) {
117
+ const rail = document.querySelector<HTMLElement>("[data-category-rail]");
118
+ if (rail) {
119
+ const delta = rail.getBoundingClientRect().top - railAnchorTop;
120
+ if (Math.abs(delta) > 0.5) {
121
+ window.scrollBy({ top: delta, left: 0, behavior: "instant" as ScrollBehavior });
122
+ }
123
+ }
124
+ }
125
+ railAnchorTop = null;
126
+ endProgress();
127
+ });
128
+ document.addEventListener("astro:page-load", endProgress);
129
+ syncCategoryRail();
130
+ </script>
131
+ </body>
132
+ </html>
@@ -0,0 +1,38 @@
1
+ ---
2
+ // ── Composer skeleton: src/components/Navigation.astro ────────────────────────
3
+ // Substitutions (see COMPOSE.md § "4. Navigation.astro"):
4
+ // {{shell.navBrandMark}} — brand mark / wordmark text from data.shell.
5
+ // {{nav.links}} — one <a href={href}>{label}</a> per entry in the inlined
6
+ // Navigation links array, labels VERBATIM (no editorial rebrands). Render
7
+ // each inside a <li class="site-nav-item">.
8
+ // Fixed bulk (keep literal): transition:persist, the <!-- nav:links --> marker,
9
+ // the empty <div class="nav-actions"> mount, the mobile hamburger toggle.
10
+ ---
11
+ <header class="site-nav" transition:persist="site-nav">
12
+ <nav class="max-w-6xl mx-auto px-lg flex items-center justify-between gap-lg py-md">
13
+ <a href="/" class="font-display text-lg tracking-tight">{{shell.navBrandMark}}</a>
14
+
15
+ <input type="checkbox" id="nav-toggle" class="peer hidden" aria-hidden="true" />
16
+ <label
17
+ for="nav-toggle"
18
+ class="md:hidden inline-flex flex-col gap-[5px] cursor-pointer"
19
+ aria-label="Toggle navigation"
20
+ >
21
+ <span class="block h-[2px] w-6 bg-ink"></span>
22
+ <span class="block h-[2px] w-6 bg-ink"></span>
23
+ <span class="block h-[2px] w-6 bg-ink"></span>
24
+ </label>
25
+
26
+ <div
27
+ class="hidden peer-checked:flex md:flex absolute md:static top-full left-0 right-0 md:right-auto
28
+ flex-col md:flex-row gap-md md:gap-lg items-start md:items-center
29
+ bg-paper md:bg-transparent border-b md:border-0 border-rule px-lg md:px-0 py-md md:py-0"
30
+ >
31
+ <ul class="flex flex-col md:flex-row gap-md md:gap-lg items-start md:items-center">
32
+ {{nav.links}}
33
+ <!-- nav:links -->
34
+ </ul>
35
+ <div class="nav-actions"></div>
36
+ </div>
37
+ </nav>
38
+ </header>
@@ -0,0 +1,41 @@
1
+ // ── Composer skeleton: astro.config.mjs ───────────────────────────────────────
2
+ // UNLIKE the other skeletons, this one is a MERGE TARGET, not a clobber. The
3
+ // scaffold's generated astro.config.mjs varies (integrations args, image.domains,
4
+ // vite.server settings differ run to run). Composer must NOT overwrite it with
5
+ // this file — it applies exactly two mutations to the scaffold's own config and
6
+ // preserves everything else (see COMPOSE.md § "2. astro.config.mjs"):
7
+ //
8
+ // (1) register the Tailwind v4 Vite plugin → vite.plugins: [tailwindcss()]
9
+ // (2) fix the bare `process.env` reference → globalThis guard (TS-safe)
10
+ //
11
+ // The shape below is the canonical post-mutation result for a typical scaffold —
12
+ // use it as the reference for what those two edits should produce.
13
+ // @ts-check
14
+ import { defineConfig } from "astro/config";
15
+ import wix from "@wix/astro";
16
+ import wixPages from "@wix/astro-pages";
17
+ import react from "@astrojs/react";
18
+ import cloudProviderFetchAdapter from "@wix/cloud-provider-fetch-adapter";
19
+ import tailwindcss from "@tailwindcss/vite"; // (1) added by Composer
20
+
21
+ // (2) `process.env` guarded so strict `tsc --noEmit` does not fail with
22
+ // "Cannot find name 'process'" without an @types/node dependency.
23
+ const isBuild =
24
+ (/** @type {any} */ (globalThis)).process?.env?.NODE_ENV === "production";
25
+
26
+ // https://astro.build/config
27
+ export default defineConfig({
28
+ integrations: [wix(), wixPages(), react()],
29
+ security: { checkOrigin: false },
30
+ ...(isBuild && { adapter: cloudProviderFetchAdapter({}) }),
31
+
32
+ image: {
33
+ domains: ["static.wixstatic.com"],
34
+ },
35
+
36
+ vite: {
37
+ plugins: [tailwindcss()], // (1) merge into any existing vite config
38
+ },
39
+
40
+ output: "server",
41
+ });