@wix/agent-skills 1.24.0 → 1.25.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 (30) hide show
  1. package/README.md +1 -0
  2. package/package.json +2 -1
  3. package/skills/wix-app/SKILL.md +4 -1
  4. package/skills/wix-app/references/BUSINESS_MANAGER_THEME.md +108 -0
  5. package/skills/wix-app/references/BUSINESS_MANAGER_TOKENS.md +81 -0
  6. package/skills/wix-app/references/DASHBOARD_MODAL.md +41 -0
  7. package/skills/wix-app/references/DASHBOARD_PAGE.md +2 -0
  8. package/skills/wix-app/references/DASHBOARD_PLUGIN.md +19 -4
  9. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +5 -4
  10. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +8 -7
  11. package/skills/wix-app/references/dashboard-page/DYNAMIC_PARAMETERS.md +21 -38
  12. package/skills/wix-headless/SKILL.md +0 -1
  13. package/skills/wix-headless/references/CAPABILITIES.md +3 -3
  14. package/skills/wix-headless/references/DISCOVERY.md +1 -1
  15. package/skills/wix-headless/references/SDK_HANDOFF.md +1 -1
  16. package/skills/wix-headless/references/SEED.md +1 -1
  17. package/skills/wix-headless/references/SETUP.md +1 -1
  18. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +1 -1
  19. package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +2 -2
  20. package/skills/wix-headless/references/managed/AUTHENTICATION.md +3 -14
  21. package/skills/wix-headless/scripts/bootstrap.mjs +156 -0
  22. package/skills/wix-headless-kit/SKILL.md +4 -4
  23. package/skills/wix-headless-kit/install/AGENTS.md +2 -2
  24. package/skills/wix-headless-kit/install/bootstrap.mjs +156 -0
  25. package/skills/wix-headless-kit/install/check.mjs +1 -1
  26. package/skills/wix-manage/SKILL.md +2 -8
  27. package/skills/wix-manage/references/cms/cms-data-items-crud.md +250 -18
  28. package/skills/wix-manage/references/cms/cms-schema-management.md +52 -1
  29. package/skills/wix-manage/references/cms/cms-data-operations-extended.md +0 -263
  30. package/skills/wix-manage/references/cms/cms-references-and-relationships.md +0 -162
package/README.md CHANGED
@@ -58,6 +58,7 @@ npx skills add wix/skills -g
58
58
  | [wix-app](skills/wix-app/SKILL.md) | Build Wix app extensions | Adding any extension — dashboard pages, site widgets, backend events, service plugins, embedded scripts, data collections, and more |
59
59
  | [wix-design-system](skills/wix-design-system/SKILL.md) | Wix Design System reference | Looking up WDS component props, examples, icons |
60
60
  | [wix-manage](skills/wix-manage/SKILL.md) | Wix business solution management | REST API operations for configuring and managing Wix business solutions |
61
+ | [wix-headless-kit](skills/wix-headless-kit/SKILL.md) | Build and release a Wix Headless site on shipped, verified per-solution code | Building a new headless site for a business from a brief — store, bookings, blog, events, restaurants, members, donations and more — fast, with the integration code already written |
61
62
  | [wix-headless](skills/wix-headless/SKILL.md) | Connect Wix business services to a headless frontend (SDK + Wix CLI), and optionally build & host the site | Setting up a Wix Headless backend or adding Wix business features (Stores, Bookings, CMS, Blog, Events, Forms, Members, Restaurants, Portfolio, Pricing Plans) — install apps, seed content, and produce an SDK-integration guide; for managed projects also scaffold a new site (create) or wire an existing design (connect), then build and release. Works across managed, self-managed, and stripe project types |
62
63
  | [wix-vibe-headless](skills/wix-vibe-headless/SKILL.md) | Connect an existing front end to Wix over client-only REST | Wiring a vibe-coded / HTML / Vite app to a live Wix site (storefront, bookings, blog, events, portfolio, restaurants, CMS, pricing plans) from the browser with a public `WIX_CLIENT_ID` — no SDK, no backend |
63
64
  | [wix-docs](skills/wix-docs/SKILL.md) | Look up the Wix API/SDK docs (shared fallback) | Confirming an exact Wix endpoint, method schema, field, or enum before writing code — `curl` doc-search + the `.md`-twin trick, or the Wix MCP tools. Referenced by the other skills as their docs-lookup fallback |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/agent-skills",
3
- "version": "1.24.0",
3
+ "version": "1.25.0",
4
4
  "description": "Wix Skills for AI coding agents — versioned npm distribution of the wix/skills content.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "skills/**",
19
+ "!skills/wix-headless-cold-start/**",
19
20
  "README.md",
20
21
  "LICENSE"
21
22
  ],
@@ -43,7 +43,8 @@ Helps build extensions for Wix CLI applications. Covers all extension types: das
43
43
  - [ ] **Compile as you go:** ran `npx tsc --noEmit` after the first file that imports `@wix/patterns`, not only at Step 5. Patterns' state and filter APIs are the most common source of errors, and finding twenty of them in one batch after the page is written costs far more than finding two early.
44
44
  - [ ] **🛑 Component Selection Gate (MANDATORY, dashboard UI only):** For every UI element on a Dashboard Page, resolved it against `@wix/patterns` BEFORE reaching for `@wix/design-system` — and never hand-rolled a component either library already provides. See [Component Selection Order](#component-selection-order).
45
45
  - [ ] Invoked `wix-design-system` skill ONLY before editing the first `.tsx`/`.jsx` file that imports `@wix/design-system`. Skip for backend-only or data-only extensions.
46
- - [ ] WDS: imported `@wix/design-system/styles.global.css` in the main component entry file (`page.tsx`, modal `.tsx`, etc.) — not child/tab/helper files.
46
+ - [ ] WDS: the design-system stylesheets are imported in exactly one place per app — `BusinessManagerTheme.tsx` for a dashboard surface (see the next item), or the main component entry file for a site/editor extension. Never in child, tab or helper files, and never twice.
47
+ - [ ] **🛑 Business Manager theme (every dashboard surface — page, modal AND plugin):** wrote `BusinessManagerTheme.tsx` once (both stylesheets, including `themes/odeditor.global.css`, plus `WixDesignSystemProvider` → `WixDesignSystemIconThemeProvider` → `IconThemeProvider theme="odeditor"` → `WixDesignSystemDefaultPropsProvider`), and wrapped **each** extension's root in it — above `WixPatternsProvider` and above `CustomModalLayout`. Every extension is a separate iframe that inherits none of the redesign, so theming the page does nothing for a modal it opens or a plugin in a slot; each one needs its own wrapper. Also: every icon from `@wix/wix-ui-icons-common/lazy`, and `--wds-*` tokens or `skin`/`size` props rather than hardcoded colours, font sizes or inline `style` ([BUSINESS_MANAGER_TOKENS.md](references/BUSINESS_MANAGER_TOKENS.md) — note the theme rebases the `SP*` spacing unit from 6px to 4px). `tsc`, `wix build` and `wix preview` all pass on an unthemed surface — only looking at it catches this. See [BUSINESS_MANAGER_THEME.md](references/BUSINESS_MANAGER_THEME.md).
47
48
  - [ ] **Step 4c (dashboard page UI only):** Re-opened and read the page file(s) just written — not recalled intent — and confirmed against the actual code: no `SummaryBar` unless the request asked for one, a routed drill-in (`navigateToEntityPage`) for every row and no `SidePanel` used as one, every declared filter name also appearing inside `fetchData`, and — for Cases A/B/D — the entry file both passes and guards `location`. See [UX Completeness Self-Audit](#step-4c-ux-completeness-self-audit).
48
49
  - [ ] **Step 5:** Ran validation (see [Validation](#validation))
49
50
  - [ ] Dependencies installed
@@ -209,6 +210,8 @@ Use a Dashboard Modal for dialogs that neither write nor display a listed record
209
210
  | Wix Stores Versioning (V1/V3) | [STORES_VERSIONING.md](references/STORES_VERSIONING.md) |
210
211
  | Official Documentation Links | [DOCUMENTATION.md](references/DOCUMENTATION.md) |
211
212
  | Wix Patterns Dashboard Pages | [WIX_PATTERNS_DOCS.md](references/WIX_PATTERNS_DOCS.md) |
213
+ | Business Manager theme — the wrapper every dashboard page, modal and plugin needs | [BUSINESS_MANAGER_THEME.md](references/BUSINESS_MANAGER_THEME.md) |
214
+ | Business Manager tokens — `--wds-*` replacements, the rebased spacing unit, per-component adjustments | [BUSINESS_MANAGER_TOKENS.md](references/BUSINESS_MANAGER_TOKENS.md) |
212
215
  | Dashboard UX Success Model (what a good dashboard contains) | [UX_SUCCESS_MODEL.md](references/dashboard-page/UX_SUCCESS_MODEL.md) |
213
216
  | Draft template — start here for any dashboard page (Cases A/B/C/D) | [DRAFT_TEMPLATE.md](references/dashboard-page/DRAFT_TEMPLATE.md) |
214
217
  | Draft template — collection page for Cases A/B/D | [DRAFT_TEMPLATE_COLLECTION.md](references/dashboard-page/DRAFT_TEMPLATE_COLLECTION.md) |
@@ -0,0 +1,108 @@
1
+ # Business Manager theme — one wrapper, every dashboard surface
2
+
3
+ Business Manager (the Wix site dashboard) was redesigned with the Harmony theme. **A dashboard extension runs in its own iframe and inherits none of it.** `WixDesignSystemProvider` alone gives the pre-redesign look — classic icons, pre-redesign button sizes and skins — rendered inside redesigned platform chrome.
4
+
5
+ **No automated check catches this.** `tsc`, `wix build` and `wix preview` all pass on an unthemed surface — every import resolves and every component renders. The failure is purely visual, so wire it from the start.
6
+
7
+ Verified against `@wix/design-system` 1.330.0 and `@wix/wix-ui-icons-common` 3.189.28 — both providers are root exports, `IconTheme` is typed `'default' | 'odeditor'`, and `themes/odeditor.global.css`, `lazy`, `lazy/system` and `core` all ship.
8
+
9
+ ## 1. Both packages, together
10
+
11
+ ```bash
12
+ npm install @wix/design-system@latest @wix/wix-ui-icons-common@latest
13
+ ```
14
+
15
+ The redesigned styles and matching icon set ship as a pair — update them together. An older `@wix/design-system` leaves a surface half-migrated however the providers are wired, since refinements ship continuously during the rollout.
16
+
17
+ ## 2. The wrapper — write this file once per app
18
+
19
+ ```tsx
20
+ // src/extensions/dashboard/BusinessManagerTheme.tsx
21
+ import type { FC, ReactNode } from 'react';
22
+ import { i18n } from '@wix/essentials';
23
+ import {
24
+ WixDesignSystemProvider,
25
+ WixDesignSystemIconThemeProvider,
26
+ WixDesignSystemDefaultPropsProvider,
27
+ type WixDesignSystemDefaultProps,
28
+ } from '@wix/design-system';
29
+ import { IconThemeProvider } from '@wix/wix-ui-icons-common/core';
30
+ import '@wix/design-system/styles.global.css';
31
+ import '@wix/design-system/themes/odeditor.global.css';
32
+
33
+ const BUSINESS_MANAGER_DEFAULTS: WixDesignSystemDefaultProps = {
34
+ Button: { size: 'small', skin: 'dark' },
35
+ IconButton: { size: 'small', skin: 'dark', priority: 'tertiary' },
36
+ TextButton: { size: 'small', skin: 'standard' },
37
+ Input: { size: 'small' },
38
+ };
39
+
40
+ export const BusinessManagerTheme: FC<{ children: ReactNode; locale?: string }> = ({
41
+ children,
42
+ locale = i18n.getLocale(),
43
+ }) => (
44
+ <WixDesignSystemProvider locale={locale}>
45
+ <WixDesignSystemIconThemeProvider>
46
+ <IconThemeProvider theme="odeditor">
47
+ <WixDesignSystemDefaultPropsProvider defaults={BUSINESS_MANAGER_DEFAULTS}>
48
+ {children}
49
+ </WixDesignSystemDefaultPropsProvider>
50
+ </IconThemeProvider>
51
+ </WixDesignSystemIconThemeProvider>
52
+ </WixDesignSystemProvider>
53
+ );
54
+ ```
55
+
56
+ Duplicating these four providers per entry file is how one surface silently drifts out of the theme. Each piece earns its place:
57
+
58
+ | Piece | Without it |
59
+ | --- | --- |
60
+ | `themes/odeditor.global.css` | `--wds-*` tokens keep pre-redesign values, so every component renders the old palette |
61
+ | `WixDesignSystemIconThemeProvider` + `IconThemeProvider` | Icons stay classic — heavier strokes, wrong sizes beside redesigned components |
62
+ | `WixDesignSystemDefaultPropsProvider` | Buttons and inputs render pre-redesign unless every call site passes `size`/`skin` by hand |
63
+
64
+ **Order is outermost-first and fixed**, and `WixPatternsProvider` goes *inside* the wrapper: the defaults provider must sit above the components it supplies defaults to, and the WDS leaf UI inside a patterns shell is exactly that.
65
+
66
+ A prop on a component still wins over the provider, so a one-off `size="medium"` is fine. **A nested `WixDesignSystemDefaultPropsProvider` replaces these defaults rather than merging**, so don't add a second for one subtree. And don't pass `features={{ newColorsBranding: true }}` — it predates the theme and is not a substitute.
67
+
68
+ ## 3. Where the wrapper goes
69
+
70
+ **Write the file once per app; use it once per extension.** Every dashboard extension — page, modal, plugin — is a separate iframe, so each needs its own wrapper at its own root, in the file that owns the providers, never in a child, tab or helper file:
71
+
72
+ | Surface | File | Section |
73
+ | --- | --- | --- |
74
+ | Page, Cases A/B/D (router-wired) | `{feature}.tsx` | [DRAFT_TEMPLATE_ROUTER.md § 1](dashboard-page/DRAFT_TEMPLATE_ROUTER.md#1-entry--location-is-manual-in-a-wix-cli-app-and-only-because-the-router-needs-it) |
75
+ | Page, Case C (settings only) | `{feature}.tsx` | [DRAFT_TEMPLATE.md § 1](dashboard-page/DRAFT_TEMPLATE.md#1-entry--case-c-only-router-free-no-location-plumbing) |
76
+ | Page with dynamic parameters | `withProviders.tsx` | [DYNAMIC_PARAMETERS.md](dashboard-page/DYNAMIC_PARAMETERS.md#provider-wrapper-implementation) |
77
+ | Modal | the generated `<modal>.tsx` | [DASHBOARD_MODAL.md](DASHBOARD_MODAL.md#theme) |
78
+ | Plugin | the generated plugin component | [DASHBOARD_PLUGIN.md](DASHBOARD_PLUGIN.md#theme) |
79
+
80
+ Each surface's own doc shows the wrapper already in place. Copy that file as-is rather than re-adding providers by hand. A plugin is the least forgiving of the three: it renders inside a redesigned first-party page, so an unthemed one is surrounded by the very styling it is missing.
81
+
82
+ ## 4. Import icons from the lazy entry point
83
+
84
+ Icons imported from the package root render classic **regardless of the providers above them**. Only the lazy entry point resolves through `IconThemeProvider`:
85
+
86
+ ```diff
87
+ - import { Add, Confirm } from '@wix/wix-ui-icons-common';
88
+ + import { Add, Confirm } from '@wix/wix-ui-icons-common/lazy';
89
+ ```
90
+
91
+ Use `lazy` for every icon on a dashboard surface. Outside Business Manager it keeps rendering the current set, so this is the default import, not a Business-Manager-only one. An `iconKey` in a builder file names an icon for the platform rather than importing one — leave those alone.
92
+
93
+ Two things worth knowing before you convert everything:
94
+
95
+ - **`/lazy/system` is not where app icons live.** The `system` entry holds WDS's own internal component decorations (`CheckboxChecked`, `DropDownArrow`, …) — about 80 glyphs. Ordinary icons like `Add` and `Confirm` are in `/lazy` itself, so importing them from `/lazy/system` fails `tsc` with "no exported member".
96
+ - **A lazy icon is a network fetch.** `core/icon.js` fetches the glyph JSON from the CDN at render time and suspends, falling back to an empty state on failure. That is fine in the dashboard, but a unit test asserting icon markup synchronously will see the fallback. If you need the redesign glyphs statically inlined with no provider and no fetch, `@wix/wix-ui-icons-common/odeditor` is a real entry point — `lazy` is still the default here because one import keeps tracking the right set both inside and outside Business Manager.
97
+
98
+ ## 5. Tokens and component adjustments
99
+
100
+ Everything you style yourself — which `--wds-*` token replaces a hardcoded value, which `skin`/`size` prop replaces an inline `style`, the spacing unit the theme rebases, and the per-component adjustments the wrapper can't make for you — is in [BUSINESS_MANAGER_TOKENS.md](BUSINESS_MANAGER_TOKENS.md). Read it before styling anything by hand.
101
+
102
+ ## 6. Verify
103
+
104
+ - The entry file wraps the page in `BusinessManagerTheme`, and that file imports both stylesheets and nests all four providers in order.
105
+ - Every icon comes from `@wix/wix-ui-icons-common/lazy` (not the package root, and not `/lazy/system`).
106
+ - `grep -rn "style={{" src/` and `grep -rn "#[0-9A-Fa-f]\{3,6\}" src/` return nothing for the page's own files, or only lines carrying a justification comment.
107
+ - In devtools, a component's colours resolve from `--wds-*` properties. A literal means that element is still custom-styled.
108
+ - Hover, focus, disabled, selected, error, warning and success all render — a token gap usually surfaces in a state, not at rest.
@@ -0,0 +1,81 @@
1
+ # Business Manager tokens — what to use instead of a hardcoded value
2
+
3
+ Companion to [BUSINESS_MANAGER_THEME.md](BUSINESS_MANAGER_THEME.md), which sets the theme up. This file covers what you style yourself once it is wired.
4
+
5
+ A hardcoded colour or font size keeps its old value while the themed components around it change — the most visible way a surface looks half migrated. Everything below was resolved against the installed `@wix/design-system` 1.330.0 `themes/odeditor.global.css` and component typings, not from a design-side migration note.
6
+
7
+ ## 1. Tokens, not hardcoded values
8
+
9
+ Use a `--wds-*` custom property, or the component's own `skin`/`size` prop.
10
+
11
+ The middle column is the value each token actually resolves to under the theme.
12
+
13
+ | Use case | Resolves to | Token |
14
+ | --- | --- | --- |
15
+ | Primary action fill | `#2F5DFF` | `--wds-color-fill-standard-primary` |
16
+ | Dark secondary fill | `#F0EFEF` | `--wds-color-fill-dark-secondary` |
17
+ | Dark secondary, hover | `#E8E7E7` | `--wds-color-fill-dark-secondary-hover` |
18
+ | Warning / success surface | yellow / green tones | `--wds-color-fill-warning-secondary`, `--wds-color-fill-success-secondary` |
19
+ | Primary text | `#151414` | `--wds-color-text-standard-primary` |
20
+ | Interactive / link | `#2F5DFF` | `--wds-color-text-primary` |
21
+ | Destructive text | `#DF3336` | `--wds-color-text-destructive` |
22
+ | Standard border | `#767574` | `--wds-color-border-dark-primary` |
23
+ | Subtle border | `#DEDEDE` | `--wds-color-border-dark-secondary` |
24
+ | Heading / body font | Madefor Display / Text | `--wds-font-family-display`, `--wds-font-family-default` |
25
+ | Heading 1 size / line height | `32px` / **`40px`** | `--wds-font-size-heading-1`, `--wds-font-line-height-heading-1` |
26
+ | Heading 1 weight | `500` | `--wds-font-weight-heading-1` |
27
+
28
+ Two traps in that table, both of which produce a declaration the browser silently drops:
29
+
30
+ - **`--wds-font-line-height-heading-1` resolves to 40px, not 32px.** If you are replacing a hardcoded `line-height: 32px`, the token changes your layout — that is the theme working, not a mistake, but know it before you swap.
31
+ - **`--wds-font-letter-spacing-heading-1` is unitless** (`-0.50`), so `letter-spacing: var(--wds-font-letter-spacing-heading-1)` is invalid CSS. WDS itself emits it with a fallback; if you need it, wrap it: `calc(var(--wds-font-letter-spacing-heading-1) * 1px)`.
32
+
33
+ **For a token not in the table, do not derive the name — look it up.** Grep the installed stylesheet, which is the only authority:
34
+
35
+ ```bash
36
+ grep -oE '\-\-wds-color-fill-[a-z0-9-]+' node_modules/@wix/design-system/themes/odeditor.global.css | sort -u
37
+ ```
38
+
39
+ Guessing from a Figma layer name invents tokens that do not exist (`-light` variants, for instance, are not a thing — the scale is `-primary`/`-secondary`/`-tertiary` with `-hover`/`-active`/`-disabled`), and `var()` on a missing name with no fallback makes the whole declaration invalid. You get no colour at all, and nothing in the build tells you.
40
+
41
+ **On a WDS component the prop is the target, not the token:**
42
+
43
+ ```tsx
44
+ // ❌ unchanged by a theme switch
45
+ <Button style={{ background: '#2F5DFF' }}>Save</Button>
46
+ <Badge style={{ background: '#F4B8B9' }}>Error</Badge>
47
+ <Text style={{ color: '#DF3336' }}>Invalid email</Text>
48
+ <Box style={{ background: '#F7F8FA', borderColor: '#DEDEDE' }}>
49
+
50
+ // ✅
51
+ <Button skin="standard">Save</Button>
52
+ <Badge skin="danger">Error</Badge>
53
+ <Text skin="error">Invalid email</Text>
54
+ <Box backgroundColor="D75" border="1px solid" borderColor="D60">
55
+ ```
56
+
57
+ A container that genuinely isn't a WDS component takes the tokens in its own CSS: `background: var(--wds-color-fill-standard-tertiary);`.
58
+
59
+ **Tokens are CSS custom properties**, so a colour copied into a JavaScript object — a chart palette, a canvas value — does not follow the theme.
60
+
61
+ **🛑 The theme rebases the spacing unit, from 6px to 4px.** `--wds-space-100` is `6px` under the default theme and `4px` under `odeditor`, and the `SP*` scale is defined against it (`SP2` is `calc(var(--wds-space-100) * 2)`). So the moment you import the theme stylesheet, `SP2` resolves to 8px rather than 12px, and numeric spacing (`<Box gap={2}>`) rebases with it. This is the one change that lands silently on every surface.
62
+
63
+ Keep expressing spacing in `SP*` or numeric units — **because** they follow the theme — and never convert them to the pixel values in [WDS_LAYOUT.md](dashboard-page/WDS_LAYOUT.md#base-unit)'s table, which are the 6px-base figures and are wrong on a themed surface. Use that table for the 12-column grid and layout rhythm, not as a px conversion chart.
64
+
65
+ No matching token? Ship it with a `// TODO: migrate when <token> exists` comment rather than bare. If you can't say in one sentence why it can't be a token, it should be one.
66
+
67
+ ## 2. Adjustments the wrapper doesn't cover
68
+
69
+ | Component | Adjustment | Prop |
70
+ | --- | --- | --- |
71
+ | Tabs | Small, no divider | `size="small" showDivider={false}` — `showDivider` defaults on, so pass it |
72
+ | Panel / modal headers | Smallest close/help button | `closeButtonProps={{ size: 'small' }}`, `helpButtonProps={{ size: 'small' }}` — `CloseButton` sizes are `small \| medium \| large` |
73
+ | Modal headers / footers | Dividers off | `showHeaderDivider={false} showFooterDivider={false}` — **both default to `'auto'`**, which shows them once content scrolls, so doing nothing ships the dividers the redesign removes |
74
+ | Slider | Horizontal spacing 12px, not 8px | Per call site |
75
+
76
+ Two rows from the design-side migration note have **no API to land on at 1.330.0**, so don't go looking: a modal footer's secondary slot is `secondaryButtonProps?: Omit<ButtonProps, …>` and renders a `Button`, so "secondary becomes a text button at M size" needs a hand-built footer rather than a prop (and `CustomModalLayout` has no footer-skin prop at all — the only `light` skin is `footnoteSkin`, which styles the footnote); and `AngleInput` exposes no `size`, so "medium / 38px" is not reachable. Raise those with **#wix-design-system** rather than improvising.
77
+
78
+ **Several adjustments the providers already make for you** — don't redo them by hand: a nested icon button is Dark / Tertiary from the wrapper's `IconButton` default, and `WixDesignSystemIconThemeProvider` already supplies the Accordion caret. `Accordion`, `CloseButton`, `Tooltip`, `Popover`, `Thumbnail`, `SidePanel` and ~20 more are all legal keys of `WixDesignSystemDefaultProps`, so anything you find yourself repeating per call site probably belongs in `BUSINESS_MANAGER_DEFAULTS` instead.
79
+
80
+ Two genuine author decisions remain: a **standalone** text button uses the standard (blue) skin while one beside a primary or secondary button uses Dark; and empty states are **typography only**, no legacy illustrations (on a collection page the empty state comes from the patterns shell — [DRAFT_TEMPLATE_COLLECTION.md](dashboard-page/DRAFT_TEMPLATE_COLLECTION.md)).
81
+
@@ -28,6 +28,47 @@ wix generate --params '{"extensionType":"DASHBOARD_MODAL","title":"<title>","fol
28
28
 
29
29
  The CLI generates the folder, the modal `.tsx`, the config file, the builder file, the UUID, and the `src/extensions.ts` registration. After scaffolding, implement the modal UI in the generated `.tsx`.
30
30
 
31
+ ## Theme
32
+
33
+ A modal opens as **its own iframe, separate from the page that opened it** — so theming the page does nothing for it. A themed page opening an unthemed modal is a common and very visible split: the dialog arrives in the pre-redesign look on top of a redesigned page.
34
+
35
+ Wrap the generated `<modal>.tsx` in the app's `BusinessManagerTheme`, at the root, above `CustomModalLayout`:
36
+
37
+ ```tsx
38
+ import type { FC } from 'react';
39
+ import { CustomModalLayout } from '@wix/design-system';
40
+ import { BusinessManagerTheme } from '../../BusinessManagerTheme';
41
+ import modalConfig from './<modal>.config';
42
+
43
+ const Modal: FC = () => (
44
+ <BusinessManagerTheme>
45
+ <CustomModalLayout
46
+ title={modalConfig.title}
47
+ showHeaderDivider={false}
48
+ showFooterDivider={false}
49
+ closeButtonProps={{ size: 'small' }}
50
+ /* … */
51
+ />
52
+ </BusinessManagerTheme>
53
+ );
54
+ ```
55
+
56
+ The wrapper file is written once per app and reused by every extension — [BUSINESS_MANAGER_THEME.md § 2](BUSINESS_MANAGER_THEME.md#2-the-wrapper--write-this-file-once-per-app). Icons come from `@wix/wix-ui-icons-common/lazy`, and anything you style yourself uses `--wds-*` tokens or a `skin`/`size` prop — [BUSINESS_MANAGER_TOKENS.md](BUSINESS_MANAGER_TOKENS.md).
57
+
58
+ **The redesign changes modal chrome specifically**, and the wrapper cannot make these for you:
59
+
60
+ | Part | Redesign | How |
61
+ | --- | --- | --- |
62
+ | Header / footer dividers | Removed | `showHeaderDivider={false} showFooterDivider={false}`. **Both default to `'auto'`**, which shows them once content scrolls — so doing nothing ships the dividers the redesign removes |
63
+ | Close / help button | Smallest size | `closeButtonProps={{ size: 'small' }}`, `helpButtonProps={{ size: 'small' }}` — `CloseButton` sizes are `small \| medium \| large` |
64
+ | Destructive confirm | Token, not a red literal | `skin="destructive"` on the confirm `Button` |
65
+
66
+ A confirm dialog's footer is a primary `Button` plus a cancel, and because the cancel sits beside a primary it takes the **Dark** skin rather than the wrapper's `standard` default.
67
+
68
+ **One thing the design note asks for that has no API at 1.330.0:** "the footer's secondary action is a `TextButton` at M size". `CustomModalLayout`'s slot is `secondaryButtonProps?: Omit<ButtonProps, …>` and renders a `Button`; there is no footer-skin prop either (the only `light` skin is `footnoteSkin`, which styles the footnote). Achieving it means hand-building the footer — so take it to **#wix-design-system** rather than improvising, and if you do hand-build it, the cancel needs both `skin="dark"` and `size="medium"` against the wrapper's `TextButton` default of `small`.
69
+
70
+ **Nothing renders a modal until something opens it**, so an unthemed dialog survives more than the usual checks: it is invisible to `tsc` and `wix build`, and also to a careful look at the page in `wix preview`, because it isn't on screen yet. Trigger the dialog before calling it done — that is the only step that shows it.
71
+
31
72
  ## Quick Reference
32
73
 
33
74
  | Task | Method | Example |
@@ -14,6 +14,8 @@ Do this first because a bare filtered table answers "what are all the records" a
14
14
 
15
15
  The order, what each library owns, and how to look a name up are stated once: [SKILL.md → Component Selection Order](../SKILL.md#component-selection-order).
16
16
 
17
+ **Theme:** the page's iframe inherits none of the Business Manager redesign. Wrap the entry file in the app's `BusinessManagerTheme`, import icons from `@wix/wix-ui-icons-common/lazy`, and style with `--wds-*` tokens or `skin`/`size` props — [BUSINESS_MANAGER_THEME.md](BUSINESS_MANAGER_THEME.md), [BUSINESS_MANAGER_TOKENS.md](BUSINESS_MANAGER_TOKENS.md).
18
+
17
19
  ## Scaffold
18
20
 
19
21
  Use `wix generate --params` with all required fields:
@@ -29,13 +29,28 @@ For the complete list of available slot IDs, see [Slots Reference](dashboard-plu
29
29
  - **Wix Dashboard SDK** (`@wix/dashboard`) — Interact with the dashboard page's data passed to the slot
30
30
  - **Wix Design System** (`@wix/design-system`) — Native-looking React components matching Wix's own dashboard UI
31
31
 
32
+ ## Theme
33
+
34
+ A plugin is its own iframe, so **it inherits nothing from the host page it sits in** — not even though that page is a redesigned first-party Wix app. This makes a plugin the least forgiving dashboard surface: an unthemed one renders classic icons and pre-redesign buttons directly beside the redesigned Stores/Bookings/Blog UI framing it.
35
+
36
+ Wrap the plugin component in the app's `BusinessManagerTheme` (the example below does), import icons from `@wix/wix-ui-icons-common/lazy`, and style with `--wds-*` tokens or `skin`/`size` props — never a hardcoded colour or an inline `style` override ([BUSINESS_MANAGER_TOKENS.md](BUSINESS_MANAGER_TOKENS.md)). The wrapper file itself is written once per app: [BUSINESS_MANAGER_THEME.md § 2](BUSINESS_MANAGER_THEME.md#2-the-wrapper--write-this-file-once-per-app).
37
+
38
+ Two things to get right in a slot specifically:
39
+
40
+ - **Match the host's density, don't fight it.** The wrapper's defaults (`Button` small/dark, `IconButton` small/dark/tertiary) are what the surrounding page uses. Overriding them per call site is how a plugin starts looking like a different product.
41
+ - **A nested icon button inside your own card or list row is Dark / Tertiary.** The wrapper's `IconButton` default already gives you this — don't re-specify `skin="standard"` on it.
42
+
43
+ A plugin has no page of its own, so looking at it means navigating to the host app's page that carries the slot — the Blog posts or Bookings staff screen itself.
44
+
32
45
  ## Interacting with Dashboard Data
33
46
 
34
47
  Use `observeState()` from the Dashboard SDK to receive data from the host dashboard page:
35
48
 
36
- ```typescript
49
+ ```tsx
37
50
  import { dashboard } from "@wix/dashboard";
38
- import { useEffect, useState } from "react";
51
+ import { useEffect, useState, type FC } from "react";
52
+ import { Card, Text } from "@wix/design-system";
53
+ import { BusinessManagerTheme } from "../../BusinessManagerTheme";
39
54
 
40
55
  const Plugin: FC = () => {
41
56
  const [params, setParams] = useState<Record<string, unknown>>({});
@@ -47,13 +62,13 @@ const Plugin: FC = () => {
47
62
  }, []);
48
63
 
49
64
  return (
50
- <WixDesignSystemProvider features={{ newColorsBranding: true }}>
65
+ <BusinessManagerTheme>
51
66
  <Card>
52
67
  <Card.Content size="medium">
53
68
  <Text>Received data: {JSON.stringify(params)}</Text>
54
69
  </Card.Content>
55
70
  </Card>
56
- </WixDesignSystemProvider>
71
+ </BusinessManagerTheme>
57
72
  );
58
73
  };
59
74
  ```
@@ -59,21 +59,22 @@ Case C has one page and no rows to open, so it needs no router and no manual `lo
59
59
  import type { FC } from 'react';
60
60
  import { withDashboard } from '@wix/patterns';
61
61
  import { WixPatternsProvider } from '@wix/patterns/provider';
62
- import { WixDesignSystemProvider } from '@wix/design-system';
63
- import '@wix/design-system/styles.global.css';
62
+ import { BusinessManagerTheme } from '../../BusinessManagerTheme'; // BUSINESS_MANAGER_THEME.md § 2
64
63
  import { {Feature}SettingsPage } from './{Feature}SettingsPage'; // DRAFT_TEMPLATE_SETTINGS.md
65
64
 
66
65
  const Page: FC = () => (
67
- <WixDesignSystemProvider>
66
+ <BusinessManagerTheme>
68
67
  <WixPatternsProvider>
69
68
  <{Feature}SettingsPage />
70
69
  </WixPatternsProvider>
71
- </WixDesignSystemProvider>
70
+ </BusinessManagerTheme>
72
71
  );
73
72
 
74
73
  export default withDashboard(Page);
75
74
  ```
76
75
 
76
+ `BusinessManagerTheme` is the app's own wrapper around the design-system providers, the `odeditor` theme stylesheet and the Business Manager default props — [BUSINESS_MANAGER_THEME.md § 2](../BUSINESS_MANAGER_THEME.md#2-the-wrapper--write-this-file-once-per-app) has the file to write once per app. **Business Manager passes none of the redesign through the extension's iframe**, so a bare `WixDesignSystemProvider` here renders the pre-redesign look while `tsc`, `wix build` and `wix preview` all pass. `WixPatternsProvider` nests inside it, never above.
77
+
77
78
  Cases A, B and D differ — they need `location` supplied manually for `PatternsReactRouter`. See [DRAFT_TEMPLATE_ROUTER.md](DRAFT_TEMPLATE_ROUTER.md) rather than adding that plumbing here; it's dead code without a router underneath it.
78
79
 
79
80
  ## 2. Collection page — Case A, B, D
@@ -1,19 +1,18 @@
1
1
  # Draft Template — Cases A, B and D (router-wired)
2
2
 
3
- **Applies to [DRAFT_TEMPLATE.md](DRAFT_TEMPLATE.md)'s Cases A, B and D.** All three need `PatternsReactRouter`, because in all three a row opens a page of its own — a panel is not the drill-in ([UX_SUCCESS_MODEL.md](UX_SUCCESS_MODEL.md)). Case A's detail route is read-only (§4); B and D route to a full `EntityPage`. The collection and settings components live in [DRAFT_TEMPLATE.md](DRAFT_TEMPLATE.md); this file covers only what a router adds — the entry file, the app shell, and the detail/entity page.
3
+ **Applies to [DRAFT_TEMPLATE.md](DRAFT_TEMPLATE.md)'s Cases A, B and D.** All three need `PatternsReactRouter`, because in all three a row opens a page of its own — a panel is not the drill-in ([UX_SUCCESS_MODEL.md](UX_SUCCESS_MODEL.md)). Case A's detail route is read-only (§4); B and D route to a full `EntityPage`. This file covers only what a router adds.
4
4
 
5
5
  Every snippet below is copied from the installed `dist/docs/*.md` this session read, not from memory.
6
6
 
7
7
  ## 1. Entry — `location` is manual in a Wix CLI app, and only because the router needs it
8
8
 
9
- `PatternsReactRouter` reads the page location through `container.usePageLocation()`, which only `withDashboard`'s `location` prop feeds — nothing supplies it automatically in a Wix CLI app the way Yoshi BM flow does:
9
+ `PatternsReactRouter` reads the page location through `container.usePageLocation()`, which only `withDashboard`'s `location` prop feeds — nothing supplies it automatically in a Wix CLI app:
10
10
 
11
11
  ```tsx
12
12
  // {feature}.tsx — Case A, B or D
13
13
  import { useEffect, useState, type FC } from 'react';
14
14
  import { dashboard } from '@wix/dashboard';
15
- import { WixDesignSystemProvider } from '@wix/design-system';
16
- import '@wix/design-system/styles.global.css';
15
+ import { BusinessManagerTheme } from '../../BusinessManagerTheme';
17
16
  import { {Feature}App } from './{Feature}App';
18
17
 
19
18
  type PageLocation = Parameters<Parameters<typeof dashboard.observeState>[0]>[1]['pageLocation'];
@@ -29,16 +28,18 @@ const Page: FC = () => {
29
28
  }, []);
30
29
 
31
30
  return (
32
- <WixDesignSystemProvider>
31
+ <BusinessManagerTheme>
33
32
  {location ? <{Feature}App location={location} /> : null}
34
- </WixDesignSystemProvider>
33
+ </BusinessManagerTheme>
35
34
  );
36
35
  };
37
36
 
38
37
  export default Page;
39
38
  ```
40
39
 
41
- **Skipping this is a runtime-only failure.** Per `PatternsReactRouter`'s own docs: "Nothing catches this before runtime — type checking and bundling both pass, because neither renders the page." `tsc` and `wix build` will not catch a missing `location` — only opening the page in a browser will. This is exactly why [Step 5's Preview](../../SKILL.md#validation) is not optional for Case B/D.
40
+ `BusinessManagerTheme` belongs here, not in `{Feature}App.tsx` — its default props must apply above `WixPatternsProvider`. Write it once per app: [BUSINESS_MANAGER_THEME.md](../BUSINESS_MANAGER_THEME.md#2-the-wrapper--write-this-file-once-per-app).
41
+
42
+ **Skipping either the theme or `location` is a runtime-only failure.** Per `PatternsReactRouter`'s own docs: "Nothing catches this before runtime — type checking and bundling both pass, because neither renders the page." Only a browser catches a missing `location` or an unthemed page, which is why [Step 5's Preview](../../SKILL.md#validation) is not optional.
42
43
 
43
44
  ## 2. App shell — provider, router, routes
44
45
 
@@ -136,49 +136,35 @@ This dashboard page manages dynamic parameters for an embedded script. The param
136
136
  - Display the preview alongside the settings form using Layout and Cell components
137
137
  - The preview should react to parameter changes in real-time
138
138
 
139
- ## Example Implementation
139
+ ## Files to Generate
140
140
 
141
- See the generated site-popup example for a complete reference implementation:
142
- - src/extensions/dashboard/withProviders.tsx - Provider wrapper with WDS
143
- - src/extensions/dashboard/pages/page.tsx - Dashboard page with parameter management (wrapped with withProviders)
144
- - src/extensions/dashboard/components/site-popup-settings.tsx - Settings form component
145
- - src/extensions/dashboard/types.ts - Type definitions
141
+ When dynamic parameters are present, generate all of these — the two wrapper files are not optional:
146
142
 
147
- Key implementation patterns from the example:
148
- 1. withProviders.tsx wraps the component with WixDesignSystemProvider
149
- 2. page.tsx exports the component wrapped: export default withProviders(MyComponent)
150
- 3. Parameters are saved as individual string fields, not as JSON
151
- 4. Parameters are loaded with proper type conversion (string to boolean, string to number, etc.)
152
- 5. Use embeddedScripts directly from '@wix/app-management'
143
+ | File | Role |
144
+ | --- | --- |
145
+ | `dashboard/BusinessManagerTheme.tsx` | Theme wrapper — [BUSINESS_MANAGER_THEME.md § 2](../BUSINESS_MANAGER_THEME.md#2-the-wrapper--write-this-file-once-per-app) |
146
+ | `dashboard/withProviders.tsx` | Provider wrapper (below) |
147
+ | `dashboard/pages/page.tsx` | The page, exported wrapped in `withProviders` |
148
+ | `dashboard/types.ts` | Parameter type definitions |
149
+ | Component files | Settings forms, previews |
153
150
 
154
- ## File Generation Requirements
155
-
156
- When dynamic parameters are present, you MUST generate these files:
157
- 1. src/extensions/dashboard/withProviders.tsx - Provider wrapper (REQUIRED for WDS)
158
- 2. src/extensions/dashboard/pages/page.tsx - The main dashboard page component
159
- 3. src/extensions/dashboard/types.ts - Type definitions for the parameters (if needed)
160
- 4. Any additional component files (settings forms, previews, etc.)
161
-
162
- The withProviders.tsx is NOT optional - it must always be generated when there are dynamic parameters.
151
+ Parameters are saved as individual string fields, never as one JSON string, and converted back to their real types on load. Use `embeddedScripts` directly from `@wix/app-management`.
163
152
 
164
153
  ## Provider Wrapper Implementation
165
154
 
166
- You MUST generate the following file: src/extensions/dashboard/withProviders.tsx
167
-
168
- This file is REQUIRED to wrap dashboard components with the Wix Design System provider.
155
+ Generate `src/extensions/dashboard/withProviders.tsx`:
169
156
 
170
157
  ```typescript
171
158
  import React from 'react';
172
- import { WixDesignSystemProvider } from '@wix/design-system';
173
159
  import { i18n } from '@wix/essentials';
160
+ import { BusinessManagerTheme } from './BusinessManagerTheme';
174
161
 
175
162
  export default function withProviders<P extends {} = {}>(Component: React.FC<P>) {
176
163
  return function DashboardProviders(props: P) {
177
- const locale = i18n.getLocale();
178
164
  return (
179
- <WixDesignSystemProvider locale={locale} features={{ newColorsBranding: true }}>
165
+ <BusinessManagerTheme locale={i18n.getLocale()}>
180
166
  <Component {...props} />
181
- </WixDesignSystemProvider>
167
+ </BusinessManagerTheme>
182
168
  );
183
169
  };
184
170
  }
@@ -187,16 +173,16 @@ export default function withProviders<P extends {} = {}>(Component: React.FC<P>)
187
173
  export { withProviders };
188
174
  ```
189
175
 
190
- This file must be included in your generated files output.
176
+ Business Manager passes none of the redesign through the extension's iframe, so a wrapper holding `WixDesignSystemProvider` alone renders the pre-redesign look while compiling and previewing cleanly. `features={{ newColorsBranding: true }}` predates the theme and does not substitute for it.
191
177
 
192
178
  ## Using Provider Wrapper
193
179
 
194
180
  In your dashboard page component (page.tsx):
195
- 1. Import the withProviders wrapper: `import withProviders from '../../withProviders';`
181
+ 1. `import withProviders from '../../withProviders';`
196
182
  2. Import embeddedScripts from '@wix/app-management'
197
- 3. DO NOT wrap your component with WixDesignSystemProvider - the provider wrapper does this
198
- 4. Export the component wrapped with withProviders: `export default withProviders(MyComponent);`
199
- 5. Your component should only contain the Page component and its content, not providers
183
+ 3. Add no design-system providers in the page — `withProviders` owns them
184
+ 4. Export wrapped: `export default withProviders(MyComponent);`
185
+ 5. The component holds the Page and its content, not providers
200
186
 
201
187
  Example structure:
202
188
  ```typescript
@@ -204,8 +190,7 @@ import { useEffect, useState, type FC } from 'react';
204
190
  import { dashboard } from '@wix/dashboard';
205
191
  import { embeddedScripts } from '@wix/app-management';
206
192
  import { Page, Card, Button, ... } from '@wix/design-system';
207
- import '@wix/design-system/styles.global.css';
208
- import withProviders from '../../withProviders';
193
+ import withProviders from '../../withProviders'; // owns the stylesheets and providers
209
194
 
210
195
  const MyDashboardPage: FC = () => {
211
196
  const [options, setOptions] = useState<MyScriptOptions>(defaultOptions);
@@ -253,9 +238,7 @@ export default withProviders(MyDashboardPage);
253
238
  ## Critical Notes
254
239
 
255
240
  - Only implement UI for parameters that are relevant to your specific use case - ignore parameters that don't apply
256
- - ALWAYS generate withProviders.tsx when there are dynamic parameters
257
- - ALWAYS wrap the dashboard page export with withProviders()
258
- - DO NOT use WixDesignSystemProvider directly in the dashboard page component - use withProviders instead
241
+ - ALWAYS generate `BusinessManagerTheme.tsx` and `withProviders.tsx`, and wrap the page export with `withProviders()` — no design-system providers in the page itself
259
242
  - ALWAYS use embeddedScripts directly from '@wix/app-management'
260
243
  - ALWAYS convert parameter values to strings when saving (embeddedScripts.embedScript must receive all string values in the parameters object)
261
244
  - ALWAYS convert string parameters back to proper types when loading (e.g., 'true' -> true for booleans, string to number for numbers)
@@ -9,7 +9,6 @@ allowed-tools:
9
9
  - Bash(npm install *)
10
10
  - Bash(npm run *)
11
11
  - Bash(node *)
12
- - Bash(bash *)
13
12
  - Bash(cd *)
14
13
  - Bash(ls *)
15
14
  - Bash(mkdir *)
@@ -67,7 +67,7 @@ The verticals the skill operates end-to-end today: **stores · blog · cms · fo
67
67
 
68
68
  ### bookings — appointments and classes
69
69
  - **Intent:** book / appointment / schedule / class / session / reserve a slot — a **service or appointment with a provider** (a stylist, trainer, tutor, clinic, studio).
70
- - **Not bookings — route to `restaurants` instead:** a **table at a restaurant** is a Table Reservations concern, not a bookable service; and a **special dining occasion guests reserve** — a wine tasting, cheese pairing, chef's table, or tasting-menu evening at a restaurant — is a **restaurants → Table Reservations *experience*** (see the restaurants entry), **not** a bookings service. Reach for `bookings` only when what's booked is a standalone service/class with a provider, never a seat at a restaurant.
70
+ - **Not bookings — route to `restaurants` instead:** a **table at a restaurant** is a Table Reservations concern, not a bookable service; and a **special dining occasion guests reserve** — a chef's table, cheese pairing, or tasting-menu evening at a restaurant — is a **restaurants → Table Reservations *experience*** (see the restaurants entry), **not** a bookings service. Reach for `bookings` only when what's booked is a standalone service/class with a provider, never a seat at a restaurant.
71
71
  - **Not bookings — route to `rentals` instead:** when the **customer chooses how long** they want something, and what's booked is a **thing rather than a person** — a room by the hour, a desk for three days, a van for the weekend. The tell is a duration *range* the customer picks within. A 60-minute haircut is `bookings`; a meeting room booked for 1–8 hours is `rentals`.
72
72
  - **Required site features:** a list of services; a page per service; a way to pick a time and book it.
73
73
  - **Implementation checklist:** show each service's name, duration, and price; show the staff or provider; show the available time slots; a book action; a confirmation after booking.
@@ -85,8 +85,8 @@ The verticals the skill operates end-to-end today: **stores · blog · cms · fo
85
85
  - **Implementation checklist:** show each plan's name, price, and billing cycle; list what each plan includes (the perks); a clear "choose plan" action; highlight a recommended tier where it makes sense.
86
86
 
87
87
  ### restaurants — menus and food
88
- - **Intent:** menu / restaurant / cafe / food / dish list / order food / dine-in / **reserve a table** / a **special dining occasion guests reserve** (wine tasting, cheese pairing, chef's table, tasting-menu evening).
89
- - **Required site features:** a menu organized into sections; each item with a name, description, and price. **Add-ons, each on demand (separate apps/features; see `SETUP.md`):** online ordering, table reservations, and — **when the brief names special dining occasions** — **experiences** (a reservation that *is* a curated occasion at the restaurant, e.g. a wine-and-cheese pairing), which ride on the Table Reservations app.
88
+ - **Intent:** menu / restaurant / cafe / food / dish list / order food / dine-in / **reserve a table** / a **special dining occasion guests reserve** (chef's table, cheese pairing, tasting-menu evening).
89
+ - **Required site features:** a menu organized into sections; each item with a name, description, and price. **Add-ons, each on demand (separate apps/features; see `SETUP.md`):** online ordering, table reservations, and — **when the brief names special dining occasions** — **experiences** (a reservation that *is* a curated occasion at the restaurant, e.g. a chef's table), which ride on the Table Reservations app.
90
90
  - **Experiences vs bookings — decide here:** an **experience** is a **reservation that is itself a special dining occasion at the restaurant** — it books seats at the restaurant's own location and carries its own name, per-guest price, schedule, and booking form. Use it for pairing sessions, tastings, and chef's tables. Use the separate **`bookings`** vertical only for a **service/appointment/class with a provider** that isn't a seat at the restaurant. For anything a restaurant hosts and seats, prefer an experience.
91
91
  - **Implementation checklist:** show the menu grouped into sections in order; each item's name, description, price, and labels (vegan, spicy…) and modifiers / variants where they exist; an order action if online ordering is wired; a reserve-a-table action if reservations are wired; **if experiences are wired, list each experience with its name, description, per-guest price, and schedule, and a reserve-seats action.**
92
92
 
@@ -52,7 +52,7 @@ For each capability, build its `intent.<cap>` block — the inputs the seed step
52
52
  | bookings | `{ serviceCount, servicesNamed: [] }` | `serviceCount: 2`, brand-derived service names |
53
53
  | rentals | `{ unitType, serviceCount, resourceCount, servicesNamed: [] }` | `unitType: "HOUR"` (`"DAY"` if the brief rents by the day), `serviceCount: 2`, `resourceCount: 2`, brand-derived item names |
54
54
  | pricing-plans | `{ planCount, tiersNamed: [] }` | `planCount: 2` (e.g. Basic / Pro), monthly billing |
55
- | restaurants | `{ menuName, sections: [{ name, itemCount }], ordering?, reservations?, experiences?: [{ name }] }` | one menu, 2 sections, `itemCount: 3` each; add-ons only when the brief names them. **`experiences[]`** = special dining occasions guests reserve (wine/cheese pairing, chef's table) — a restaurant *reservation that is an experience*, **not** the `bookings` vertical (see `CAPABILITIES.md`). |
55
+ | restaurants | `{ menuName, sections: [{ name, itemCount }], ordering?, reservations?, experiences?: [{ name }] }` | one menu, 2 sections, `itemCount: 3` each; add-ons only when the brief names them. **`experiences[]`** = special dining occasions guests reserve (chef's table, tasting menu) — a restaurant *reservation that is an experience*, **not** the `bookings` vertical (see `CAPABILITIES.md`). |
56
56
  | portfolio | `{ collections: [{ name }], projectCount }` | one brand-derived collection, `projectCount: 3` |
57
57
 
58
58
  Counts are deliberately small (the seed shows the shape, not a full catalog).
@@ -48,7 +48,7 @@ Before implementing a capability, Read the local recipe linked in its row.
48
48
  | restaurants — online ordering (add-on; only when the Orders app is in the run) | add `@wix/ecom` + `@wix/redirects` to the row above | `how-to-code-restaurant-orders.md` — ordering cart/checkout on top of the menu display. |
49
49
  | portfolio | `@wix/portfolio` (+ `media` from `@wix/sdk` to resolve image strings; **no** `@wix/ecom`/`@wix/redirects` — display-only) | `how-to-code-portfolio.md` — Portfolio v1 display-only read. |
50
50
  | restaurants — table reservations (add-on; only when the Table Reservations app is in the run) | `@wix/table-reservations` (a **distinct** package from `@wix/restaurants`; **no ecom/redirects** — a reservation is a hold, not a purchase) | `how-to-code-restaurant-reservations.md` — book-a-table hold→reserve. |
51
- | restaurants — experiences (add-on; special dining occasions guests reserve — wine/cheese pairing, chef's table) | `@wix/table-reservations` (same package; the **`experiences`** namespace + `timeSlots`/`reservations`) | `how-to-code-restaurant-reservations.md` — "Booking an experience" (query experiences → scheduled slots → reserve with `experienceId`). |
51
+ | restaurants — experiences (add-on; special dining occasions guests reserve — chef's table, tasting menu) | `@wix/table-reservations` (same package; the **`experiences`** namespace + `timeSlots`/`reservations`) | `how-to-code-restaurant-reservations.md` — "Booking an experience" (query experiences → scheduled slots → reserve with `experienceId`). |
52
52
 
53
53
  > **Cross-cutting packages** (`CAPABILITIES.md` § "Cross-cutting capabilities"): these aren't per-vertical rows but get added to the package list when the run used them. If **coupons** were seeded, add `@wix/marketing`. The eCommerce checkout packages (`@wix/ecom`, `@wix/redirects`) are already folded into the stores row above — include them once when any purchase-flow vertical is present.
54
54