@wix/agent-skills 1.7.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 (117) hide show
  1. package/README.md +3 -7
  2. package/package.json +1 -1
  3. package/skills/wix-app/SKILL.md +2 -0
  4. package/skills/wix-app/references/STORES_VERSIONING.md +1 -0
  5. package/skills/wix-design-system/SKILL.md +4 -0
  6. package/skills/wix-headless/SKILL.md +55 -32
  7. package/skills/wix-headless/references/BUILD-astro.md +246 -0
  8. package/skills/wix-headless/references/BUILD-own-build.md +167 -0
  9. package/skills/wix-headless/references/BUILD.md +50 -252
  10. package/skills/wix-headless/references/DESIGN_SYSTEM.md +94 -34
  11. package/skills/wix-headless/references/DISCOVERY-connect.md +55 -0
  12. package/skills/wix-headless/references/DISCOVERY-create.md +238 -0
  13. package/skills/wix-headless/references/DISCOVERY.md +41 -422
  14. package/skills/wix-headless/references/PLAN-connect.md +19 -0
  15. package/skills/wix-headless/references/PLAN-create.md +17 -0
  16. package/skills/wix-headless/references/PLAN.md +37 -27
  17. package/skills/wix-headless/references/SEED.md +27 -18
  18. package/skills/wix-headless/references/SETUP.md +32 -213
  19. package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +5 -4
  20. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +337 -0
  21. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +428 -0
  22. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +5 -5
  23. package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +10 -10
  24. package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +12 -13
  25. package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +10 -12
  26. package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +8 -8
  27. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +50 -27
  28. package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +7 -8
  29. package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +5 -5
  30. package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +3 -3
  31. package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +5 -19
  32. package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +2 -2
  33. package/skills/wix-headless/references/astro/gift-cards/PAGES.md +1 -1
  34. package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +6 -6
  35. package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +4 -4
  36. package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +3 -3
  37. package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +3 -3
  38. package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +9 -9
  39. package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +5 -4
  40. package/skills/wix-headless/references/astro/templates/Footer.astro +1 -1
  41. package/skills/wix-headless/references/astro/templates/Layout.astro +1 -1
  42. package/skills/wix-headless/references/astro/templates/Navigation.astro +1 -1
  43. package/skills/wix-headless/references/astro/templates/astro.config.mjs +1 -1
  44. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +218 -0
  45. package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +194 -0
  46. package/skills/wix-headless/references/astro/templates/bookings/ManageBooking.tsx +84 -0
  47. package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +25 -0
  48. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +50 -0
  49. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +45 -0
  50. package/skills/wix-headless/references/astro/templates/bookings/api/confirm-booking.ts +34 -0
  51. package/skills/wix-headless/references/astro/templates/bookings/api/waitlist.ts +74 -0
  52. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +111 -0
  53. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +413 -0
  54. package/skills/wix-headless/references/astro/templates/bookings/manage-booking.astro +76 -0
  55. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +81 -0
  56. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +65 -0
  57. package/skills/wix-headless/references/astro/templates/global.css +2 -2
  58. package/skills/wix-headless/references/astro/templates/index.astro +1 -1
  59. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +19 -9
  60. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +3 -3
  61. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +106 -0
  62. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +295 -0
  63. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +4 -2
  64. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +27 -1
  65. package/skills/wix-headless/references/commands/known-apps.json +2 -1
  66. package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +142 -0
  67. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +71 -21
  68. package/skills/wix-headless/references/custom/blog/WIRING.md +52 -0
  69. package/skills/wix-headless/references/custom/bookings/WIRING.md +88 -0
  70. package/skills/wix-headless/references/custom/cms/WIRING.md +97 -0
  71. package/skills/wix-headless/references/custom/ecom/WIRING.md +67 -0
  72. package/skills/wix-headless/references/custom/forms/WIRING.md +101 -0
  73. package/skills/wix-headless/references/custom/stores/WIRING.md +80 -0
  74. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +5 -5
  75. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +2 -2
  76. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +3 -3
  77. package/skills/wix-headless/references/images/INSTRUCTIONS.md +16 -15
  78. package/skills/wix-headless/references/seed-recipes.md +2 -2
  79. package/skills/wix-headless/references/shared/AGENTS_MD.md +47 -0
  80. package/skills/wix-headless/references/shared/AUTHENTICATION.md +3 -5
  81. package/skills/wix-headless/references/shared/DESIGN_MD.md +85 -0
  82. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +29 -28
  83. package/skills/wix-headless/references/shared/IMPLEMENTER.md +87 -27
  84. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +2 -2
  85. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +24 -313
  86. package/skills/wix-headless/references/shared/STYLING.md +8 -18
  87. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +39 -9
  88. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +17 -14
  89. package/skills/wix-headless/references/verticals/_schema.json +1 -1
  90. package/skills/wix-headless/references/verticals/_schema.md +3 -3
  91. package/skills/wix-headless/references/verticals/blog.md +1 -1
  92. package/skills/wix-headless/references/verticals/bookings.md +41 -0
  93. package/skills/wix-headless/references/verticals/cms.md +1 -1
  94. package/skills/wix-headless/references/verticals/ecom.md +2 -2
  95. package/skills/wix-headless/references/verticals/gift-cards.md +1 -1
  96. package/skills/wix-headless/references/verticals/stores.md +1 -1
  97. package/skills/wix-headless/scripts/check-manifest.mjs +143 -6
  98. package/skills/wix-headless/scripts/compose.mjs +540 -0
  99. package/skills/wix-headless/scripts/emit-design-tokens.mjs +128 -51
  100. package/skills/wix-headless/scripts/flatten.sh +61 -0
  101. package/skills/wix-headless/scripts/generate-images.mjs +242 -0
  102. package/skills/wix-headless/scripts/scaffold.sh +47 -16
  103. package/skills/wix-headless/scripts/write-decorative-json.mjs +62 -0
  104. package/skills/wix-manage/SKILL.md +1 -1
  105. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +1 -1
  106. package/skills/wix-manage/references/cms/cms-data-items-crud.md +1 -1
  107. package/skills/wix-manage/references/cms/cms-references-and-relationships.md +1 -1
  108. package/skills/wix-manage/references/cms/cms-schema-management.md +1 -1
  109. package/skills/wix-manage/references/domains/domain-search-and-purchase.md +10 -7
  110. package/skills/wix-manage/references/forms/create-form.md +49 -1
  111. package/skills/wix-manage/references/stores/bulk-create-products-with-options.md +1 -1
  112. package/skills/wix-manage/references/stores/setup-online-store-catalog-v3.md +1 -1
  113. package/skills/wix-headless/references/astro/COMPOSE.md +0 -142
  114. package/skills/wix-headless/scripts/finalize-run-json.mjs +0 -141
  115. package/skills/wix-headless/scripts/init-site-json.mjs +0 -101
  116. package/skills/wix-headless/scripts/preview.sh +0 -45
  117. package/skills/wix-headless/scripts/release.sh +0 -73
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: custom-forms-wiring
3
+ description: "Integration-mode wiring subagent for the forms capability. Connects a brought-in static site to Wix Forms — wires an existing <form> to submit via @wix/forms, OR injects a new connected form (RSVP / lead / contact) styled from the design's CSS tokens. Client-side @wix/sdk + OAuthStrategy visitor session, loaded from CDN. The universal connection floor for integration mode."
4
+ ---
5
+
6
+ # Forms wiring (integration mode)
7
+
8
+ You wire the **forms capability** into a brought-in static site for `wix-headless` integration mode (`frontend = "custom"`). Forms is the **universal connection floor** — when a design has no dynamic content, a domain-appropriate form (RSVP, lead, contact) is the connection that makes it live.
9
+
10
+ You write **client-side, vanilla JS** — no React, no build step. `@wix/sdk` + `@wix/forms` load from a CDN; the HTML *is* the deployable. Read `INSTRUCTIONS.md` § "The technical spine" and § "Wiring discipline" before starting.
11
+
12
+ ## Inputs (inlined by the orchestrator)
13
+
14
+ - **`appId`** — from `wix.config.json`; the `OAuthStrategy` `clientId`.
15
+ - **`formId`** — the Wix Form created at Seed time (Seed creates the form definition from the augmentation spec's `fields`, with `postSubmissionTriggers.upsertContact` so submissions create CRM contacts). Never hardcode or invent a form ID — if it's missing, fail loudly.
16
+ - **`fields`** — each `{ name, label, type, required, options?, target }`. The **`target`** is the Wix field key the submission map uses (from the created form's schema). If only `name` is known, the orchestrator resolves `target` from the seeded form schema before dispatch.
17
+ - **The augmentation spec** (`injectAt`, `styleFrom`) and/or a binding-map entry (an existing `<form>` to wire).
18
+ - **`tokens`** — the design's resolved CSS custom properties for styling.
19
+
20
+ ## Two cases
21
+
22
+ ### A. Augment — inject a new connected form (the static-design path)
23
+
24
+ The design has no form (e.g. a wedding invitation). Inject one at `augmentation.injectAt`.
25
+
26
+ 1. **Build the `<form>` markup** from `fields`, styled with the design's tokens. Use the site's existing CSS custom properties (`var(--…)`) and font/spacing variables verbatim so the form reads as designed-in. Reuse the page's section/heading rhythm (match an existing `section`'s padding, an existing heading's font). Each input's `name` attribute = the field's `target`.
27
+ 2. **Insert** at `injectAt` (e.g. `position: "before"` the `section.closing`). Additive only — do not alter surrounding markup or the global `<style>`. Put the form's own CSS in a single scoped `<style>` block that references the design tokens.
28
+ 3. **Wire submission** with the script below.
29
+
30
+ ### B. Wire — connect an existing `<form>` (the form-shaped-design path)
31
+
32
+ The design already has a `<form>` (binding-map entry, `entity: "forms.submit"`). Map its inputs' `name`/`id` to the form's field `target`s, intercept submit, and post via the SDK. Keep the existing markup and styling; only add the submit handler script.
33
+
34
+ ## The submission script (both cases)
35
+
36
+ Append one `<script type="module">` (before `</body>`). Inline the literal `appId` and `formId`.
37
+
38
+ ```html
39
+ <script type="module">
40
+ import { createClient, OAuthStrategy } from "https://esm.sh/@wix/sdk@1";
41
+ import { submissions } from "https://esm.sh/@wix/forms@1";
42
+
43
+ const wix = createClient({
44
+ modules: { submissions },
45
+ auth: OAuthStrategy({ clientId: "REPLACE_WITH_APP_ID" }), // appId from wix.config.json
46
+ });
47
+
48
+ const FORM_ID = "REPLACE_WITH_FORM_ID";
49
+ const form = document.querySelector("#wix-rsvp-form"); // the injected/targeted form
50
+
51
+ form?.addEventListener("submit", async (e) => {
52
+ e.preventDefault();
53
+ const btn = form.querySelector("[type=submit]");
54
+ if (btn) btn.disabled = true;
55
+
56
+ // keys MUST be the Wix field `target`s (input name="<target>")
57
+ const data = Object.fromEntries(new FormData(form).entries());
58
+
59
+ try {
60
+ const result = await wix.submissions.createSubmission({
61
+ formId: FORM_ID,
62
+ submissions: data,
63
+ });
64
+ if (result.status === "PENDING" || result.status === "CONFIRMED") {
65
+ form.querySelector("[data-wix-success]")?.removeAttribute("hidden");
66
+ form.reset();
67
+ } else {
68
+ throw new Error("unexpected submission status: " + result.status);
69
+ }
70
+ } catch (err) {
71
+ console.error("[wix-forms] submission failed:", err);
72
+ form.querySelector("[data-wix-error]")?.removeAttribute("hidden");
73
+ // surface field-level violations if present
74
+ const violations = err?.details?.validationError?.fieldViolations ?? [];
75
+ for (const v of violations) {
76
+ for (const fe of (v?.data?.errors ?? [])) {
77
+ const el = form.querySelector(`[name="${fe.errorPath}"]`);
78
+ if (el) el.setAttribute("aria-invalid", "true");
79
+ }
80
+ }
81
+ } finally {
82
+ if (btn) btn.disabled = false;
83
+ }
84
+ });
85
+ </script>
86
+ ```
87
+
88
+ - Include a hidden success node (`<p data-wix-success hidden>…</p>`) and error node (`<p data-wix-error hidden>…</p>`) in the form markup, styled with the tokens.
89
+ - The submission `data` keys are the field **`target`s** — set each input's `name` to its `target`.
90
+ - Pin the CDN versions (`@1`) in the import URLs; do not float `@latest` in shipped HTML.
91
+
92
+ ## Discipline (from `INSTRUCTIONS.md`)
93
+
94
+ - **Additive only** — never restructure the design or edit the global stylesheet; the injected form is self-contained.
95
+ - **Style from tokens** — use `var(--…)` from the site's `:root`; never introduce a foreign palette/font.
96
+ - **Guard the call** — try/catch; on failure show the error node, keep the form usable.
97
+ - **Inline `appId` + `formId` literally** — no env vars, no build-time substitution.
98
+
99
+ ## Return
100
+
101
+ Per `shared/RETURN_CONTRACT.md`: report the file(s) edited, the inject anchor used, the `formId` wired, and the form's `target`→input mapping. If `formId` was missing, return `status: "failed"` with `errors: [{ code: "FORM_NOT_SEEDED" }]` — do not invent one.
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: custom-stores-wiring
3
+ description: "Integration-mode wiring subagent for the stores capability. Connects a brought-in static site's product markup to Wix Stores — replaces hard-coded product cards with live productsV3 queries rendered into the existing DOM template, client-side via @wix/sdk + @wix/stores from CDN. Cart-add + checkout via the ecom guide."
4
+ ---
5
+
6
+ # Stores wiring (integration mode)
7
+
8
+ You wire the **stores capability** into a brought-in static site (`frontend = "custom"`). The design already shows products as **hard-coded sample cards**; you replace the sample data with live `@wix/stores` queries, rendering into the **existing card markup** the design provides. Client-side vanilla JS, `@wix/sdk` from CDN, no build. Read `INSTRUCTIONS.md` § "The technical spine" + § "Wiring discipline" first.
9
+
10
+ ## Inputs (inlined by the orchestrator)
11
+
12
+ - **`appId`** — `OAuthStrategy` `clientId` (from `wix.config.json`).
13
+ - **Binding-map entries** for `stores.products` regions: `{ file, anchor, shape, template, bindings, sampleCount }`.
14
+ - **Seeded `productIds` / slugs** (from Seed) — so the wired query shows the seeded catalog.
15
+ - **`tokens`** — design CSS custom properties (only needed if you add an empty-state node).
16
+
17
+ ## The read-and-render pattern (this is the core; blog/cms reuse it)
18
+
19
+ For each binding-map list region:
20
+
21
+ 1. **Keep the first sample child as the template.** The region (`anchor`) holds `sampleCount` near-identical children matching `template` (e.g. `article.product-card`). Clone that node per result; remove the remaining static samples. Do **not** restyle — the existing classes carry the design.
22
+ 2. **Query live data** and **bind fields** by the binding-map `bindings` map (DOM selector relative to template → entity field path).
23
+ 3. **Render on load**, guard with try/catch; on error leave the original samples visible.
24
+
25
+ ```html
26
+ <script type="module">
27
+ import { createClient, OAuthStrategy } from "https://esm.sh/@wix/sdk@1";
28
+ import { productsV3 } from "https://esm.sh/@wix/stores@1"; // V3 — never the V1 `products`
29
+
30
+ const wix = createClient({
31
+ modules: { productsV3 },
32
+ auth: OAuthStrategy({ clientId: "REPLACE_WITH_APP_ID" }),
33
+ });
34
+
35
+ const grid = document.querySelector("section.product-grid"); // binding-map anchor
36
+ const tpl = grid?.querySelector("article.product-card"); // binding-map template
37
+ if (grid && tpl) {
38
+ try {
39
+ const { items } = await wix.productsV3
40
+ .queryProducts({ fields: ["CURRENCY"] })
41
+ .limit(12)
42
+ .find();
43
+
44
+ const proto = tpl.cloneNode(true);
45
+ grid.replaceChildren(...items.map((p) => {
46
+ const card = proto.cloneNode(true);
47
+ // bindings: selector@attr → field path (e.g. "img.thumb@src" → media.mainMedia.image.url)
48
+ const img = card.querySelector("img.thumb"); if (img) img.src = p.media?.mainMedia?.image?.url ?? "";
49
+ const name = card.querySelector("h3.name"); if (name) name.textContent = p.name ?? "";
50
+ const price = card.querySelector("span.price"); if (price) price.textContent = p.priceData?.formatted?.price ?? "";
51
+ // description is RICH TEXT — bind plainDescription, never the HTML `description` (see note below)
52
+ const desc = card.querySelector(".description"); if (desc) desc.textContent = p.plainDescription ?? (p.description ?? "").replace(/<[^>]*>/g, "");
53
+ // link to a detail page if the design has one (see "Detail" below)
54
+ const link = card.querySelector("a"); if (link && p.slug) link.href = `/product/${p.slug}`;
55
+ return card;
56
+ }));
57
+ } catch (err) {
58
+ console.error("[wix-stores] product query failed:", err); // leave samples visible
59
+ }
60
+ }
61
+ </script>
62
+ ```
63
+
64
+ - **Use `productsV3`**, never V1 `products` (V1 silently returns 0 on V3 catalogs).
65
+ - **Description is rich text — bind `p.plainDescription`, never `p.description`.** `description` is HTML/ricos; binding it into `textContent` (or a framework `{…}` expression) renders literal `<p>…</p>` tags. Use `plainDescription` (a plain string), falling back to `description.replace(/<[^>]*>/g, "")` if absent.
66
+ - **(create × own only — N/A for brought-in static sites.)** When you *own* the markup (the SPA is generated, not brought in), size every image: Wix media URLs are full-resolution, so an `<img>` with no sizing overflows its card onto the text. Put each image in a fixed `aspect-ratio`/`height` slot with `width:100%; height:100%; object-fit:cover`. A brought-in static site is already sized by its own design — skip this.
67
+ - Apply the binding-map's actual selectors/field paths — the snippet's `img.thumb`/`h3.name`/`span.price`/`.description` are illustrative.
68
+ - **Categories:** if a region is `categoriesV3`, query `wix.categoriesV3.queryCategories().eq("visible", true).find()` (the builder rejects empty filters — always chain at least one predicate).
69
+
70
+ ## Detail (`shape: "detail"`)
71
+
72
+ If the design has a product-detail page keyed by slug, read the slug from the URL (`location.pathname`), `queryProducts().eq("slug", slug).find()`, and bind the single result into the detail markup. If there is no detail page, link cards to the catalog or omit links.
73
+
74
+ ## Buy / cart
75
+
76
+ Add-to-cart and checkout are the **ecom** capability — see `references/custom/ecom/WIRING.md`. If a card has a "Buy"/"Add" control and ecom is in the capability set, the ecom guide wires it; otherwise leave it inert or link to the product.
77
+
78
+ ## Discipline & return
79
+
80
+ Additive only; render into the existing template; inline `appId`; guard every call (samples are the error fallback). Return per `shared/RETURN_CONTRACT.md`: files edited, anchors wired, query used, seeded IDs surfaced. Missing seeded catalog → note it; the empty query still wires (Seed should have populated it).
@@ -5,17 +5,17 @@ description: "Implements vertical-agnostic ecommerce — cart page, checkout red
5
5
 
6
6
  # Ecom Implementer
7
7
 
8
- Extends `references/shared/IMPLEMENTER.md`. Read that file first for phase routing, REST auth + doc lookups, prompt-inlined inputs (no site.json reads), return contract, style conventions, and common failure modes.
8
+ Extends `references/shared/IMPLEMENTER.md`. Read that file first for phase routing, REST auth + doc lookups, prompt-inlined inputs (read only your `.wix/seeded.json` slice), return contract, style conventions, and common failure modes.
9
9
 
10
10
  ## Scope routing
11
11
 
12
12
  | Scope | Phase | Reference |
13
13
  |-------|-------|-----------|
14
14
  | `components` | Components (CartView, CartBadge — TSX only, **no CSS**) — `src/utils/discounts.ts` is pre-copied by the orchestrator | `../astro/ecom/CART_WIRING.md` |
15
- | ~~`components-css`~~ | **Do not dispatch.** `src/styles/components-ecom.css` is copied from `<SKILL_ROOT>/references/astro/templates/ecom/components-ecom.css` by the orchestrator's pre-Step-4.5 batch (see BUILD.md § Step 4.5). The template uses direct `var(--token)` CSS, so it works against any designer-published vocabulary without per-run rewrites. `COMPONENTS_CSS.md` documents that CSS for reference — there is no `components-css` subagent to dispatch. | — |
15
+ | ~~`components-css`~~ | **Do not dispatch.** `src/styles/components-ecom.css` is copied from `<SKILL_ROOT>/references/astro/templates/ecom/components-ecom.css` by the orchestrator's pre-Step-4.5 batch (see BUILD-astro.md § Step 4.5). The template uses direct `var(--token)` CSS, so it works against any designer-published vocabulary without per-run rewrites. `COMPONENTS_CSS.md` documents that CSS for reference — there is no `components-css` subagent to dispatch. | — |
16
16
  | `pages` | Pages (cart.astro, thank-you.astro, Navigation CartBadge mount) | `../astro/ecom/CART_PAGES.md` |
17
17
 
18
- > **Why `components` is split.** A single agent writing the .tsx islands plus the scoped CSS was Phase 3's critical path on the most recent run (204 s for ecom alone). The CSS file has no runtime coupling to the TSX components — it's referenced only by class name at build time — so it splits cleanly into a sibling agent that runs in the same dispatch batch. Mirrors the stores split. See `../astro/ecom/COMPONENTS_CSS.md` § "What this scope owns".
18
+ > **Why `components` is TSX-only.** The scoped CSS (`src/styles/components-ecom.css`) has no runtime coupling to the TSX components — it's referenced only by class name at build time — so it ships pre-copied from the template by the orchestrator (see the `components-css` scope-routing row above) rather than being written by an agent. Mirrors the stores split. See `../astro/ecom/COMPONENTS_CSS.md` § "What this scope owns".
19
19
 
20
20
  Note: `ecom` is never triggered independently — it's co-loaded by verticals that require it (`stores` today; `bookings`, `events` in the future). No `seed` scope — ecom has no data of its own; it works off line items from whichever catalog app is installed.
21
21
 
@@ -29,7 +29,7 @@ Components (`components` scope — TSX only):
29
29
  - `<SKILL_ROOT>/references/astro/templates/ecom/CartView.tsx`
30
30
  - `<SKILL_ROOT>/references/astro/templates/ecom/CartBadge.tsx`
31
31
 
32
- Components CSS (`components-css` scope — scoped CSS only):
32
+ Components CSS (pre-copied by the orchestrator — no agent writes it):
33
33
  - `<SKILL_ROOT>/references/astro/templates/ecom/components-ecom.css`
34
34
 
35
35
  ### Pre-copied by the orchestrator (do NOT write this yourself)
@@ -40,7 +40,7 @@ Components CSS (`components-css` scope — scoped CSS only):
40
40
 
41
41
  ## CSS ownership — ecom pack
42
42
 
43
- Ecom-specific component CSS lives in `src/styles/components-ecom.css` (written by your `components` scope), NOT in the designer's `global.css`. The classes you own:
43
+ Ecom-specific component CSS lives in `src/styles/components-ecom.css` (pre-copied from the template by the orchestrator before Step 4.5 — see the `components-css` scope-routing row above; your `components` scope imports it, never writes it), NOT in the designer's `global.css`. The classes the pack owns:
44
44
 
45
45
  - `.cart-summary` — the bordered/sticky summary panel on `/cart`. Compound bordered card; sticky on desktop.
46
46
  - `.cart-total` — the row inside the summary that anchors the total amount with a top rule and display-serif typography.
@@ -5,7 +5,7 @@ description: "Implements contact, lead, and signup forms via @wix/forms. Scopes:
5
5
 
6
6
  # Forms Implementer
7
7
 
8
- Extends `references/shared/IMPLEMENTER.md`. Read that file first for phase routing, REST auth + doc lookups, prompt-inlined inputs (no site.json reads), return contract, style conventions, and common failure modes.
8
+ Extends `references/shared/IMPLEMENTER.md`. Read that file first for phase routing, REST auth + doc lookups, prompt-inlined inputs (read only your `.wix/seeded.json` slice), return contract, style conventions, and common failure modes.
9
9
 
10
10
  ## Scope routing
11
11
 
@@ -17,7 +17,7 @@ Extends `references/shared/IMPLEMENTER.md`. Read that file first for phase routi
17
17
 
18
18
  ## Files this vertical creates / contributes
19
19
 
20
- See `<SKILL_ROOT>/references/verticals/forms.md` frontmatter.
20
+ Each scope's files are enumerated in `../astro/forms/CONTACT_FORM.md` (§ Form Setup, § React island, § Page wiring).
21
21
 
22
22
  ## Form purpose variants
23
23
 
@@ -5,7 +5,7 @@ description: "Implements the passive Wix Gift Cards vertical — runtime probe u
5
5
 
6
6
  # Gift Cards Implementer
7
7
 
8
- Extends `references/shared/IMPLEMENTER.md`. Read that file first for phase routing, REST auth + doc lookups, prompt-inlined inputs (no site.json reads), return contract, style conventions, and common failure modes.
8
+ Extends `references/shared/IMPLEMENTER.md`. Read that file first for phase routing, REST auth + doc lookups, prompt-inlined inputs (read only your `.wix/seeded.json` slice), return contract, style conventions, and common failure modes.
9
9
 
10
10
  ## Scope routing
11
11
 
@@ -18,11 +18,11 @@ This pack has **no `seed` scope** — the dashboard's eGift Card template is the
18
18
 
19
19
  ## Files this vertical creates / contributes
20
20
 
21
- See `<SKILL_ROOT>/references/verticals/gift-cards.md` frontmatter (`creates:` and `contributes:` blocks).
21
+ See the § "Templates" list below for the files each scope produces (and the nav/home contributions it patches).
22
22
 
23
23
  ## Pre-return file-existence assertion (pages scope)
24
24
 
25
- Before returning `status: "complete"` from the `pages` scope, verify every file in `creates:` (phase: pages) plus the patched files in `contributes:` exists on disk. If a declared file is missing, return `status: "partial"` with `errors: [{ code: "PHASE4_FILE_MISSING", path: "<expected path>" }]` rather than claiming success.
25
+ Before returning `status: "complete"` from the `pages` scope, verify every file the scope produces (the page templates in § "Templates" below, plus the patched `Navigation.astro` / `index.astro`) exists on disk. If a declared file is missing, return `status: "partial"` with `errors: [{ code: "PHASE4_FILE_MISSING", path: "<expected path>" }]` rather than claiming success.
26
26
 
27
27
  ## Templates
28
28
 
@@ -36,11 +36,15 @@ If your prompt is missing a `Scope:` line, stop and ask the parent — do not gu
36
36
  - **400** `unsupportedDimensions` → see § "Error Handling"
37
37
  - **400** `invalidTaskUUID` → `taskUUID` must be valid UUIDv4 → see § "Quick Reference"
38
38
 
39
- ## Quick Reference: Generation Call Shape
39
+ ## Preferred: generate + import via `generate-images.mjs`
40
40
 
41
- Before the first REST call, ensure the `curl` tool schema is loaded (the orchestrator's session auth covers this for the whole session per `<SKILL_ROOT>/references/commands/AUTHENTICATION.md` — only re-load if you hit a tool-not-found error). Use your runtime's AUTHENTICATION.md recovery ladder to look up the suffix.
41
+ **Run the phase's generation + Wix Media import through `<SKILL_ROOT>/scripts/generate-images.mjs`** (see `../shared/IMAGE_GENERATION.md` § "Preferred: run the whole phase through `generate-images.mjs`"). Build the image list — one entry per slot (Phase 1) or per entity (Phase 2), each with `{key, positivePrompt, width, height}` — and pipe it in with the run's cached `WIX_TOKEN`. The script fires all generations concurrently in-process and returns a `key → {url, fileId}` map plus a `slots` (key→url) convenience map. This is the deterministic form of the "one concurrent batch" rule — it cannot serialize and cannot hit the `google:4@2` N≥3 504. Then attach: Phase 1 → `write-decorative-json.mjs`; Phase 2 → the per-entity PATCH/PUT/publish recipe in this file. **You still own prompt construction** (brand-contextual, per the guidelines) and **entity attachment**; the script owns the parallel network round-trips only.
42
42
 
43
- **All generation tool calls for an image phase MUST be in one concurrent batch.** The exact shape depends on the model — see `../shared/IMAGE_GENERATION.md` § "Required: minimize round-trips" for the rule. In short:
43
+ ## Quick Reference: Generation Call Shape (manual fallback)
44
+
45
+ The shapes below are the **reference bodies** the script builds, and the **fallback** if you hand-drive generation. Before the first REST call, ensure the `curl` tool schema is loaded (the orchestrator's session auth covers this for the whole session per `<SKILL_ROOT>/references/shared/AUTHENTICATION.md` — only re-load if you hit a tool-not-found error). Use your runtime's AUTHENTICATION.md recovery ladder to look up the suffix.
46
+
47
+ **If you do hand-drive it, all generation tool calls for an image phase MUST be in one concurrent batch.** The exact shape depends on the model — see `../shared/IMAGE_GENERATION.md` § "Required (manual fallback): minimize round-trips" for the rule. In short:
44
48
 
45
49
  - **`google:4@2` (the default):** N concurrent 1-task `curl` calls as siblings in one batch. (Batched N≥3 times out at 504 on this model.)
46
50
  - **`bfl:5@1`, `runware:400@1`:** one batched `curl` call with N tasks in the body array.
@@ -108,12 +112,12 @@ Generate site-wide decorative images that don't depend on any entity. Used by th
108
112
  **Process (must follow this order):**
109
113
 
110
114
  1. **Craft all image prompts up front** using brand context — see `IMAGE_GENERATION.md` § "Prompt guidelines".
111
- 2. **Dispatch all generation tool calls in one concurrent batch** — siblings for `google:4@2` (1 task each, N blocks in parallel), or one batched call for other models (N tasks in `body`). Required, not optional — see `IMAGE_GENERATION.md` § "Required: minimize round-trips per image phase". Sequential 1-task calls across multiple turns is an anti-pattern; never do it.
115
+ 2. **Generate + import via `generate-images.mjs`** (preferred — § "Preferred: generate + import" above): build the `images` list (`key` = slot name, e.g. `hero`/`about`) and run the script with the cached `WIX_TOKEN`; it fires all generations concurrently and returns the `slots` map. **Manual fallback only:** follow § "Mandatory pre-call procedure" above (construct ALL tasks first, dispatch in one concurrent batch).
112
116
  3. **Import each to Wix Media** via `REST: POST https://www.wixapis.com/site-media/v1/files/import`.
113
117
  4. **Collect the resolved URLs keyed by slot purpose** (e.g., `{"hero": "https://static.wixstatic.com/...", "about": "https://static.wixstatic.com/..."}`). This map goes into your return JSON under `data.slots` — see § Return below. Do NOT write `.wix/image-urls.md` or any other file; the orchestrator pipes your `data.slots` directly into `patch-decorative-slots.mjs` via stdin.
114
118
  5. Return the structured JSON block per `../shared/RETURN_CONTRACT.md` (see § Return below). The JSON return is your sole output channel.
115
119
 
116
- The orchestrator runs `patch-decorative-slots.mjs` with your `data.slots` map piped in on stdin. The patch script injects `<img>` tags into the designer's `data-decorative-slot="<key>"` placeholders. If your return is missing or has no slots, the patch is a no-op and the placeholders fall back to the designer's solid-color rendering — nothing blocks.
120
+ The orchestrator consumes your `data.slots` map via one of two deterministic scripts, depending on the frontend — **your output contract is identical either way** (a slot→URL map; you never touch frontend source): on **astro** it pipes the map into `patch-decorative-slots.mjs`, which injects `<img>` tags into the designer's `data-decorative-slot="<key>"` placeholders in `.astro` pages; on a **framework-SPA (`own`)** it pipes the map into `write-decorative-json.mjs`, which writes `src/decorative-images.json` for the generated app to import. Either way, if your return is missing or has no slots, the consumer is a no-op and the placeholders fall back to the designer's solid-color (themed-block) rendering — nothing blocks.
117
121
 
118
122
  ## Scope: `image-phase-2-entity` (Phase 1 Seed data inline)
119
123
 
@@ -131,14 +135,11 @@ Generate images for products, blog posts, and CMS items. Attach via REST PATCH c
131
135
  **Process per entity type (must follow):**
132
136
 
133
137
  1. **Craft all image prompts** for this entity type up front, using each entity's own context (name, description, title, etc.).
134
- 2. **Dispatch all generation tool calls in one concurrent batch** — same dispatch shape as Phase 1 Decorative:
135
- - For `google:4@2` (default): N parallel sibling `curl` tool calls, one task each.
136
- - For `bfl:5@1` / `runware:400@1` / others: ONE batched call with all N tasks in `body`.
137
- See `IMAGE_GENERATION.md` § "Required: minimize round-trips per image phase". Sequential 1-task calls across multiple turns is an anti-pattern.
138
+ 2. **Generate + import via `generate-images.mjs`** (preferred — § "Preferred: generate + import" above): build the `images` list with `key` = each entity's ID, run the script with the cached `WIX_TOKEN`, and read the returned `map[entityId].url` / `.fileId` for the attach step. The script generates all entity images concurrently and isolates per-image failures (`status: "partial"`) — including the `google:4@2` 504 retry below, handled in-script. **Manual fallback only:** follow § "Mandatory pre-call procedure" above (construct ALL tasks first, dispatch in one concurrent batch).
138
139
 
139
- **`google:4@2` 504 retry.** Even with N concurrent siblings, individual tasks intermittently 504. When the response array contains an entry with `errorMessage: "Request timed out"` or HTTP 504, retry **only the failing task(s)** in a follow-up batch — do NOT re-dispatch the whole batch. Cap at 1 retry per task; if it 504s twice, fall back to `bfl:5@1` for that task or skip it (entity gets no image; user can upload from dashboard).
140
+ **`google:4@2` 504 retry** (manual fallback; the script does this for you). Even with N concurrent siblings, individual tasks intermittently 504. When the response array contains an entry with `errorMessage: "Request timed out"` or HTTP 504, retry **only the failing task(s)** in a follow-up batch — do NOT re-dispatch the whole batch. Cap at 1 retry per task; if it 504s twice, fall back to `bfl:5@1` for that task or skip it (entity gets no image; user can upload from dashboard).
140
141
 
141
- **N≥6 entities — stagger.** When you have 6 or more entities of one type, split into pairs of 3 parallel siblings rather than 6+ in one shot. Runware throttles google:4@2 above ~4 concurrent tasks per request burst, and the timeout ladder gets steeper. Two messages with 3 siblings each is reliably faster than one message with 6 + multiple retries. (Heuristic — refine after more runs collect data.)
142
+ **N≥6 entities — stagger.** When you have 6 or more entities of one type, split into pairs of 3 parallel siblings rather than 6+ in one shot. Runware throttles google:4@2 above ~4 concurrent tasks per request burst, and the timeout ladder gets steeper. Two messages with 3 siblings each is reliably faster than one message with 6 + multiple retries.
142
143
  3. **Import each to Wix Media**. Imports can parallelize.
143
144
  4. **PATCH each entity** with its image URL / file ID. PATCH calls can also parallelize (sibling `curl` tool calls in one message).
144
145
 
@@ -192,7 +193,7 @@ Generate images for products, blog posts, and CMS items. Attach via REST PATCH c
192
193
  2. Retry the PATCH once with the new revision.
193
194
  3. If the retry also fails with 409, surface the error — something else is mutating the entity faster than we can react. Don't loop.
194
195
 
195
- Successful PATCHes from the original parallel batch keep their state; only the 409'd entity needs the recovery. Cap at one retry per failed entity. Append to `run.json.recoveries[]`: `{ "code": "INVALID_REVISION_RETRY", "entityId": "<id>", "originalRevision": "<x>", "actualRevision": "<y>" }`.
196
+ Successful PATCHes from the original parallel batch keep their state; only the 409'd entity needs the recovery. Cap at one retry per failed entity.
196
197
 
197
198
  ### Blog Posts (if `blogPosts` is in your prompt)
198
199
 
@@ -280,11 +281,11 @@ At the end, emit a structured JSON block per `../shared/RETURN_CONTRACT.md`. Do
280
281
  "summary": "Generated N decorative images; uploaded to Wix Media; returned slot→URL map",
281
282
  "data": {
282
283
  "decorativeCount": 3,
283
- "purposes": ["hero", "about", "background"],
284
+ "purposes": ["hero", "about", "productsHeader"],
284
285
  "slots": {
285
286
  "hero": "https://static.wixstatic.com/media/...",
286
287
  "about": "https://static.wixstatic.com/media/...",
287
- "background": "https://static.wixstatic.com/media/..."
288
+ "productsHeader": "https://static.wixstatic.com/media/..."
288
289
  },
289
290
  "model": "google:4@2",
290
291
  "totalCredits": 0.297
@@ -336,7 +337,7 @@ The JSON block MUST be the **last** content in your message (see `../shared/RETU
336
337
 
337
338
  | WRONG | CORRECT |
338
339
  |-------|---------|
339
- | N sequential 1-task `curl` generation calls across multiple turns | All generation tool calls in one concurrent batch — parallel siblings for `google:4@2`, or one batched call for other models. See IMAGE_GENERATION.md § "Required: minimize round-trips per image phase" |
340
+ | N sequential 1-task `curl` generation calls across multiple turns | Run `generate-images.mjs` (it parallelizes in-process); or, hand-driving, all generation tool calls in one concurrent batch — parallel siblings for `google:4@2`, or one batched call for other models. See IMAGE_GENERATION.md § "Required (manual fallback): minimize round-trips" |
340
341
  | Poll `.wix/logs/<feature>-data.md` sidecars to learn Phase 1 Seed is done | Phase 1 Seed data is inline in your prompt — if missing, return `failed` |
341
342
  | `sleep 60` loop to wait for Phase 1 Seed | No waiting, no polling — prompt has the data or the agent fails |
342
343
  | Write `.wix/logs/images.md` or `.wix/image-urls.md` sidecar | Return structured JSON per `RETURN_CONTRACT.md` instead (decorative URLs go in `data.slots`) |
@@ -8,8 +8,8 @@ Per-vertical recipe lookup for the seed dispatch in `SEED.md`. Recipe paths are
8
8
  | cms | `references/cms/cms-schema-management.md` (collection create) + `references/cms/cms-data-items-crud.md` (item create per collection) + `references/cms/cms-references-and-relationships.md` (only when a collection's `intent.cms.collections[N]` declares cross-references) | `collectionIds{}`, `itemIds{<collection>: []}` |
9
9
  | blog | `references/blog/how-to-create-blog-posts.md` | `postIds[]`, `categoryIds[]` |
10
10
  | forms | `references/forms/create-form.md` | `formIds[]` |
11
- | gift-cards | — (no seed surface; activation lives in Phase 2 app-install) | `{status: "skipped"}` |
12
- | ecom | — (cart/checkout vertical; no seed surface) | `{status: "skipped"}` |
11
+ | gift-cards | — *(no recipe by design — no seed surface; activation lives in Phase 2 app-install)* | `{status: "skipped"}` |
12
+ | ecom | — *(no recipe by design — cart/checkout vertical; no seed surface)* | `{status: "skipped"}` |
13
13
 
14
14
  The orchestrator dispatches one subagent per pack with a recipe. `gift-cards` and `ecom` get a phase entry of `{phase: "seed-<pack>", status: "skipped"}` recorded directly by the orchestrator without dispatching a subagent.
15
15
 
@@ -0,0 +1,47 @@
1
+ # AGENTS.md — the end-of-run site doc
2
+
3
+ The orchestrator writes one file at the end of a successful run: a project-root `AGENTS.md` describing **what the site has**. It is the one end-of-run artifact — *content about the site*, not telemetry. A fresh session (or a coding agent) opening the project reads it to learn what's there.
4
+
5
+ ## Author, location, timing
6
+
7
+ - **Author:** the orchestrator, in the final turn. Composed **from session scratch** (brand, frontend, verticals, the page/route list it built) **+ `.wix/seeded.json`** (entity counts). **Re-read nothing** to compose it.
8
+ - **Location:** project-root `AGENTS.md` — the conventional path agents auto-read. Root, not `.wix/`. It sits outside the astro/Vite bundler root, so it never ships to `dist/`.
9
+ - **Timing:** the **last tool call of the final message**. Summary prose (the live URL) first; `Write AGENTS.md` last — same ordering discipline `BUILD.md` § "Final Message" defines.
10
+
11
+ ## Content — fill this template, slotted values only
12
+
13
+ Deterministic projection of scratch + seeded counts → same inputs produce a byte-identical file. Emit exactly these sections; no free prose beyond the slots.
14
+
15
+ ```markdown
16
+ # <brand>
17
+
18
+ A Wix headless site built with the `wix-headless` skill. <one-line brand description>.
19
+
20
+ ## Live site
21
+ - **Site:** <published URL>
22
+ - **Dashboard:** https://manage.wix.com/dashboard/<siteId>
23
+
24
+ ## Frontend
25
+ <astro (Wix-hosted) | custom>. Run: `<wix dev | npm run dev>`. Build + publish: `<wix release | npm run build then wix release>`.
26
+
27
+ ## Features
28
+ - <one bullet per loaded, non-disabled vertical, in plain language>
29
+ Stores → a product catalog · CMS → content collections (About, FAQ, …) · Blog → posts · Forms → a contact form · Gift cards → activate from the dashboard
30
+
31
+ ## Pages
32
+ <one line per route that exists: `/`, `/products`, `/products/[slug]`, `/cart`, …>
33
+
34
+ ## Seeded content
35
+ <counts only: "3 products across 2 categories · 6 blog posts · About + FAQ collections.">
36
+
37
+ ## Extending
38
+ Built with the `wix-headless` skill; re-run it to add features or restyle.
39
+ ```
40
+
41
+ ## Excluded — never in AGENTS.md
42
+
43
+ No per-phase timings, statuses, `started`/`ended`/`seconds`, `x-wix-request-id`s, error codes, subagent handles, recoveries, or rate-limit notes. If a field would only matter to someone debugging the *run*, it does not belong here. (Entity IDs stay in `.wix/seeded.json`, not here — counts only.)
44
+
45
+ ## Not a state file
46
+
47
+ `AGENTS.md` is reading material. Project **detection** ("is this a wix-headless project / which frontend") keys off `wix.config.json` + the `@wix/astro` dep in `package.json` — never `AGENTS.md` presence.
@@ -19,7 +19,7 @@ The "stop and tell the user" path is a **last-resort fallback** for when the bac
19
19
  {"event":"awaiting_user","expiresInSeconds":600,"userCode":"TPV5HUG5","verificationUri":"https://users.wix.com/login/device-login?color=developer&studio=true"}
20
20
  ```
21
21
 
22
- (Earlier revisions of this doc claimed the CLI wrote human-readable prose to stderr with no JSON events — that was wrong. The events are JSON on stdout. There may be incidental Node warnings interleaved; line-by-line JSON parsing with a `try` around each line handles that cleanly.)
22
+ The events are JSON on stdout. There may be incidental Node warnings interleaved; line-by-line JSON parsing with a `try` around each line handles that cleanly.
23
23
 
24
24
  ### How to invoke — exact shape
25
25
 
@@ -79,7 +79,7 @@ The body is the recipe's documented JSON payload, with `siteId` inlined where th
79
79
 
80
80
  ## Recovery ladder
81
81
 
82
- **Do not re-mint the token as a recovery step** (see token-minting note above — a re-minted token is byte-identical). Retry the *same* call with the *same* cached token.
82
+ **Re-mint is never a recovery step — see Token minting.** Retry the *same* call with the *same* cached token.
83
83
 
84
84
  | Symptom | First response | If it still fails |
85
85
  |---|---|---|
@@ -105,6 +105,4 @@ SITE_TOKEN=$(npx @wix/cli@latest token --site "$SITE_ID")
105
105
 
106
106
  **Do not share tokens across scopes.** Site-operating calls (`wixapis.com/stores/v3/...`, `/blog/v3/...`, `/wix-data/v2/...`) need the **site** token + `wix-site-id` header; using the account token returns `403 SITE_TOKEN_REQUIRED`. Account-level calls (`manage.wix.com/credit-transactions/...`, `/subscriptions/...`) need the **account** token alone — no `wix-site-id` header; using the site token returns `403 ACCOUNT_TOKEN_REQUIRED`.
107
107
 
108
- Today the only account-scoped call in the skill is the Discovery Q3 balance lookup (`DISCOVERY.md` § 2.5.2). If a future phase needs another, mint a fresh account token at the call site (do not cache across the run alongside the site token — keep them in separate scratch slots so misuse is hard).
109
-
110
- **Historical note.** Earlier revisions of this file said the CLI did not expose an account-scoped primitive and concluded the balance lookup was unrecoverable. That was a misreading of `wix token --help` — the help output reads `Get a site-scoped access token` against `--site`, implying (correctly) that omitting `--site` returns the default, account-scoped token. The balance lookup was disabled for no good reason for several runs.
108
+ Today the only account-scoped call in the skill is the Discovery Q3 balance lookup (`DISCOVERY-create.md` § 2.5.2). If a future phase needs another, mint a fresh account token at the call site (do not cache across the run alongside the site token — keep them in separate scratch slots so misuse is hard).
@@ -0,0 +1,85 @@
1
+ # DESIGN.md — the design-token format (vendored spec)
2
+
3
+ `DESIGN.md` is the **single design artifact** of the wix-headless design-system phase. The Designer authors it; `emit-design-tokens.mjs` writes it + projects `.wix/design-tokens.css` and `.wix/site.d.ts` from it; `compose.mjs` reads its **frontmatter** to write the astro design-system files. It is the standalone, framework-agnostic spec a non-astro frontend, a human, or another tool can read.
4
+
5
+ This file is the **canonical spec inside the skill** — the public DESIGN.md frontmatter format (the `design.md` spec, captured here) plus the small, documented extensions this skill uses. Do not depend on the external `design.md` project at runtime.
6
+
7
+ ## Frontmatter structure
8
+
9
+ A `DESIGN.md` file is YAML frontmatter delimited by `---`, optionally followed by a free-form markdown body:
10
+
11
+ ```yaml
12
+ ---
13
+ version: alpha # optional
14
+ name: <string> # the brand / design-system name
15
+ colors:
16
+ <token-name>: <Color>
17
+ typography:
18
+ <token-name>:
19
+ fontFamily: <string>
20
+ fontSize: <Dimension> # optional (unused by this skill)
21
+ fontWeight: <number> # optional
22
+ lineHeight: <Dimension|number> # optional
23
+ letterSpacing: <Dimension> # optional
24
+ spacing:
25
+ <scale-level>: <Dimension|number>
26
+ rounded: # corner radii (DESIGN.md's name for radius tokens)
27
+ <scale-level>: <Dimension>
28
+ containers: # EXTENSION (this skill): content/reading widths
29
+ <scale-level>: <Dimension>
30
+ googleFontsHref: <string> # EXTENSION (this skill): the ready Google Fonts <link> href
31
+ ---
32
+
33
+ # free-form body — documentation only, NEVER parsed
34
+ ```
35
+
36
+ ### Value types
37
+
38
+ - **Color** — any valid CSS color string (hex `#RRGGBB`, `rgb()`, `hsl()`, named). **Quote hex values** — an unquoted `#hex` after `: ` is a YAML comment.
39
+ - **Dimension** — a string with a unit suffix: `px`, `em`, `rem` (e.g. `"1rem"`, `16px`).
40
+ - **Token reference** — `{path.to.value}` (curly-brace object path into the YAML tree).
41
+
42
+ ## How this skill uses it
43
+
44
+ ### Frontmatter only is canonical
45
+
46
+ `compose.mjs` and `emit-design-tokens.mjs` read the **frontmatter only**. The markdown body is documentation and is **never parsed** — so a generated `DESIGN.md` can carry a minimal or empty body without affecting the build, and run-to-run body variance never reaches the output.
47
+
48
+ ### Token vocabulary (the groups this skill consumes)
49
+
50
+ | DESIGN.md group | wix CSS projection | Notes |
51
+ |---|---|---|
52
+ | `colors` | `--color-<key>` | semantic role keys (see color roles below) |
53
+ | `typography.<level>.fontFamily` | `--font-<level>` | `display` + `body` required; `mono` optional |
54
+ | `spacing` | `--spacing-<key>` | full `2xs…4xl` rhythm scale |
55
+ | `rounded` | `--radius-<key>` | `sm` + `md` required |
56
+ | `containers` | `--container-<key>` | **extension** — content widths, a separate axis from spacing (`prose, md, 3xl, 6xl`) |
57
+ | `googleFontsHref` | the Layout `<link>` href | **extension** — the ready stylesheet URL for the chosen families |
58
+
59
+ ### Color roles — wix-native keys are the contract
60
+
61
+ The skill's component-CSS templates reference a fixed set of `--color-*` names (`STYLING.md` § "Required tokens"). So the **canonical color token keys in our DESIGN.md are the wix editorial roles** — and these are valid DESIGN.md color token names (the format leaves token names free-form):
62
+
63
+ `paper` (primary background), `paper-warm` (secondary surface), `ink` (primary text / dark fills), `ink-soft`, `mute` (muted text), `rule` (borders / dividers), `accent` (brand emphasis), `cream`, `error`.
64
+
65
+ `paper`, `paper-warm`, `ink`, `mute`, `rule`, `accent` are **required**; `ink-soft`, `cream`, `error` recommended (derived as a fail-safe if absent).
66
+
67
+ ### Standard-role compatibility (reading an externally-authored DESIGN.md)
68
+
69
+ A DESIGN.md authored elsewhere may use the DESIGN.md spec's *common* semantic roles instead of the wix-native keys. `compose.mjs` carries a **role-translation table** so such a file is still consumable; wix-native keys are not in the table and pass through unchanged (winning on conflict):
70
+
71
+ | standard role | → wix `--color-*` | | standard role | → wix `--color-*` |
72
+ |---|---|---|---|---|
73
+ | `primary` | `accent` | | `surface` / `background` | `paper` |
74
+ | `secondary` | `paper-warm` | | `on-surface` / `on-background` | `ink` |
75
+ | `tertiary` | `ink-soft` | | `outline` | `rule` |
76
+ | `neutral` | `mute` | | `error` | `error` |
77
+
78
+ This translation is a **compatibility layer**, not the authoring path: the Designer in this skill emits the wix-native keys directly (lossless — no role round-trip), so `STYLING.md` and every `components-<pack>.css` template stay untouched.
79
+
80
+ ## Producers & consumers in the run
81
+
82
+ - **Designer** (`DESIGN_SYSTEM.md`) — **authors `DESIGN.md` directly** (its frontmatter is the spec); returns only the brand-voice strings + the `DESIGN.md` path.
83
+ - **`emit-design-tokens.mjs`** — reads the Designer's `DESIGN.md` and projects `.wix/design-tokens.css` + `.wix/site.d.ts` from its frontmatter. It does **not** write `DESIGN.md` (the Designer does).
84
+ - **`compose.mjs`** — reads `DESIGN.md` frontmatter → writes the 6 astro design-system files (astro only).
85
+ - **Non-astro (`own`) frontends** — import `.wix/design-tokens.css` for the same values; component composition stays framework-native (no `compose.mjs`).