@wix/agent-skills 1.6.0 → 1.8.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 (195) hide show
  1. package/README.md +5 -9
  2. package/package.json +1 -1
  3. package/skills/wix-app/SKILL.md +51 -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/STORES_VERSIONING.md +1 -0
  16. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +0 -44
  17. package/skills/wix-app/references/custom-element-widget/SETTINGS_PANEL.md +19 -330
  18. package/skills/wix-app/references/dashboard-menu-plugin/bookings-slots.md +0 -12
  19. package/skills/wix-app/references/dashboard-menu-plugin/ecommerce-slots.md +7 -0
  20. package/skills/wix-app/references/dashboard-menu-plugin/restaurants-slots.md +0 -12
  21. package/skills/wix-app/references/dashboard-plugin/SLOTS.md +3 -15
  22. package/skills/wix-app/references/service-plugin/ADDITIONAL-FEES.md +2 -18
  23. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +2 -42
  24. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +1 -11
  25. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +1 -11
  26. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +2 -40
  27. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +2 -19
  28. package/skills/wix-app/references/service-plugin/VALIDATIONS.md +2 -18
  29. package/skills/wix-app/references/site-plugin/SLOTS.md +17 -68
  30. package/skills/wix-design-system/SKILL.md +4 -0
  31. package/skills/wix-headless/SKILL.md +131 -386
  32. package/skills/wix-headless/references/BUILD-astro.md +246 -0
  33. package/skills/wix-headless/references/BUILD-own-build.md +167 -0
  34. package/skills/wix-headless/references/BUILD.md +105 -0
  35. package/skills/wix-headless/references/DESIGN_SYSTEM.md +175 -0
  36. package/skills/wix-headless/references/DISCOVERY-connect.md +55 -0
  37. package/skills/wix-headless/references/DISCOVERY-create.md +238 -0
  38. package/skills/wix-headless/references/DISCOVERY.md +50 -306
  39. package/skills/wix-headless/references/PLAN-connect.md +19 -0
  40. package/skills/wix-headless/references/PLAN-create.md +17 -0
  41. package/skills/wix-headless/references/PLAN.md +92 -0
  42. package/skills/wix-headless/references/SEED.md +214 -0
  43. package/skills/wix-headless/references/SETUP.md +73 -248
  44. package/skills/wix-headless/references/{blog → astro/blog}/BLOG_PAGES.md +6 -5
  45. package/skills/wix-headless/references/{blog → astro/blog}/BLOG_SETUP.md +2 -2
  46. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +337 -0
  47. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +428 -0
  48. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +214 -0
  49. package/skills/wix-headless/references/{cms → astro/cms}/FAQ_KNOWLEDGE_BASE.md +14 -12
  50. package/skills/wix-headless/references/{cms → astro/cms}/PORTFOLIO.md +15 -16
  51. package/skills/wix-headless/references/{cms → astro/cms}/RESOURCE_LIBRARY.md +13 -15
  52. package/skills/wix-headless/references/{cms → astro/cms}/TEAM_DIRECTORY.md +11 -11
  53. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +354 -0
  54. package/skills/wix-headless/references/{ecom → astro/ecom}/CART_PAGES.md +8 -9
  55. package/skills/wix-headless/references/{ecom → astro/ecom}/CART_WIRING.md +6 -6
  56. package/skills/wix-headless/references/{ecom → astro/ecom}/COMPONENTS_CSS.md +6 -6
  57. package/skills/wix-headless/references/{forms → astro/forms}/CONTACT_FORM.md +18 -32
  58. package/skills/wix-headless/references/{gift-cards → astro/gift-cards}/COMPONENTS.md +3 -3
  59. package/skills/wix-headless/references/{gift-cards → astro/gift-cards}/PAGES.md +2 -2
  60. package/skills/wix-headless/references/{stores → astro/stores}/BACK_IN_STOCK.md +7 -7
  61. package/skills/wix-headless/references/{stores → astro/stores}/CATEGORY_PAGES.md +12 -13
  62. package/skills/wix-headless/references/{stores → astro/stores}/COMPONENTS_CSS.md +7 -7
  63. package/skills/wix-headless/references/{stores → astro/stores}/HOME_AND_NAV.md +11 -9
  64. package/skills/wix-headless/references/{stores → astro/stores}/PRODUCT_PAGES.md +11 -9
  65. package/skills/wix-headless/references/{stores → astro/stores}/SHARED_WIRING.md +8 -7
  66. package/skills/wix-headless/references/astro/templates/Footer.astro +27 -0
  67. package/skills/wix-headless/references/astro/templates/Layout.astro +132 -0
  68. package/skills/wix-headless/references/astro/templates/Navigation.astro +38 -0
  69. package/skills/wix-headless/references/astro/templates/astro.config.mjs +41 -0
  70. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +218 -0
  71. package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +194 -0
  72. package/skills/wix-headless/references/astro/templates/bookings/ManageBooking.tsx +84 -0
  73. package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +25 -0
  74. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +50 -0
  75. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +45 -0
  76. package/skills/wix-headless/references/astro/templates/bookings/api/confirm-booking.ts +34 -0
  77. package/skills/wix-headless/references/astro/templates/bookings/api/waitlist.ts +74 -0
  78. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +111 -0
  79. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +413 -0
  80. package/skills/wix-headless/references/astro/templates/bookings/manage-booking.astro +76 -0
  81. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +81 -0
  82. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +65 -0
  83. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +302 -0
  84. package/skills/wix-headless/references/astro/templates/global.css +286 -0
  85. package/skills/wix-headless/references/astro/templates/index.astro +56 -0
  86. package/skills/wix-headless/{templates → references/astro/templates}/stores/back-in-stock.ts +1 -1
  87. package/skills/wix-headless/{templates → references/astro/templates}/stores/components-stores.css +138 -33
  88. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +28 -19
  89. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +6 -6
  90. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +106 -0
  91. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +295 -0
  92. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +35 -232
  93. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +39 -8
  94. package/skills/wix-headless/references/commands/known-apps.json +2 -1
  95. package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +142 -0
  96. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +88 -0
  97. package/skills/wix-headless/references/custom/blog/WIRING.md +52 -0
  98. package/skills/wix-headless/references/custom/bookings/WIRING.md +88 -0
  99. package/skills/wix-headless/references/custom/cms/WIRING.md +97 -0
  100. package/skills/wix-headless/references/custom/ecom/WIRING.md +67 -0
  101. package/skills/wix-headless/references/custom/forms/WIRING.md +101 -0
  102. package/skills/wix-headless/references/custom/stores/WIRING.md +80 -0
  103. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +12 -12
  104. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +6 -6
  105. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +13 -13
  106. package/skills/wix-headless/references/images/INSTRUCTIONS.md +58 -60
  107. package/skills/wix-headless/references/seed-recipes.md +49 -0
  108. package/skills/wix-headless/references/shared/AGENTS_MD.md +47 -0
  109. package/skills/wix-headless/references/shared/AUTHENTICATION.md +108 -0
  110. package/skills/wix-headless/references/shared/BUILD_NOISE.md +2 -2
  111. package/skills/wix-headless/references/shared/DESIGN_MD.md +85 -0
  112. package/skills/wix-headless/references/shared/DOCS_SEARCH.md +41 -0
  113. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +40 -39
  114. package/skills/wix-headless/references/shared/IMPLEMENTER.md +92 -41
  115. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +3 -3
  116. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +32 -312
  117. package/skills/wix-headless/references/shared/STYLING.md +48 -21
  118. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +59 -29
  119. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +31 -28
  120. package/skills/wix-headless/references/verticals/_schema.json +31 -117
  121. package/skills/wix-headless/references/verticals/_schema.md +60 -150
  122. package/skills/wix-headless/references/verticals/blog.md +5 -99
  123. package/skills/wix-headless/references/verticals/bookings.md +41 -0
  124. package/skills/wix-headless/references/verticals/cms.md +9 -100
  125. package/skills/wix-headless/references/verticals/ecom.md +6 -77
  126. package/skills/wix-headless/references/verticals/forms.md +5 -85
  127. package/skills/wix-headless/references/verticals/gift-cards.md +6 -103
  128. package/skills/wix-headless/references/verticals/stores.md +10 -144
  129. package/skills/wix-headless/scripts/check-manifest.mjs +148 -11
  130. package/skills/wix-headless/scripts/compose.mjs +540 -0
  131. package/skills/wix-headless/scripts/emit-design-tokens.mjs +136 -53
  132. package/skills/wix-headless/scripts/flatten.sh +61 -0
  133. package/skills/wix-headless/scripts/generate-images.mjs +242 -0
  134. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +67 -43
  135. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +3 -3
  136. package/skills/wix-headless/scripts/scaffold.sh +113 -27
  137. package/skills/wix-headless/scripts/seed-utilities.sh +50 -12
  138. package/skills/wix-headless/scripts/write-decorative-json.mjs +62 -0
  139. package/skills/wix-manage/SKILL.md +4 -8
  140. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +2 -0
  141. package/skills/wix-manage/references/cms/cms-data-items-crud.md +4 -0
  142. package/skills/wix-manage/references/cms/cms-references-and-relationships.md +2 -0
  143. package/skills/wix-manage/references/cms/cms-schema-management.md +4 -0
  144. package/skills/wix-manage/references/domains/domain-search-and-purchase.md +10 -7
  145. package/skills/wix-manage/references/ecommerce/api-shipping.md +443 -0
  146. package/skills/wix-manage/references/ecommerce/flow-add-free-shipping.md +5 -6
  147. package/skills/wix-manage/references/ecommerce/flow-fix-coverage-gaps.md +4 -5
  148. package/skills/wix-manage/references/ecommerce/flow-optimize-shipping-rates.md +4 -5
  149. package/skills/wix-manage/references/ecommerce/goal-increase-aov.md +1 -1
  150. package/skills/wix-manage/references/ecommerce/goal-reduce-cart-abandonment.md +1 -2
  151. package/skills/wix-manage/references/ecommerce/guardrail-shipping-health.md +2 -2
  152. package/skills/wix-manage/references/ecommerce/recipe-apply-shipping-recommendations.md +4 -5
  153. package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +7 -7
  154. package/skills/wix-manage/references/ecommerce/setup-discount-rules.md +209 -72
  155. package/skills/wix-manage/references/ecommerce/setup-store-pickup-location.md +9 -10
  156. package/skills/wix-manage/references/ecommerce/skill-graph.md +4 -4
  157. package/skills/wix-manage/references/forms/create-form.md +50 -0
  158. package/skills/wix-manage/references/stores/bulk-create-products-with-options.md +2 -0
  159. package/skills/wix-manage/references/stores/create-product-from-image.md +91 -38
  160. package/skills/wix-manage/references/stores/setup-online-store-catalog-v3.md +2 -0
  161. package/skills/wix-app/references/custom-element-widget/default-thumbnail.png +0 -0
  162. package/skills/wix-app/references/data-collection/extension-template.ts +0 -107
  163. package/skills/wix-headless/references/ORCHESTRATION.md +0 -269
  164. package/skills/wix-headless/references/commands/install-app.md +0 -42
  165. package/skills/wix-headless/references/commands/mcp-bootstrap.md +0 -28
  166. package/skills/wix-headless/references/designer/INSTRUCTIONS.md +0 -828
  167. package/skills/wix-headless/references/shared/MCP_PREFIX.md +0 -105
  168. package/skills/wix-headless/scripts/copy-utility-templates.mjs +0 -153
  169. package/skills/wix-headless/scripts/finalize-run-json.mjs +0 -141
  170. package/skills/wix-headless/scripts/init-site-json.mjs +0 -63
  171. package/skills/wix-headless/scripts/preview.sh +0 -45
  172. package/skills/wix-headless/scripts/release.sh +0 -73
  173. package/skills/wix-headless/templates/ecom/components-ecom.css +0 -215
  174. package/skills/wix-manage/references/events/list-events.md +0 -203
  175. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/CartBadge.tsx +0 -0
  176. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/CartView.tsx +0 -0
  177. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/cart.astro +0 -0
  178. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/discounts.ts +0 -0
  179. /package/skills/wix-headless/{templates → references/astro/templates}/ecom/thank-you.astro +0 -0
  180. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/GiftCardPurchase.tsx +0 -0
  181. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/_home-teaser-snippet.astro +0 -0
  182. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/_nav-snippet.astro +0 -0
  183. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/components-gift-cards.css +0 -0
  184. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/gift-cards.astro +0 -0
  185. /package/skills/wix-headless/{templates → references/astro/templates}/gift-cards/gift-cards.ts +0 -0
  186. /package/skills/wix-headless/{templates → references/astro/templates}/stores/AddToCartButton.tsx +0 -0
  187. /package/skills/wix-headless/{templates → references/astro/templates}/stores/BackInStockForm.tsx +0 -0
  188. /package/skills/wix-headless/{templates → references/astro/templates}/stores/CategoryRail.astro +0 -0
  189. /package/skills/wix-headless/{templates → references/astro/templates}/stores/ProductCard.astro +0 -0
  190. /package/skills/wix-headless/{templates → references/astro/templates}/stores/ProductPurchase.tsx +0 -0
  191. /package/skills/wix-headless/{templates → references/astro/templates}/stores/SeoTags.astro +0 -0
  192. /package/skills/wix-headless/{templates → references/astro/templates}/stores/categories.ts +0 -0
  193. /package/skills/wix-headless/{templates → references/astro/templates}/stores/category/[slug].astro +0 -0
  194. /package/skills/wix-headless/{templates → references/astro/templates}/stores/products/[slug].astro +0 -0
  195. /package/skills/wix-headless/{templates → references/astro/templates}/stores/products/index.astro +0 -0
@@ -1,6 +1,6 @@
1
1
  # Phase 3 Components — Gift Cards
2
2
 
3
- Launched in **Step 4.5** alongside other verticals' `components` scopes (after Phase 2 Design System). Writes the runtime probe utility, the buy-flow React island, and scoped CSS. Finishes before the Phase 4 Pages scopes run in Step 7.
3
+ This is the **components** portion of the gift-cards **merged build agent** (the build wave). Your agent writes the runtime probe utility, the buy-flow React island, and scoped CSS **first**, then its pages (`/gift-cards` route + Navigation/index patches) — so the island is on disk before the page mounts it. Because the page side patches the shared shells, the whole gift-cards agent runs in the build wave's **serialized shell chain** (`BUILD-astro.md` § "Step 4.5").
4
4
 
5
5
  ## Scope
6
6
 
@@ -18,7 +18,7 @@ Files this agent MUST NOT touch:
18
18
 
19
19
  ## Coordination: design tokens
20
20
 
21
- Your parent prompt includes the design tokens inline. Reference token CSS variables (`var(--color-cream)`, `var(--spacing-lg)`, etc.) from `components-gift-cards.css`. Do NOT read `.wix/design-tokens.css` from disk.
21
+ Read the design tokens from `.wix/design-tokens.css` (on disk, gate-verified present before the wave). Reference token CSS variables (`var(--color-cream)`, `var(--spacing-lg)`, etc.) from `components-gift-cards.css`.
22
22
 
23
23
  ## Critical rules
24
24
 
@@ -116,4 +116,4 @@ Use brand `@theme` utilities (`bg-cream`, `text-ink`, etc.) where natural; fall
116
116
  | Throw or log+rethrow on probe failure | Return `null`; callers gate the UI on null |
117
117
  | Hardcode denomination amounts (€10, €25, etc.) | Always render from `product.presetVariants` |
118
118
  | Skip `wixGiftCardsAppNewCatalog: true` in cart options | Required — without it the cart line is the wrong item type and `ORDER_PAID` does not issue a gift card |
119
- | Write your own `wix-image.ts` / `analytics.ts` | Import from the shared utilities |
119
+ | Write your own `wix-image.ts` / `analytics.ts` | Import from the shared utilities |
@@ -1,6 +1,6 @@
1
1
  # Phase 4 Pages — Gift Cards
2
2
 
3
- Launched in **Step 7** alongside other verticals' `pages` scopes. Writes the `/gift-cards` route and patches `Navigation.astro` + `index.astro` at their declared markers. The Components scope's outputs (`src/utils/gift-cards.ts`, `src/components/GiftCardPurchase.tsx`, `src/styles/components-gift-cards.css`) must already exist before this scope runs.
3
+ The **pages** portion of the gift-cards **merged build agent** (the build wave) — written *after* its `components`. Writes the `/gift-cards` route and patches `Navigation.astro` + `index.astro` at their declared markers. Because it patches the shared shells, the gift-cards agent runs in the build wave's **serialized shell chain** (one shell-patcher at a time — `BUILD-astro.md` § "Step 4.5"). The components outputs (`src/utils/gift-cards.ts`, `src/components/GiftCardPurchase.tsx`, `src/styles/components-gift-cards.css`) were written earlier in this same agent, so they're already on disk.
4
4
 
5
5
  ## Scope
6
6
 
@@ -126,4 +126,4 @@ If a marker is missing, return `status: "partial"` with `errors: [{ code: "MARKE
126
126
  | Replace the marker comment with the inserted snippet | Insert AFTER the marker; preserve the marker line |
127
127
  | Move CSS into `<style>` blocks inside `.astro` files | Page/teaser CSS lives in `components-gift-cards.css` (Components scope) |
128
128
  | Hardcode `<title>"Gift Cards"</title>` | Use `title={\`${product.name}\`}` so the dashboard owner controls naming |
129
- | Conditionally re-render the page when the app is enabled later | The Astro page is server-rendered each request — the probe runs every time, so dashboard changes are picked up without rebuild |
129
+ | Conditionally re-render the page when the app is enabled later | The Astro page is server-rendered each request — the probe runs every time, so dashboard changes are picked up without rebuild |
@@ -1,15 +1,17 @@
1
1
  # Phase 3 Components — Back in Stock (Stores)
2
2
 
3
- Split across the stores `components` scope (TSX/util files) and the `components-css` sibling (CSS rules). The matching Phase 4 wiring lives in `PRODUCT_PAGES.md` (SSR probe import + new props on `<ProductPurchase>`).
3
+ The stores `components` scope writes the TSX/util files; the CSS rules ship in the **pre-copied** `components-stores.css` template (no agent authors them). The matching page wiring lives in `PRODUCT_PAGES.md` (SSR probe import + new props on `<ProductPurchase>`). Both the components and that page wiring run inside the **same stores merged build agent** (the build wave), components first.
4
4
 
5
5
  ## Scope
6
6
 
7
7
  Files written for back-in-stock, by scope:
8
8
 
9
9
  **`components` scope** (see `./SHARED_WIRING.md`):
10
- - `src/utils/back-in-stock.ts` — SSR-elevated probe of the Wix back-in-stock service, plus the canonical Stores app id constant
11
10
  - `src/components/BackInStockForm.tsx` — React island that posts via `@wix/ecom`'s `backInStockNotifications.createBackInStockNotificationRequest`
12
11
 
12
+ **Pre-copied by the orchestrator** (do NOT author — same treatment as `categories.ts`):
13
+ - `src/utils/back-in-stock.ts` — SSR-elevated probe of the Wix back-in-stock service, plus the canonical Stores app id constant. Pre-copied into the project in the build-wave pre-batch (BUILD-astro.md § "Step 4.5"). **Import** `getBackInStockEnabled`/the app-id constants from `../utils/back-in-stock`; never `Write` it yourself (racing the pre-copy trips the harness staleness guard).
14
+
13
15
  **`components-css` scope** (see `./COMPONENTS_CSS.md`):
14
16
  - `src/styles/components-stores.css` — appends the back-in-stock form CSS rules at the end of the file (see § 3 below)
15
17
 
@@ -45,9 +47,9 @@ This scope uses **template files** instead of inline code. For each file below:
45
47
 
46
48
  Do NOT modify logic, imports, the bare-fields request shape, or the app-id constants.
47
49
 
48
- ### 1. `src/utils/back-in-stock.ts`
50
+ ### 1. `src/utils/back-in-stock.ts` — pre-copied, not owned by this scope
49
51
 
50
- Use template `templates/back-in-stock.ts`.
52
+ > Pre-copied by the orchestrator in the build-wave pre-batch (BUILD-astro.md § "Step 4.5") — same treatment as `categories.ts`. **Import** from `../utils/back-in-stock`; do NOT write it yourself. The exports below are documented here so callers (the form island, the `[slug].astro` probe) know the surface.
51
53
 
52
54
  Exports:
53
55
  - `WIX_STORES_BACK_IN_STOCK_APP_ID` — string constant. Use this for the `catalogReference.appId` in the form.
@@ -150,7 +152,6 @@ The full components scope return must mention back-in-stock:
150
152
  "summary": "Wrote stores islands, scoped CSS, back-in-stock probe + form",
151
153
  "data": {
152
154
  "islands": ["ProductPurchase.tsx", "AddToCartButton.tsx", "BackInStockForm.tsx"],
153
- "utils": ["back-in-stock.ts"],
154
155
  "scopedCssFile": "src/styles/components-stores.css",
155
156
  "backInStockWired": true
156
157
  },
@@ -159,7 +160,6 @@ The full components scope return must mention back-in-stock:
159
160
  "src/components/AddToCartButton.tsx",
160
161
  "src/components/ProductPurchase.tsx",
161
162
  "src/components/BackInStockForm.tsx",
162
- "src/utils/back-in-stock.ts",
163
163
  "src/styles/components-stores.css"
164
164
  ],
165
165
  "errors": []
@@ -175,4 +175,4 @@ The full components scope return must mention back-in-stock:
175
175
  | Send `"$385"` as `price` | Numeric string `"385"` only; the API rejects formatted prices with `400 DECIMAL_GTE` |
176
176
  | Wrap the subscribe call in `auth.elevate(...)` from the React island | Visitor scope is enough; elevation belongs only to the SSR probe |
177
177
  | Add a custom `src/pages/api/back-in-stock-subscribe.ts` route | Not needed — SDK from the island works. The Wix cloud adapter returned 403 on app-defined POST routes during the trial. |
178
- | Drop the module-memoization in `back-in-stock.ts` | Keep it; multiple SSR awaits in the same request coalesce into one `getSettings` call |
178
+ | Drop the module-memoization in `back-in-stock.ts` | Keep it; multiple SSR awaits in the same request coalesce into one `getSettings` call |
@@ -1,8 +1,8 @@
1
1
  # Phase 4 Category Pages — Stores
2
2
 
3
- Scope: `pages-categories`. Launched in **Step 7** alongside `pages-products` and `pages-home-and-nav`. This scope writes the dedicated category landing route and the shared `<CategoryRail/>` + `categories.ts` helper that `pages-products` and `pages-home-and-nav` also import.
3
+ Scope: `pages-categories` — written by the stores **merged build agent** (the build wave) *before* its `pages-products` scope, so `<CategoryRail/>` is on disk before that scope mounts it. This scope writes the dedicated category landing route and the shared `<CategoryRail/>`. The `categories.ts` helper is **pre-copied by the orchestrator in the build-wave pre-batch** (BUILD-astro.md § "Step 4.5") — do NOT write it here.
4
4
 
5
- **Dispatch:** all three stores Phase-4 scopes are dispatched in parallel — Astro resolves the cross-file imports at build time (Step 8). The orchestrator does not need to serialize. Each scope only needs its own declared files to exist by the time `astro build` runs.
5
+ **Within-agent order:** the merged stores agent writes `components` → `pages-categories` (this scope) → `pages-products`. `pages-home-and-nav` is a *separate* serialized agent (it patches the shared shells) and resolves `<CategoryRail/>` at build time (Step 8). Each scope only needs its own declared files to exist by the time `astro build` runs.
6
6
 
7
7
  ## Scope
8
8
 
@@ -10,7 +10,9 @@ Files this agent OWNS (writes):
10
10
 
11
11
  - `src/pages/category/[slug].astro` — category landing (server-side filtered, cursor-paginated)
12
12
  - `src/components/CategoryRail.astro` — shared rail + Prev/Next pagination, persisted across `<ClientRouter />` swaps
13
- - `src/utils/categories.ts` — TTL-cached helpers: `listStoreCategories`, `getCategoryBySlug`, `listProductsInCategory`
13
+
14
+ Files this agent imports but MUST NOT write:
15
+ - `src/utils/categories.ts` — TTL-cached helpers (`listStoreCategories`, `getCategoryBySlug`, `listProductsInCategory`). **Pre-copied by the orchestrator** before this phase (it's a static, brand-agnostic SDK wrapper); import the helpers, never author the file. Writing it races `pages-products`/`pages-home-and-nav`, which import the same path.
14
16
 
15
17
  Files this agent MUST NOT touch:
16
18
  - `src/pages/products/index.astro`, `[slug].astro`, `src/components/ProductCard.astro` — owned by `pages-products`
@@ -21,7 +23,7 @@ Files this agent MUST NOT touch:
21
23
  ## Inputs (from parent prompt)
22
24
 
23
25
  - **Phase 1 return data** — `categories: []`. Phase 1 does not seed categories (they're merchant-driven). This scope still writes the helper + rail + route — they're harmless when no categories exist, and they light up automatically once the merchant creates visible categories with items in the dashboard. `listStoreCategories()` queries the API live at SSR time (5-min TTL cache), so no redeploy is needed when categories are added later.
24
- - **Design tokens** — `.wix/site.json.designTokens` for the published vocabulary. Page header / breadcrumbs / pill / pagination styling should follow `references/shared/STYLING.md` (utilities derived from tokens, semantic classes only for primitives).
26
+ - **Design tokens** — read the design tokens (the DESIGN.md vocabulary) from `.wix/design-tokens.css` (on disk). Page header / breadcrumbs / pill / pagination styling should follow `references/shared/STYLING.md` (utilities derived from tokens, semantic classes only for primitives).
25
27
  - **Designer output summary** — confirm `Layout.astro` already includes `<ClientRouter />`, `transition:persist` markers on nav/footer, and the `[data-nav-progress]` element + after-swap hook. If any of those is missing, return `status: "partial"` with `errors: [{ code: "DESIGNER_LAYOUT_MISSING_TRANSITIONS", path: "src/layouts/Layout.astro" }]`.
26
28
 
27
29
  ## Critical rules (all must be honored)
@@ -31,18 +33,17 @@ Files this agent MUST NOT touch:
31
33
  3. **`queryCategories(...)` rejects empty filters.** The SDK builder's `.find()` validates that at least one predicate has been chained. Always include `.eq("visible", true)` (the constraint we want anyway). Provided template already does this.
32
34
  4. **Filter out the auto-managed "All Products" category** by `handle === "online_stores_all_products"`. It's installed by Wix Stores automatically and contains every product; surfacing it in the rail makes the All pill duplicate.
33
35
  5. **Filter out empty categories** by `itemCounter === 0` so the rail doesn't show buckets that 404 in practice (the route still works, but the pill leads to "Nothing in <name> just now").
34
- 6. **Use the Stores app id `215238eb-22a5-4c36-9e7b-e7c08025e04e`** as `STORES_APP_ID` in `categories.ts`. Same id used for cart ops and Phase 1 product seed. NOT the back-in-stock id `1380b703-…`.
36
+ 6. **`STORES_APP_ID` lives in the pre-copied `categories.ts`** — the template already sets it to the Stores app id `215238eb-22a5-4c36-9e7b-e7c08025e04e` (same id used for cart ops and Phase 1 product seed; NOT the back-in-stock id `1380b703-…`). You do not write that file; this is documented so the helpers you import behave as expected.
35
37
  7. **Cursor pagination** uses `productsV3.queryProducts().limit(24).skipTo(cursor)`. Cursor lives in `?cursor=…` on the URL, surfaced from `result.cursors.next` / `result.cursors.prev`. Prev/Next links use `data-astro-prefetch="hover"` so hovering them warms the cache.
36
38
  8. **Module-level TTL cache (5 min)** in `categories.ts` is opportunistic; safe under the Cloudflare-style fetch adapter (each worker isolate is single-tenant). Errors don't poison the cache.
37
39
  9. **Two-call pipeline** in `listProductsInCategory`: first `listItemsInCategory(categoryId, { appNamespace: "@wix/stores" })` for IDs, then `productsV3.queryProducts().in("_id", ids).limit(24).skipTo(cursor).find()`. There is no Wix endpoint that does category filter + cursor paging in one shot — don't attempt `listCategoriesForItems` from the SDK; it ships items via GET querystring and breaks on arrays. If you need product → categories mapping (e.g. for breadcrumbs on product detail), call the REST POST endpoint directly: `POST /categories/v1/categories/list-categories-for-items`.
38
40
 
39
41
  ## Writing the templates
40
42
 
41
- Read each template at `templates/stores/` and write it verbatim to the corresponding `src/` path, with three small adjustments:
43
+ Read each template at `references/astro/templates/stores/` and write it verbatim to the corresponding `src/` path, with three small adjustments. (`categories.ts` is **not** in this list — the orchestrator pre-copies it; you only import its helpers.)
42
44
 
43
45
  | Template path | Site path |
44
46
  |---|---|
45
- | `templates/categories.ts` | `src/utils/categories.ts` |
46
47
  | `templates/CategoryRail.astro` | `src/components/CategoryRail.astro` |
47
48
  | `templates/category/[slug].astro` | `src/pages/category/[slug].astro` |
48
49
 
@@ -54,13 +55,12 @@ Adjustments at the call site:
54
55
 
55
56
  ## Pre-return file-existence assertion
56
57
 
57
- Before returning `status: "complete"`, verify all three files exist:
58
+ Before returning `status: "complete"`, verify the two files you write exist:
58
59
 
59
- - `src/utils/categories.ts`
60
60
  - `src/components/CategoryRail.astro`
61
61
  - `src/pages/category/[slug].astro`
62
62
 
63
- If any is missing, return `status: "partial"` with `errors: [{ code: "PHASE4_FILE_MISSING", path: "<expected path>" }]`. The orchestrator's manifest check will also catch this, but an agent-side assertion gives a faster and more precise failure.
63
+ If either is missing, return `status: "partial"` with `errors: [{ code: "PHASE4_FILE_MISSING", path: "<expected path>" }]`. The orchestrator's manifest check will also catch this, but an agent-side assertion gives a faster and more precise failure. Also confirm the pre-copied `src/utils/categories.ts` is on disk (you import it); if it's missing, that's an orchestrator-side bug — return `status: "partial"` with `errors: [{ code: "UTILITY_TEMPLATE_NOT_PRECOPIED", path: "src/utils/categories.ts" }]` and do NOT write your own.
64
64
 
65
65
  ## Return contract
66
66
 
@@ -69,11 +69,10 @@ If any is missing, return `status: "partial"` with `errors: [{ code: "PHASE4_FIL
69
69
  "status": "complete",
70
70
  "phase": "stores-pages",
71
71
  "scope": "pages-categories",
72
- "summary": "Wrote shared CategoryRail + categories helper; /category/[slug] route renders M categories.",
72
+ "summary": "Wrote shared CategoryRail + /category/[slug] route (imports the pre-copied categories helper); route renders M categories.",
73
73
  "data": {
74
74
  "categoriesRendered": 0,
75
75
  "filesWritten": [
76
- "src/utils/categories.ts",
77
76
  "src/components/CategoryRail.astro",
78
77
  "src/pages/category/[slug].astro"
79
78
  ]
@@ -83,4 +82,4 @@ If any is missing, return `status: "partial"` with `errors: [{ code: "PHASE4_FIL
83
82
  }
84
83
  ```
85
84
 
86
- Phase 1 always reports zero categories (it does not seed them). Set `categoriesRendered: 0` and return `status: "complete"` — the helper, rail, and route are still written so the storefront lights up automatically the first time the merchant creates a visible category with items in the dashboard, with no code change needed.
85
+ Phase 1 always reports zero categories (it does not seed them). Set `categoriesRendered: 0` and return `status: "complete"` — the helper, rail, and route are still written so the storefront lights up automatically the first time the merchant creates a visible category with items in the dashboard, with no code change needed.
@@ -1,6 +1,6 @@
1
1
  # Phase 3 Components-CSS — Stores
2
2
 
3
- Sibling of the `components` scope. Launched in **Step 4.5** in the same concurrent batch — runs in parallel with the TSX/Astro work, ecom and gift-cards components, and Image Phase 2.
3
+ **This stylesheet is pre-copied from the skill template by the orchestrator** (build-wave pre-batch, BUILD-astro.md § "Step 4.5") — there is no `components-css` subagent to dispatch. This file documents the CSS for reference so the stores `components` scope (in the merged build agent) knows the class-name surface it targets.
4
4
 
5
5
  ## What this scope owns
6
6
 
@@ -19,11 +19,11 @@ Exactly one file:
19
19
 
20
20
  You only need:
21
21
 
22
- 1. **`<SKILL_ROOT>/templates/stores/components-stores.css`** — the canonical template. Read it once.
22
+ 1. **`<SKILL_ROOT>/references/astro/templates/stores/components-stores.css`** — the canonical template. Read it once.
23
23
  2. **`<SKILL_ROOT>/references/shared/STYLING.md`** — the styling-contract conventions (how to use `@apply`, the `@theme` token utilities, the no-default-Tailwind-colors rule, and the global-vs-scoped CSS ownership boundary).
24
24
  3. **`<SKILL_ROOT>/references/shared/RETURN_CONTRACT.md`** — the return JSON shape.
25
25
  4. **`src/styles/global.css`** in the project — read to audit for stores-class leaks (see § "Global-CSS leak audit" below).
26
- 5. **Design tokens (inline in your prompt)** — the parent skill pastes the full `designTokens` JSON into your dispatch prompt. Use it directly; do NOT read `.wix/design-tokens.css` or `.wix/site.d.ts` from disk.
26
+ 5. **Design tokens (on disk)** — read the design tokens (the DESIGN.md vocabulary — `colors`/`typography`/`spacing`/`rounded`/`containers`) from `.wix/design-tokens.css` (gate-verified present before the wave). They are NOT inlined in your prompt.
27
27
 
28
28
  You do NOT need to read `INSTRUCTIONS.md`, `SHARED_WIRING.md`, `BACK_IN_STOCK.md`, the TSX templates, the back-in-stock util, or any other reference. Skipping those reads is the point of the split — they would consume tokens for context this scope doesn't use.
29
29
 
@@ -32,7 +32,7 @@ You do NOT need to read `INSTRUCTIONS.md`, `SHARED_WIRING.md`, `BACK_IN_STOCK.md
32
32
  ### 1. Read the template
33
33
 
34
34
  ```
35
- <SKILL_ROOT>/templates/stores/components-stores.css
35
+ <SKILL_ROOT>/references/astro/templates/stores/components-stores.css
36
36
  ```
37
37
 
38
38
  This is the canonical scoped CSS for the stores pack. Adapt sizing/spacing to the brand's aesthetic — use the design tokens from your prompt (`--color-bark`, `--color-cream`, `--spacing-md`, `--font-display`, etc.). **Do not rename the class names or state modifiers** — they must match the contract keys the TSX components reference.
@@ -68,7 +68,7 @@ The boundary: **rules referenced by exactly one pack's TSX live in that pack's s
68
68
 
69
69
  ### 4. Global-CSS leak audit
70
70
 
71
- Before writing your file, **read `src/styles/global.css`** and grep for any class your scope owns. Stores-specific rules sometimes leak into the designer's foundation (observed across runs):
71
+ Before writing your file, **read `src/styles/global.css`** and grep for any class your scope owns. Stores-specific rules sometimes leak into the designer's foundation:
72
72
 
73
73
  - `.product-grid` and `body[data-navigating="true"] .product-grid` — designer drift; should be in `components-stores.css`, not `global.css`.
74
74
  - Any `.product-card-*` rule.
@@ -86,7 +86,7 @@ Write the adapted CSS to `src/styles/components-stores.css`. The first line must
86
86
 
87
87
  ## Coordination: design tokens
88
88
 
89
- Your parent prompt includes the design tokens JSON inline. Use it directly — do **not** read `.wix/design-tokens.css` or `.wix/site.d.ts` from disk and do not poll for them.
89
+ Read the design tokens from `.wix/design-tokens.css` (on disk, gate-verified present before the wave) — they are NOT inlined in your prompt.
90
90
 
91
91
  ## Return format
92
92
 
@@ -126,4 +126,4 @@ If a leak was found and overridden, include `errors: [{code: "GLOBAL_CSS_LEAK",
126
126
  | Use default Tailwind colors (`bg-green-50`, `text-red-600`) | Brand `@theme` utilities (`bg-bark`, `text-cream`) or `var(--color-...)` |
127
127
  | Write rules for `.add-to-cart-btn` here | That's a global contract class — owned by the designer's `global.css` |
128
128
  | Rename a class because the brand is "more elegant" with kebab-cased variants | Class names are contract keys; renaming breaks every TSX import that references them |
129
- | Skip the leak audit | Skipping ships double-defined rules; the audit is < 5 s and prevents downstream visual regressions |
129
+ | Skip the leak audit | Skipping ships double-defined rules; the audit is < 5 s and prevents downstream visual regressions |
@@ -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` — dispatched as its **own serialized shell-patcher agent** in the build wave (NOT merged into the stores private-files agent, because it patches the shared shells). Imports the orchestrator-pre-copied `categories.ts` helper and the `CategoryRail`/`ProductCard` the stores private agent writes — **resolved at build time, so no write-ordering against that agent.** Patches the home page's stores-related placeholder data with live `productsV3` queries AND inserts the Shop submenu (categories list) into the persisted Navigation at the `<!-- nav:links -->` marker. (The `CartBadge` mount at `<!-- nav:actions -->` is ecom's; you own only `<!-- nav:links -->`.) Read your seeded slice from `.wix/seeded.json` (`seeded.stores`).
4
+
5
+ > **You patch the shared `Navigation.astro` + `index.astro` shells**, which other packs (ecom at `nav:actions`, gift-cards, blog) 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 the shell-patching agents so concurrent marker edits don't collide — BUILD-astro.md § "Step 4.5", the serialized shell chain.)
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** — read the design tokens (the DESIGN.md vocabulary) from `.wix/design-tokens.css` (on disk) 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[]` |
@@ -1,10 +1,10 @@
1
1
  # Phase 4 Product Pages — Stores
2
2
 
3
- Scope: `product-pages`. Launched in **Step 7** after designer page scopes have written placeholder `.astro` files. This scope rewrites the product listing, product detail, and ProductCard component with live `productsV3` queries.
3
+ Scope: `product-pages` (the `pages-products` scope) — written by the stores **merged build agent** (the build wave) *after* its `components` and `pages-categories` scopes. This scope writes the product listing, product detail, and ProductCard component **once** — applying the designer's visual spec (`references/astro/designer/INSTRUCTIONS.md` → `store-pages`) together with live `productsV3` queries in a single pass. Read your seeded slice from `.wix/seeded.json` (`seeded.stores`).
4
4
 
5
5
  ## Scope
6
6
 
7
- Files this agent OWNS (rewrites from designer output):
7
+ Files this agent OWNS (each written once, visual structure + live queries together):
8
8
 
9
9
  - `src/pages/products/index.astro` — product listing
10
10
  - `src/pages/products/[slug].astro` — product detail with `wixMetadata` + SEO tags
@@ -12,15 +12,17 @@ Files this agent OWNS (rewrites from designer output):
12
12
 
13
13
  Files this agent MUST NOT touch:
14
14
  - `src/components/ProductPurchase.tsx`, `src/components/AddToCartButton.tsx` — owned by `components`
15
- - `src/pages/cart.astro`, `src/pages/thank-you.astro` — owned by `pages-cart-checkout`
15
+ - `src/pages/cart.astro`, `src/pages/thank-you.astro` — owned by `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 the `pages-categories` scope, which your merged agent writes **before** this one. **Import** from `../../components/CategoryRail.astro`; never `Write` it here. By the time you mount it, the `pages-categories` step has already put it on disk. If it's somehow absent, you wrote your scopes out of order — return `status: "partial"` with `errors: [{ code: "MISSING_PAGES_CATEGORIES_OUTPUT", path: "src/components/CategoryRail.astro" }]` (write `pages-categories` before `pages-products`; never defensively `Write` it from this scope).
18
+ - `src/utils/categories.ts` — pre-copied by the orchestrator in the build-wave pre-batch (BUILD-astro.md § "Step 4.5"). **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`.
23
- - **Designer output summary** — paths of existing `products/index.astro`, `products/[slug].astro`, `ProductCard.astro` with placeholder data.
24
+ - **Design tokens** — read the design tokens (the DESIGN.md vocabulary) from `.wix/design-tokens.css` (on disk) 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`.
25
+ - **Designer visual spec** — the layout, contract classes, and decorative-slot conventions for `products/index.astro`, `products/[slug].astro`, `ProductCard.astro` (from `references/astro/designer/INSTRUCTIONS.md` → `store-pages`), applied in the same pass as the live queries.
24
26
 
25
27
  ## Critical rules (all must be honored)
26
28
 
@@ -66,13 +68,13 @@ Do NOT modify logic, imports, SDK calls, `wixMetadata` export, or prop-passing.
66
68
 
67
69
  Use template `templates/products/index.astro`.
68
70
 
69
- Preserves the designer's page structure (class names, layout) and replaces the placeholder products array with a guarded, **cursor-paginated** `productsV3.queryProducts({ fields: ["CURRENCY"] }).limit(24).skipTo(cursor).find()` (cursor read from `?cursor=` on the URL; Prev/Next anchors built from `result.cursors.next` / `.prev`). Mounts the shared `<CategoryRail/>` (written by `pages-categories`) above the grid, passing `activeSlug={null}` and the prev/next hrefs. Emits the `AddProductImpression` analytics event from a client-side script that reads a JSON payload serialized at SSR.
71
+ Applies the designer's page structure (class names, layout) and binds a guarded, **cursor-paginated** `productsV3.queryProducts({ fields: ["CURRENCY"] }).limit(24).skipTo(cursor).find()` (cursor read from `?cursor=` on the URL; Prev/Next anchors built from `result.cursors.next` / `.prev`). Mounts the shared `<CategoryRail/>` (written by `pages-categories`) above the grid, passing `activeSlug={null}` and the prev/next hrefs. Emits the `AddProductImpression` analytics event from a client-side script that reads a JSON payload serialized at SSR.
70
72
 
71
- > **Imports written by `pages-categories`.** Both `<CategoryRail/>` and `listStoreCategories` come from files this scope must NOT write — they're owned by the `pages-categories` scope. Import paths: `../../components/CategoryRail.astro` and `../../utils/categories`. If either import fails to resolve, return `status: "partial"` with `errors: [{ code: "MISSING_PAGES_CATEGORIES_OUTPUT", path: "<missing path>" }]` — that means the orchestrator dispatched scopes out of order.
73
+ > **Imports you must NOT write.** `<CategoryRail/>` (`../../components/CategoryRail.astro`) is written by the `pages-categories` scope your merged agent runs *before* this one; `listStoreCategories` (`../../utils/categories`) is pre-copied by the orchestrator. Both are on disk by the time you mount them. If either fails to resolve, return `status: "partial"` with `errors: [{ code: "MISSING_PAGES_CATEGORIES_OUTPUT", path: "<missing path>" }]` — that means your agent wrote `pages-products` before `pages-categories`, or the pre-copy was skipped.
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`. |
@@ -1,8 +1,8 @@
1
1
  # Phase 3 Components — Stores (TSX/Astro)
2
2
 
3
- Launched in **Step 4.5** (after Phase 2 Design System completes, parallel to any running designer page scopes). Writes code that depends on the **design tokens** but NOT on Phase 4 page markup. Finishes before the Phase 4 Pages scopes run in Step 7.
3
+ This is the **components** portion of the stores **merged build agent** (the build wave — `BUILD-astro.md` § "Step 4.5"). Your agent writes these islands **first**, then the stores pages (`pages-categories`, `pages-products`) that mount them — so the islands are on disk before the page code references them. The code here depends on the **design tokens** (read from `.wix/design-tokens.css` on disk) but NOT on page markup.
4
4
 
5
- > **CSS lives in a sibling scope.** `src/styles/components-stores.css` is owned by the `components-css` scope (see `./COMPONENTS_CSS.md`), which runs concurrently with this one in the same Step 4.5 batch. This scope does NOT write the CSS file. Reference contract class names from the design tokens here; the CSS sibling defines the rules.
5
+ > **CSS is pre-copied, not authored.** `src/styles/components-stores.css` ships from the skill template, copied by the orchestrator in the build-wave pre-batch (see `./COMPONENTS_CSS.md`). This scope does NOT write the CSS file. Reference its contract class names from the design tokens here; the pre-copied stylesheet defines the rules.
6
6
 
7
7
  ## Scope
8
8
 
@@ -17,14 +17,15 @@ Files this agent MUST NOT touch:
17
17
  - `src/styles/components-stores.css` — owned by the **`components-css`** sibling scope (see `./COMPONENTS_CSS.md`). Reference its class names; do not write the file.
18
18
  - `src/utils/wix-image.ts` — **shared utility shipped by the build skill.** Import `resolveWixImageUrl` from `../utils/wix-image`; do NOT write your own copy (would shadow the shared util and drop other verticals' callers). The canonical source lives at `<SKILL_ROOT>/shared-utilities/wix-image.ts`; it's copied into projects by `seed-utilities.sh` during Setup.
19
19
  - `src/components/CartView.tsx`, `src/components/CartBadge.tsx`, `src/utils/analytics.ts`, `src/styles/components-ecom.css` — owned by ecom
20
- - Any `.astro` page — those are designed and later rewritten by other scopes
20
+ - `src/utils/back-in-stock.ts` — **pre-copied by the orchestrator** in the build-wave pre-batch (BUILD-astro.md § "Step 4.5"), same as `categories.ts`. Import `getBackInStockEnabled`/the app-id constants from `../utils/back-in-stock`; never `Write` it (see `./BACK_IN_STOCK.md`).
21
+ - Any `.astro` page — written by your agent's `pages-*` scopes (after the islands) or by another vertical
21
22
  - `src/styles/global.css` — owned by designer foundation
22
23
  - `src/layouts/Layout.astro` — owned by designer foundation (including the `components-stores.css` import line)
23
24
  - Any designed component (`ProductCard.astro`, `Navigation.astro`, etc.) — owned by designers
24
25
 
25
26
  ## Coordination: design tokens
26
27
 
27
- Your parent prompt includes the design tokens inline. Use it directly — do **not** read `.wix/design-tokens.css` + `.wix/site.d.ts` from disk and do not poll for it. The parent skill serializes your launch behind designer foundation specifically so the contract is already available in your prompt when you start.
28
+ Read the design tokens from `.wix/design-tokens.css` (on disk, gate-verified present before the wave). The parent skill serializes your launch behind the designer foundation specifically so this file is already written when you start.
28
29
 
29
30
  Reference the ACTUAL class names from the contract in React components (e.g. `className="add-to-cart-btn"`, not `className="addToCartButton"` or an invented name). See `references/shared/IMPLEMENTER.md` § "Contract class-name adaptation" for the full rule.
30
31
 
@@ -94,7 +95,7 @@ Handles variant selection, quantity selector, stock awareness, and wraps `AddToC
94
95
  <ProductPurchase client:load product={product} inventoryByVariant={inventoryByVariant} />
95
96
  ```
96
97
 
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).
98
+ **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
99
 
99
100
  Key behaviors:
100
101
  - `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 +160,6 @@ Classes from contract (stores pack):
159
160
  | 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
161
  | `<!--` HTML comments in `.astro` frontmatter | `//` or `/* */` — frontmatter is TypeScript |
161
162
  | 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` |
163
+ | Introspect `node_modules/@wix/*` | All symbols are documented here; if missing, use docs-search REST (see `DOCS_SEARCH.md`) |
163
164
  | 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} />` |
165
+ | 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.mjs):
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.mjs):
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>