@wix/agent-skills 1.13.0 → 1.15.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 (250) hide show
  1. package/README.md +4 -1
  2. package/package.json +1 -1
  3. package/skills/README.md +23 -0
  4. package/skills/wix-app/SKILL.md +10 -2
  5. package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +326 -0
  6. package/skills/wix-app/references/CODE_QUALITY.md +1 -0
  7. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +124 -115
  8. package/skills/wix-app/references/DASHBOARD_PAGE.md +3 -0
  9. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +23 -9
  10. package/skills/wix-app/references/SITE_PLUGIN.md +1 -1
  11. package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +115 -0
  12. package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +264 -0
  13. package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +37 -0
  14. package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +86 -0
  15. package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +119 -0
  16. package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +103 -0
  17. package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +76 -0
  18. package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +82 -0
  19. package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +89 -0
  20. package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +124 -0
  21. package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +91 -0
  22. package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +71 -0
  23. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +70 -0
  24. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +73 -0
  25. package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +98 -0
  26. package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +278 -0
  27. package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +94 -0
  28. package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +43 -0
  29. package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +66 -0
  30. package/skills/wix-app/references/auto-patterns-dashboard/views.md +76 -0
  31. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -14
  32. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +54 -29
  33. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +2 -2
  34. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +17 -105
  35. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +127 -0
  36. package/skills/wix-app/references/editor-react-component/PARTS.md +2 -1
  37. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +15 -15
  38. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +25 -53
  39. package/skills/wix-app/scripts/generate-auto-patterns.js +510 -0
  40. package/skills/wix-auth/SKILL.md +12 -0
  41. package/skills/wix-auth/references/device-flow.md +140 -0
  42. package/skills/wix-docs/SKILL.md +188 -0
  43. package/skills/wix-docs/references/API_SPEC_SEARCH.md +213 -0
  44. package/skills/wix-docs/references/EXTRACTING.md +120 -0
  45. package/skills/wix-headless/SKILL.md +84 -130
  46. package/skills/wix-headless/entry/bootstrap.mjs +93 -0
  47. package/skills/wix-headless/entry/skill.md +78 -0
  48. package/skills/wix-headless/references/AI_FEATURES.md +178 -0
  49. package/skills/wix-headless/references/CAPABILITIES.md +84 -0
  50. package/skills/wix-headless/references/DISCOVERY.md +34 -56
  51. package/skills/wix-headless/references/DOC_DISCOVERY.md +37 -0
  52. package/skills/wix-headless/references/FEEDBACK.md +118 -0
  53. package/skills/wix-headless/references/IMAGE_GENERATION.md +69 -0
  54. package/skills/wix-headless/references/SDK_HANDOFF.md +97 -0
  55. package/skills/wix-headless/references/SEED.md +44 -188
  56. package/skills/wix-headless/references/SETUP.md +32 -103
  57. package/skills/wix-headless/references/astro.md +98 -0
  58. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +196 -0
  59. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +236 -0
  60. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +279 -0
  61. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +163 -0
  62. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +203 -0
  63. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +222 -0
  64. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +124 -0
  65. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +160 -0
  66. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +118 -0
  67. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +132 -0
  68. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +124 -0
  69. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +188 -0
  70. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +173 -0
  71. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +161 -0
  72. package/skills/wix-headless/references/inline-recipes/setup-blog.md +175 -0
  73. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +228 -0
  74. package/skills/wix-headless/references/inline-recipes/setup-cms.md +200 -0
  75. package/skills/wix-headless/references/inline-recipes/setup-events.md +196 -0
  76. package/skills/wix-headless/references/inline-recipes/setup-forms.md +174 -0
  77. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +176 -0
  78. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +153 -0
  79. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +229 -0
  80. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +161 -0
  81. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +117 -0
  82. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +152 -0
  83. package/skills/wix-headless/references/managed/AUTHENTICATION.md +57 -0
  84. package/skills/wix-headless/references/managed/CONNECT.md +74 -0
  85. package/skills/wix-headless/references/managed/CREATE.md +130 -0
  86. package/skills/wix-headless/references/managed/DEPLOYMENT.md +57 -0
  87. package/skills/wix-headless/references/non-astro.md +59 -0
  88. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +22 -0
  89. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +7 -0
  90. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +55 -0
  91. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +63 -0
  92. package/skills/wix-manage/SKILL.md +24 -1
  93. package/skills/wix-manage/references/analytics/query-site-analytics.md +241 -0
  94. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +1 -1
  95. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +265 -0
  96. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +436 -0
  97. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +209 -0
  98. package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +249 -0
  99. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +51 -0
  100. package/skills/wix-vibe-headless/SKILL.md +136 -0
  101. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +128 -0
  102. package/skills/wix-vibe-headless/references/blog/wix-blog.js +217 -0
  103. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +153 -0
  104. package/skills/wix-vibe-headless/references/bookings/wix-bookings-checkout.js +147 -0
  105. package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +215 -0
  106. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +154 -0
  107. package/skills/wix-vibe-headless/references/cms/wix-cms.js +186 -0
  108. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +142 -0
  109. package/skills/wix-vibe-headless/references/events/wix-events-browse.js +135 -0
  110. package/skills/wix-vibe-headless/references/events/wix-events-registration.js +187 -0
  111. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +211 -0
  112. package/skills/wix-vibe-headless/references/members/wix-members-auth.js +387 -0
  113. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +111 -0
  114. package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +194 -0
  115. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +127 -0
  116. package/skills/wix-vibe-headless/references/pricing-plans/wix-pricing-plans.js +157 -0
  117. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +138 -0
  118. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-menu.js +224 -0
  119. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-ordering.js +156 -0
  120. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-reservations.js +107 -0
  121. package/skills/wix-vibe-headless/references/shared/wix-client.js +186 -0
  122. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +155 -0
  123. package/skills/wix-vibe-headless/references/storefront/wix-store-cart.js +147 -0
  124. package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +142 -0
  125. package/skills/wix-headless/references/BUILD-astro.md +0 -244
  126. package/skills/wix-headless/references/BUILD-own-build.md +0 -167
  127. package/skills/wix-headless/references/BUILD.md +0 -105
  128. package/skills/wix-headless/references/DESIGN_SYSTEM.md +0 -165
  129. package/skills/wix-headless/references/DISCOVERY-connect.md +0 -55
  130. package/skills/wix-headless/references/DISCOVERY-create.md +0 -238
  131. package/skills/wix-headless/references/PLAN-connect.md +0 -19
  132. package/skills/wix-headless/references/PLAN-create.md +0 -17
  133. package/skills/wix-headless/references/PLAN.md +0 -92
  134. package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +0 -300
  135. package/skills/wix-headless/references/astro/blog/BLOG_SETUP.md +0 -218
  136. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +0 -45
  137. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +0 -77
  138. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +0 -214
  139. package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +0 -231
  140. package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +0 -453
  141. package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +0 -354
  142. package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +0 -299
  143. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +0 -351
  144. package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +0 -119
  145. package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +0 -103
  146. package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +0 -132
  147. package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +0 -463
  148. package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +0 -119
  149. package/skills/wix-headless/references/astro/gift-cards/PAGES.md +0 -129
  150. package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +0 -178
  151. package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +0 -85
  152. package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +0 -129
  153. package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +0 -229
  154. package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +0 -215
  155. package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +0 -165
  156. package/skills/wix-headless/references/astro/templates/Footer.astro +0 -27
  157. package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
  158. package/skills/wix-headless/references/astro/templates/Navigation.astro +0 -38
  159. package/skills/wix-headless/references/astro/templates/astro.config.mjs +0 -41
  160. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +0 -374
  161. package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +0 -136
  162. package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +0 -25
  163. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +0 -71
  164. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +0 -54
  165. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +0 -49
  166. package/skills/wix-headless/references/astro/templates/bookings/bookingDriver.ts +0 -245
  167. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +0 -424
  168. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +0 -176
  169. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +0 -181
  170. package/skills/wix-headless/references/astro/templates/ecom/CartBadge.tsx +0 -84
  171. package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +0 -543
  172. package/skills/wix-headless/references/astro/templates/ecom/cart.astro +0 -13
  173. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +0 -302
  174. package/skills/wix-headless/references/astro/templates/ecom/discounts.ts +0 -71
  175. package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +0 -24
  176. package/skills/wix-headless/references/astro/templates/gift-cards/GiftCardPurchase.tsx +0 -172
  177. package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +0 -42
  178. package/skills/wix-headless/references/astro/templates/gift-cards/_nav-snippet.astro +0 -11
  179. package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +0 -220
  180. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +0 -51
  181. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.ts +0 -75
  182. package/skills/wix-headless/references/astro/templates/global.css +0 -288
  183. package/skills/wix-headless/references/astro/templates/index.astro +0 -56
  184. package/skills/wix-headless/references/astro/templates/stores/AddToCartButton.tsx +0 -77
  185. package/skills/wix-headless/references/astro/templates/stores/BackInStockForm.tsx +0 -176
  186. package/skills/wix-headless/references/astro/templates/stores/CategoryRail.astro +0 -69
  187. package/skills/wix-headless/references/astro/templates/stores/ProductCard.astro +0 -79
  188. package/skills/wix-headless/references/astro/templates/stores/ProductPurchase.tsx +0 -397
  189. package/skills/wix-headless/references/astro/templates/stores/SeoTags.astro +0 -21
  190. package/skills/wix-headless/references/astro/templates/stores/back-in-stock.ts +0 -67
  191. package/skills/wix-headless/references/astro/templates/stores/categories.ts +0 -155
  192. package/skills/wix-headless/references/astro/templates/stores/category/[slug].astro +0 -130
  193. package/skills/wix-headless/references/astro/templates/stores/components-stores.css +0 -400
  194. package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +0 -128
  195. package/skills/wix-headless/references/astro/templates/stores/products/index.astro +0 -101
  196. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +0 -161
  197. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +0 -32
  198. package/skills/wix-headless/references/bookings/FLOW.md +0 -246
  199. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +0 -95
  200. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +0 -355
  201. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +0 -176
  202. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +0 -71
  203. package/skills/wix-headless/references/commands/known-apps.json +0 -6
  204. package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +0 -142
  205. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +0 -88
  206. package/skills/wix-headless/references/custom/blog/WIRING.md +0 -52
  207. package/skills/wix-headless/references/custom/bookings/WIRING.md +0 -197
  208. package/skills/wix-headless/references/custom/cms/WIRING.md +0 -97
  209. package/skills/wix-headless/references/custom/ecom/WIRING.md +0 -67
  210. package/skills/wix-headless/references/custom/forms/WIRING.md +0 -101
  211. package/skills/wix-headless/references/custom/stores/WIRING.md +0 -80
  212. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +0 -59
  213. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +0 -43
  214. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +0 -51
  215. package/skills/wix-headless/references/images/INSTRUCTIONS.md +0 -357
  216. package/skills/wix-headless/references/seed-recipes.md +0 -49
  217. package/skills/wix-headless/references/shared/AGENTS_MD.md +0 -47
  218. package/skills/wix-headless/references/shared/AUTHENTICATION.md +0 -108
  219. package/skills/wix-headless/references/shared/BUILD_NOISE.md +0 -8
  220. package/skills/wix-headless/references/shared/DESIGN_MD.md +0 -84
  221. package/skills/wix-headless/references/shared/DOCS_SEARCH.md +0 -41
  222. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +0 -186
  223. package/skills/wix-headless/references/shared/IMPLEMENTER.md +0 -206
  224. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +0 -97
  225. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +0 -143
  226. package/skills/wix-headless/references/shared/STYLING.md +0 -141
  227. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +0 -126
  228. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +0 -252
  229. package/skills/wix-headless/references/verticals/_schema.json +0 -74
  230. package/skills/wix-headless/references/verticals/_schema.md +0 -95
  231. package/skills/wix-headless/references/verticals/blog.md +0 -31
  232. package/skills/wix-headless/references/verticals/bookings.md +0 -41
  233. package/skills/wix-headless/references/verticals/cms.md +0 -30
  234. package/skills/wix-headless/references/verticals/ecom.md +0 -25
  235. package/skills/wix-headless/references/verticals/forms.md +0 -26
  236. package/skills/wix-headless/references/verticals/gift-cards.md +0 -24
  237. package/skills/wix-headless/references/verticals/stores.md +0 -33
  238. package/skills/wix-headless/scripts/check-manifest.mjs +0 -335
  239. package/skills/wix-headless/scripts/compose.mjs +0 -525
  240. package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -157
  241. package/skills/wix-headless/scripts/flatten.sh +0 -61
  242. package/skills/wix-headless/scripts/generate-images.mjs +0 -242
  243. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +0 -148
  244. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +0 -190
  245. package/skills/wix-headless/scripts/scaffold.sh +0 -139
  246. package/skills/wix-headless/scripts/seed-utilities.sh +0 -93
  247. package/skills/wix-headless/scripts/write-decorative-json.mjs +0 -62
  248. package/skills/wix-headless/shared-utilities/analytics.ts +0 -40
  249. package/skills/wix-headless/shared-utilities/ricos.ts +0 -179
  250. package/skills/wix-headless/shared-utilities/wix-image.ts +0 -72
@@ -1,525 +0,0 @@
1
- #!/usr/bin/env node
2
- // ── compose.mjs — the deterministic Composer (astro design-system phase) ──────
3
- //
4
- // Replaces the former `design-system-composer` LLM subagent (this script is now
5
- // the sole spec). The Composer's job is MECHANICAL: take the Designer's framework-
6
- // agnostic spec + the application inputs and SUBSTITUTE them into six pinned
7
- // skeletons at references/astro/templates/. There is no judgment in re-emitting
8
- // the fixed bulk (View-Transitions script, @utility btn family, view-transition
9
- // CSS), so an LLM is pure cost + run-to-run variance. This script does it in
10
- // sub-second, byte-reproducibly.
11
- //
12
- // It is a sibling of emit-design-tokens.mjs / patch-decorative-slots.mjs and,
13
- // like them, reads its input as a JSON object on stdin and takes the project
14
- // dir as argv[2]. It locates the skeletons relative to its own path (no
15
- // SKILL_ROOT needed).
16
- //
17
- // Usage:
18
- // node compose.mjs <project-dir> <<'JSON'
19
- // { "shell": {...}, "brand": {...}, "navLinks": [...],
20
- // "loadedPacks": [...], "packsWithComponents": [...], "disabledPacks": [...] }
21
- // JSON
22
- //
23
- // Tokens come from DESIGN.md — the single design format (no inline token JSON).
24
- // compose reads `<project-dir>/DESIGN.md` (or `designMdPath`), parses its
25
- // FRONTMATTER ONLY (the markdown body is documentation, never read), and applies
26
- // a role-translation table (references/shared/DESIGN_MD.md) so a DESIGN.md
27
- // authored with standard roles (primary/surface/on-surface/…) maps onto the wix
28
- // `--color-*` vocabulary; wix-native keys pass through losslessly. `rounded` →
29
- // radii; a custom `containers` group + a `googleFontsHref` key are honored.
30
- // The Designer authors that DESIGN.md directly; emit-design-tokens.mjs projects
31
- // the token CSS/types from it. DESIGN.md exists on disk before compose runs.
32
- //
33
- // stdin JSON (the application inputs — NOT the design tokens, which live in DESIGN.md):
34
- // - designMdPath — optional path to the DESIGN.md (default <project-dir>/DESIGN.md).
35
- // - shell — { heroHeadline, heroSub, footerTagline, navBrandMark }.
36
- // - brand — { name, description }.
37
- // - navLinks — [ { href, label } ]; labels used VERBATIM.
38
- // - loadedPacks — string[] of loaded vertical packs.
39
- // - packsWithComponents — string[]; one components-<pack>.css import per entry,
40
- // in order (COMPOSE § Layout.astro).
41
- // - disabledPacks — string[]; dormant packs still get their home/nav markers,
42
- // never a visible entry point.
43
- //
44
- // What it writes (the 6 design-system files), by substituting {{…}} slots into
45
- // the pinned skeletons — the fixed bulk is copied byte-for-byte:
46
- // 1. src/styles/global.css — {{theme}} ← @theme palette
47
- // 2. astro.config.mjs — MERGE (anchored codemod, not clobber)
48
- // 3. src/layouts/Layout.astro — imports, fonts href, brand title
49
- // 4. src/components/Navigation.astro — brand mark, nav links
50
- // 5. src/components/Footer.astro — brand, tagline, nav links
51
- // 6. src/pages/index.astro — hero copy, brand, home markers
52
- //
53
- // Token contract: guarantees the required-token set (STYLING.md § "Required
54
- // tokens — the component-CSS template contract") resolves in @theme. Missing
55
- // roles are DERIVED as a fail-safe (the Designer is expected to emit a complete
56
- // set + a googleFontsHref; derivation is a safety net, not the hot path).
57
- //
58
- // Output: a single manifest JSON object on stdout (the orchestrator parses it
59
- // the same way it parsed the subagent's return — same { status, phase, data,
60
- // files } shape). Diagnostics go to stderr. Exit 0 on complete, 1 on a hard
61
- // failure (missing scaffold / unrecoverable token gap / missing config anchor).
62
- //
63
- // astro only. Custom (non-astro) frontends never reach the Composer — the
64
- // orchestrator only invokes this when frontend === "astro".
65
-
66
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
67
- import { join, dirname, resolve, isAbsolute } from "node:path";
68
- import { fileURLToPath } from "node:url";
69
- import { execSync } from "node:child_process";
70
-
71
- const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
72
- const TEMPLATES = resolve(SCRIPT_DIR, "..", "references", "astro", "templates");
73
-
74
- const projectDir = process.argv[2] ?? process.cwd();
75
-
76
- function die(code, message) {
77
- // Emit a structured failure manifest on stdout so the orchestrator parses a
78
- // return either way, plus a human line on stderr. Hard-fail with exit 1.
79
- console.error(`compose: ${message}`);
80
- console.log(JSON.stringify({ status: "failed", phase: "compose", data: {}, files: [], errors: [{ code, message }] }, null, 2));
81
- process.exit(1);
82
- }
83
-
84
- // ── read + validate input ─────────────────────────────────────────────────────
85
- if (process.stdin.isTTY) die("NO_INPUT", "expected the compose input JSON on stdin");
86
- let input;
87
- try {
88
- const raw = readFileSync(0, "utf8").trim();
89
- if (!raw) die("EMPTY_INPUT", "stdin was empty — pass the compose input JSON object");
90
- input = JSON.parse(raw);
91
- } catch (e) {
92
- die("BAD_JSON", `stdin is not valid JSON (${e.message})`);
93
- }
94
-
95
- // ── token source: DESIGN.md frontmatter (portable) ───────────────────────────
96
- // Minimal frontmatter parser for the restricted DESIGN.md shape (groups of
97
- // `key: scalar`, plus typography tokens with an indented `fontFamily:`). Not a
98
- // general YAML parser — the body is never read. Color values are quoted in the
99
- // emitted DESIGN.md because an unquoted `#hex` after `: ` is a YAML comment.
100
- function unquote(v) {
101
- v = v.trim();
102
- const qc = v[0];
103
- if (qc === '"' || qc === "'") {
104
- // Return the quoted content up to the closing quote (handles a trailing
105
- // ` # comment` after the closing quote, and \" / \\ escapes in "…").
106
- let out = "";
107
- for (let i = 1; i < v.length; i++) {
108
- const c = v[i];
109
- if (qc === '"' && c === "\\" && i + 1 < v.length) { out += v[++i]; continue; }
110
- if (c === qc) break;
111
- out += c;
112
- }
113
- return out;
114
- }
115
- const hash = v.search(/\s#/); // strip trailing inline comment on bare scalars
116
- if (hash !== -1) v = v.slice(0, hash).trim();
117
- return v;
118
- }
119
- // Parse a flow-style inline object — `{ fontFamily: "X", fontWeight: 600 }` —
120
- // splitting top-level commas while respecting quotes (so `"Helvetica, Arial"`
121
- // stays one value). Used for typography tokens authored in flow style.
122
- function parseInlineObject(s) {
123
- const inner = s.trim().replace(/^\{/, "").replace(/\}$/, "");
124
- const obj = {};
125
- let buf = "", inq = null;
126
- const parts = [];
127
- for (const ch of inner) {
128
- if (inq) { if (ch === inq) inq = null; buf += ch; continue; }
129
- if (ch === '"' || ch === "'") { inq = ch; buf += ch; continue; }
130
- if (ch === ",") { parts.push(buf); buf = ""; continue; }
131
- buf += ch;
132
- }
133
- if (buf.trim()) parts.push(buf);
134
- for (const p of parts) {
135
- const ci = p.indexOf(":");
136
- if (ci === -1) continue;
137
- obj[p.slice(0, ci).trim()] = unquote(p.slice(ci + 1));
138
- }
139
- return obj;
140
- }
141
- function parseFrontmatter(text) {
142
- const m = text.match(/^---\r?\n([\s\S]*?)\r?\n---/);
143
- if (!m) return null;
144
- const root = {};
145
- let group = null, sub = null;
146
- for (const raw of m[1].split(/\r?\n/)) {
147
- if (!raw.trim() || /^\s*#/.test(raw)) continue;
148
- const indent = raw.match(/^ */)[0].length;
149
- const ci = raw.indexOf(":");
150
- if (ci === -1) continue;
151
- const key = raw.slice(0, ci).trim();
152
- const rest = raw.slice(ci + 1).trim();
153
- if (indent === 0) {
154
- if (rest === "") { root[key] = {}; group = key; sub = null; }
155
- else if (rest.startsWith("{")) { root[key] = parseInlineObject(rest); group = null; sub = null; }
156
- else { root[key] = unquote(rest); group = null; sub = null; }
157
- } else if (indent === 2 && group) {
158
- if (rest === "") { root[group][key] = {}; sub = key; }
159
- else if (rest.startsWith("{")) { root[group][key] = parseInlineObject(rest); sub = null; }
160
- else { root[group][key] = unquote(rest); sub = null; }
161
- } else if (indent >= 4 && group && sub) {
162
- if (typeof root[group][sub] !== "object") root[group][sub] = {};
163
- root[group][sub][key] = unquote(rest);
164
- }
165
- }
166
- return root;
167
- }
168
- // Standard DESIGN.md color roles → wix editorial `--color-*` names. wix-native
169
- // keys (paper/ink/accent/…) are NOT in this table and pass through unchanged,
170
- // winning on any conflict — so our own emission is lossless.
171
- const COLOR_ROLE_TABLE = {
172
- primary: "accent", secondary: "paper-warm", tertiary: "ink-soft", neutral: "mute",
173
- surface: "paper", "on-surface": "ink", background: "paper", "on-background": "ink",
174
- outline: "rule", error: "error",
175
- };
176
- function designMdToTokens(fm) {
177
- // Single pass preserving source key order: each key maps via the role table
178
- // (standard DESIGN.md role → wix name) or passes through unchanged (wix-native
179
- // keys aren't in the table). Order-preserving so our own round-trip is
180
- // byte-identical to the JSON path. (A file mixing a standard role and its wix
181
- // synonym — e.g. both `surface` and `paper` — is pathological; last wins.)
182
- const colors = {};
183
- for (const [k, v] of Object.entries(fm.colors ?? {})) colors[COLOR_ROLE_TABLE[k] ?? k] = v;
184
- const typ = fm.typography ?? {};
185
- const famOf = (...keys) => { for (const key of keys) if (typ[key] && typ[key].fontFamily) return typ[key].fontFamily; return undefined; };
186
- const fonts = {};
187
- const disp = famOf("display", "h1", "heading", "title");
188
- const body = famOf("body", "p", "text", "base", "paragraph");
189
- if (disp) fonts.display = disp;
190
- if (body) fonts.body = body;
191
- if (typ.mono && typ.mono.fontFamily) fonts.mono = typ.mono.fontFamily;
192
- return {
193
- colors,
194
- fonts,
195
- radii: fm.rounded ?? {}, // DESIGN.md calls corner radii `rounded`
196
- containers: fm.containers ?? {}, // custom group
197
- ...(typeof fm.googleFontsHref === "string" ? { googleFontsHref: fm.googleFontsHref } : {}),
198
- };
199
- }
200
-
201
- // DESIGN.md is the single token source — read it, parse frontmatter only.
202
- const designMdRel = input.designMdPath ?? "DESIGN.md";
203
- const designMdPath = isAbsolute(designMdRel) ? designMdRel : join(projectDir, designMdRel);
204
- if (!existsSync(designMdPath)) die("DESIGN_MD_MISSING", `no DESIGN.md at ${designMdPath} — the Designer must author it first`);
205
- const fm = parseFrontmatter(readFileSync(designMdPath, "utf8"));
206
- if (!fm) die("DESIGN_MD_BAD", `could not parse YAML frontmatter from ${designMdPath}`);
207
- const designTokens = designMdToTokens(fm);
208
- const shell = input.shell ?? {};
209
- const brand = input.brand ?? {};
210
- const navLinks = Array.isArray(input.navLinks) ? input.navLinks : [];
211
- const loadedPacks = Array.isArray(input.loadedPacks) ? input.loadedPacks : [];
212
- const packsWithComponents = Array.isArray(input.packsWithComponents) ? input.packsWithComponents : [];
213
- const disabledPacks = Array.isArray(input.disabledPacks) ? input.disabledPacks : [];
214
-
215
- const brandName = brand.name ?? "Brand";
216
-
217
- // ── small color helper (derivation fail-safe only) ────────────────────────────
218
- function parseHex(hex) {
219
- if (typeof hex !== "string") return null;
220
- let h = hex.trim().replace(/^#/, "");
221
- if (h.length === 3) h = h.split("").map((c) => c + c).join("");
222
- if (!/^[0-9a-fA-F]{6}$/.test(h)) return null;
223
- return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16));
224
- }
225
- function toHex([r, g, b]) {
226
- return "#" + [r, g, b].map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, "0")).join("");
227
- }
228
- // mix `a` toward `b` by weight w (0..1). Falls back to `a` if either unparseable.
229
- function mix(a, b, w) {
230
- const ca = parseHex(a), cb = parseHex(b);
231
- if (!ca || !cb) return a ?? b ?? "#000000";
232
- return toHex(ca.map((v, i) => v + (cb[i] - v) * w));
233
- }
234
-
235
- // ── build the @theme palette + guarantee the required-token contract ──────────
236
- const SYSTEM_FONTS = new Set([
237
- "system-ui", "-apple-system", "blinkmacsystemfont", "segoe ui", "sans-serif",
238
- "serif", "monospace", "ui-sans-serif", "ui-serif", "ui-monospace", "inherit",
239
- ]);
240
-
241
- const colors = { ...(designTokens.colors ?? {}) };
242
- const fonts = { ...(designTokens.fonts ?? {}) };
243
- const radii = { ...(designTokens.radii ?? {}) };
244
- const containers = { ...(designTokens.containers ?? {}) };
245
-
246
- const derived = [];
247
- function ensure(group, key, value, prefix) {
248
- if (group[key] === undefined || group[key] === null || group[key] === "") {
249
- group[key] = value;
250
- derived.push(`${prefix}${key}`);
251
- }
252
- }
253
-
254
- // Colors — required core first (sane neutral defaults if the Designer omitted a
255
- // core role), then warm/soft derivations described in COMPOSE § Token contract.
256
- ensure(colors, "paper", "#ffffff", "--color-");
257
- ensure(colors, "ink", "#1a1a1a", "--color-");
258
- ensure(colors, "accent", colors.ink, "--color-");
259
- ensure(colors, "mute", mix(colors.ink, colors.paper, 0.45), "--color-");
260
- ensure(colors, "rule", mix(colors.ink, colors.paper, 0.85), "--color-");
261
- ensure(colors, "paper-warm", mix(colors.paper, colors.accent, 0.06), "--color-"); // paper warmed
262
- ensure(colors, "ink-soft", mix(colors.ink, colors.paper, 0.25), "--color-"); // ink lightened
263
- // NOTE: cream is derived but not in REQUIRED; gift-cards CSS expects
264
- // --color-cream-deep (undeclared) and relies on the var() fallback — reconcile
265
- // with STYLING.md token contract.
266
- ensure(colors, "cream", mix(colors.paper, "#fbf3e0", 0.5), "--color-");
267
- ensure(colors, "error", "#c0392b", "--color-");
268
-
269
- // Fonts — display + body required.
270
- ensure(fonts, "display", "Georgia, serif", "--font-");
271
- ensure(fonts, "body", "system-ui, sans-serif", "--font-");
272
-
273
- // Spacing is NOT a named scale — Tailwind v4's built-in numeric spacing
274
- // (`--spacing` base → gap-4, py-24, …) is used directly. Emitting named
275
- // --spacing-<t-shirt> tokens collided with the width utilities (max-w-3xl etc.
276
- // drew from --spacing-3xl), so the named scale was removed (CODEAI-696).
277
-
278
- // Radii — sm + md required.
279
- ensure(radii, "sm", "0.25rem", "--radius-");
280
- ensure(radii, "md", "0.5rem", "--radius-");
281
-
282
- // Containers — content widths, a separate axis from spacing.
283
- const CONTAINER_DEFAULTS = { prose: "42rem", md: "48rem", "3xl": "60rem", "6xl": "72rem" };
284
- for (const [k, v] of Object.entries(CONTAINER_DEFAULTS)) ensure(containers, k, v, "--container-");
285
-
286
- // Assemble the @theme block, grouped + ordered for readability.
287
- const themeLines = [];
288
- const emitGroup = (prefix, obj) => {
289
- for (const [k, v] of Object.entries(obj)) themeLines.push(` ${prefix}${k}: ${v};`);
290
- };
291
- emitGroup("--color-", colors);
292
- themeLines.push("");
293
- emitGroup("--font-", fonts);
294
- themeLines.push("");
295
- emitGroup("--radius-", radii);
296
- themeLines.push("");
297
- emitGroup("--container-", containers);
298
- const themeBlock = themeLines.join("\n");
299
-
300
- // ── self-checks (assertions) ──────────────────────────────────────────────────
301
- const errors = [];
302
-
303
- // Required-token coverage (after derivation, every required role must resolve).
304
- const REQUIRED = [
305
- ...["paper", "paper-warm", "ink", "mute", "rule", "accent"].map((k) => `--color-${k}`),
306
- "--font-display", "--font-body",
307
- "--radius-sm", "--radius-md",
308
- ...["prose", "md", "3xl", "6xl"].map((k) => `--container-${k}`),
309
- ];
310
- const present = new Set([
311
- ...Object.keys(colors).map((k) => `--color-${k}`),
312
- ...Object.keys(fonts).map((k) => `--font-${k}`),
313
- ...Object.keys(radii).map((k) => `--radius-${k}`),
314
- ...Object.keys(containers).map((k) => `--container-${k}`),
315
- ]);
316
- for (const tok of REQUIRED) {
317
- if (!present.has(tok)) errors.push({ code: "MISSING_REQUIRED_TOKEN", token: tok });
318
- }
319
-
320
- // ── skeleton load + substitution helpers ──────────────────────────────────────
321
- function readTemplate(name) {
322
- const p = join(TEMPLATES, name);
323
- if (!existsSync(p)) die("TEMPLATE_MISSING", `skeleton not found at ${p}`);
324
- return readFileSync(p, "utf8");
325
- }
326
- function writeProject(rel, content) {
327
- const dest = join(projectDir, rel);
328
- mkdirSync(dirname(dest), { recursive: true });
329
- writeFileSync(dest, content);
330
- }
331
- function escAttr(s) {
332
- return String(s ?? "").replace(/"/g, "&quot;");
333
- }
334
- // Strip the leading "// ── Composer skeleton: … ──" authoring-comment block from
335
- // an .astro skeleton's frontmatter. Those lines document the {{…}} slots (and
336
- // thus contain placeholder text that must NOT be substituted) and are not part
337
- // of the shipped site — the real Composer output drops them too. Removes the
338
- // contiguous run of `//` comment lines immediately after the opening `---`.
339
- function stripAstroHeader(src) {
340
- return src.replace(/^(---\n)((?:[ \t]*\/\/.*\n)+)/, "$1");
341
- }
342
-
343
- // ── Google Fonts href ─────────────────────────────────────────────────────────
344
- // Prefer the Designer-supplied href; otherwise build one deterministically with
345
- // a standard weight set. Returns ""
346
- // when both families are system fonts (caller drops the <link>).
347
- function buildGoogleHref() {
348
- if (typeof designTokens.googleFontsHref === "string" && designTokens.googleFontsHref.trim()) {
349
- return designTokens.googleFontsHref.trim();
350
- }
351
- const families = [];
352
- for (const fam of [fonts.display, fonts.body]) {
353
- if (typeof fam !== "string") continue;
354
- const first = fam.split(",")[0].trim();
355
- if (!first || SYSTEM_FONTS.has(first.toLowerCase())) continue;
356
- if (!families.includes(first)) families.push(first);
357
- }
358
- if (families.length === 0) return "";
359
- const q = families
360
- .map((f) => `family=${f.replace(/\s+/g, "+")}:wght@400;500;600;700`)
361
- .join("&");
362
- return `https://fonts.googleapis.com/css2?${q}&display=swap`;
363
- }
364
-
365
- // ── 1. global.css ──────────────────────────────────────────────────────────────
366
- {
367
- const skeleton = readTemplate("global.css");
368
- // Replace the first `@theme { … }` block (its comment has no braces, so the
369
- // first `}` is its close). Everything else is literal fixed bulk.
370
- const out = skeleton.replace(/@theme\s*\{[\s\S]*?\n\}/, `@theme {\n${themeBlock}\n}`);
371
- if (out === skeleton) die("ANCHOR_THEME", "could not locate the @theme block in global.css skeleton");
372
- writeProject("src/styles/global.css", out);
373
- }
374
-
375
- // ── 2. astro.config.mjs (anchored MERGE, fail loud on missing anchor) ─────────
376
- {
377
- const dest = join(projectDir, "astro.config.mjs");
378
- // The scaffold may briefly be in flight; the new wiring invokes compose only
379
- // after Setup Step 1 awaited the scaffold, so a short retry is belt-and-braces.
380
- let src = null;
381
- for (let attempt = 0; attempt < 10; attempt++) {
382
- if (existsSync(dest)) { src = readFileSync(dest, "utf8"); break; }
383
- try { execSync("sleep 1"); } catch { /* ignore */ }
384
- }
385
- if (src === null) die("SCAFFOLD_NOT_COMPLETE", `astro.config.mjs not found at ${dest} after retries`);
386
-
387
- const hasImport = /import\s+tailwindcss\s+from\s+["']@tailwindcss\/vite["']/.test(src);
388
- const hasCall = /tailwindcss\s*\(\s*\)/.test(src);
389
-
390
- // (1a) import — insert after the last top-level import statement.
391
- if (!hasImport) {
392
- const importRe = /^import\b.*$/gm;
393
- let last = null, m;
394
- while ((m = importRe.exec(src)) !== null) last = m;
395
- if (!last) die("ANCHOR_IMPORT", "no import statement found in astro.config.mjs to anchor the @tailwindcss/vite import");
396
- const insertAt = last.index + last[0].length;
397
- src = src.slice(0, insertAt) + `\nimport tailwindcss from "@tailwindcss/vite";` + src.slice(insertAt);
398
- }
399
-
400
- // (1b) merge tailwindcss() into vite.plugins (idempotent on hasCall).
401
- if (!hasCall) {
402
- if (/plugins\s*:\s*\[/.test(src)) {
403
- src = src.replace(/plugins\s*:\s*\[/, (mm) => `${mm}tailwindcss(), `);
404
- } else if (/\bvite\s*:\s*\{/.test(src)) {
405
- src = src.replace(/(\bvite\s*:\s*\{)/, `$1\n plugins: [tailwindcss()],`);
406
- } else if (/defineConfig\s*\(\s*\{/.test(src)) {
407
- src = src.replace(/(defineConfig\s*\(\s*\{)/, `$1\n vite: { plugins: [tailwindcss()] },`);
408
- } else {
409
- die("ANCHOR_VITE", "could not find vite.plugins, a vite block, or defineConfig({ to register @tailwindcss/vite");
410
- }
411
- }
412
-
413
- // (2) process.env → globalThis guard (TS-safe under strict tsc --noEmit).
414
- const GUARD = `const isBuild =\n (/** @type {any} */ (globalThis)).process?.env?.NODE_ENV === "production";`;
415
- const alreadyGuarded = /\(globalThis\)\)\.process\?\.env\?\.NODE_ENV/.test(src);
416
- const bareRe = /const\s+isBuild\s*=\s*process\.env\.NODE_ENV\s*===?\s*["']production["']\s*;/;
417
- if (!alreadyGuarded) {
418
- if (bareRe.test(src)) {
419
- src = src.replace(bareRe, GUARD);
420
- } else if (/process\.env/.test(src)) {
421
- die("ANCHOR_PROCESS_ENV", "found a bare process.env reference but not the expected `const isBuild = process.env.NODE_ENV …` line to guard");
422
- }
423
- // else: no process.env at all — nothing to guard, leave as-is.
424
- }
425
-
426
- writeProject("astro.config.mjs", src);
427
- }
428
-
429
- // ── 3. Layout.astro ────────────────────────────────────────────────────────────
430
- const componentCssImports = packsWithComponents.map(
431
- (pack) => `import '../styles/components-${pack}.css';`,
432
- );
433
- {
434
- let out = stripAstroHeader(readTemplate("Layout.astro"));
435
- // {{components-css-imports}} — one import per pack, or drop the whole line.
436
- if (componentCssImports.length) {
437
- out = out.replace(/^\{\{components-css-imports\}\}\s*$/m, componentCssImports.join("\n"));
438
- } else {
439
- out = out.replace(/^\{\{components-css-imports\}\}\s*\n/m, "");
440
- }
441
- // {{fonts.googleHref}} — drop the <link> when no web fonts.
442
- const href = buildGoogleHref();
443
- if (href) {
444
- out = out.replace(/\{\{fonts\.googleHref\}\}/g, escAttr(href));
445
- } else {
446
- out = out.replace(/^.*\{\{fonts\.googleHref\}\}.*\n/m, "");
447
- }
448
- out = out.replaceAll("{{brand.name}}", brandName);
449
- writeProject("src/layouts/Layout.astro", out);
450
- }
451
-
452
- // ── nav-link rendering ──────────────────────────────────────────────────────────
453
- const navItems = navLinks
454
- .filter((l) => l && l.href != null && l.label != null)
455
- .map((l) => ({ href: String(l.href), label: String(l.label) }));
456
-
457
- // ── 4. Navigation.astro ──────────────────────────────────────────────────────────
458
- {
459
- let out = stripAstroHeader(readTemplate("Navigation.astro"));
460
- out = out.replaceAll("{{shell.navBrandMark}}", shell.navBrandMark ?? brandName);
461
- const links = navItems
462
- .map((l) => ` <li class="site-nav-item"><a href="${escAttr(l.href)}">${l.label}</a></li>`)
463
- .join("\n");
464
- out = out.replace(/^\s*\{\{nav\.links\}\}\s*$/m, links);
465
- writeProject("src/components/Navigation.astro", out);
466
- }
467
-
468
- // ── 5. Footer.astro ──────────────────────────────────────────────────────────────
469
- {
470
- let out = stripAstroHeader(readTemplate("Footer.astro"));
471
- out = out.replaceAll("{{brand.name}}", brandName);
472
- out = out.replaceAll("{{shell.footerTagline}}", shell.footerTagline ?? "");
473
- const links = navItems
474
- .map((l) => ` <li><a href="${escAttr(l.href)}">${l.label}</a></li>`)
475
- .join("\n");
476
- out = out.replace(/^\s*\{\{nav\.links\}\}\s*$/m, links);
477
- writeProject("src/components/Footer.astro", out);
478
- }
479
-
480
- // ── 6. index.astro ────────────────────────────────────────────────────────────────
481
- // Home markers: one `<!-- home:<pack> -->` per contributing pack. Today
482
- // stores + bookings + gift-cards contribute a home section. Disabled packs
483
- // (gift-cards) still get their marker (markers are their only acceptable touchpoint).
484
- const HOME_CONTRIBUTING = ["stores", "bookings", "gift-cards"]; // canonical order
485
- const homePool = new Set([...loadedPacks, ...disabledPacks]);
486
- const homeMarkerPacks = HOME_CONTRIBUTING.filter((p) => homePool.has(p));
487
- {
488
- let out = stripAstroHeader(readTemplate("index.astro"));
489
- out = out.replaceAll("{{shell.heroHeadline}}", shell.heroHeadline ?? brandName);
490
- out = out.replaceAll("{{shell.heroSub}}", shell.heroSub ?? "");
491
- out = out.replaceAll("{{brand.name}}", brandName);
492
- const markers = homeMarkerPacks.map((p) => ` <!-- home:${p} -->`).join("\n");
493
- out = out.replace(/^\s*\{\{home-markers\}\}\s*$/m, markers);
494
- writeProject("src/pages/index.astro", out);
495
- }
496
-
497
- // ── manifest (the orchestrator parses this off stdout) ────────────────────────
498
- const filesWritten = [
499
- "src/styles/global.css",
500
- "astro.config.mjs",
501
- "src/layouts/Layout.astro",
502
- "src/components/Navigation.astro",
503
- "src/components/Footer.astro",
504
- "src/pages/index.astro",
505
- ];
506
- const manifest = {
507
- status: errors.length ? "partial" : "complete",
508
- phase: "compose",
509
- data: {
510
- filesWritten,
511
- componentCssImports: packsWithComponents,
512
- homeMarkers: homeMarkerPacks.map((p) => `home:${p}`),
513
- tokensApplied: {
514
- colors: Object.keys(colors).length,
515
- containers: Object.keys(containers).length,
516
- radii: Object.keys(radii).length,
517
- fonts: Object.keys(fonts).length,
518
- },
519
- ...(derived.length ? { derivedTokens: derived } : {}),
520
- },
521
- files: filesWritten,
522
- ...(errors.length ? { errors } : {}),
523
- };
524
- console.log(JSON.stringify(manifest, null, 2));
525
- process.exit(0);