@wix/agent-skills 1.9.0 → 1.11.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 (47) hide show
  1. package/package.json +4 -1
  2. package/skills/wix-headless/references/DESIGN_SYSTEM.md +6 -16
  3. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +1 -1
  4. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +19 -0
  5. package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +2 -2
  6. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +3 -3
  7. package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +2 -2
  8. package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +3 -3
  9. package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +2 -2
  10. package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +7 -7
  11. package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +4 -4
  12. package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +2 -2
  13. package/skills/wix-headless/references/astro/templates/Footer.astro +4 -4
  14. package/skills/wix-headless/references/astro/templates/Navigation.astro +4 -4
  15. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +147 -6
  16. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +21 -4
  17. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +11 -2
  18. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +8 -8
  19. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +94 -26
  20. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +53 -10
  21. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +128 -20
  22. package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +3 -3
  23. package/skills/wix-headless/references/astro/templates/ecom/cart.astro +3 -3
  24. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +17 -17
  25. package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +3 -3
  26. package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +4 -4
  27. package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +19 -18
  28. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +3 -3
  29. package/skills/wix-headless/references/astro/templates/global.css +17 -15
  30. package/skills/wix-headless/references/astro/templates/index.astro +4 -4
  31. package/skills/wix-headless/references/astro/templates/stores/components-stores.css +31 -31
  32. package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +4 -4
  33. package/skills/wix-headless/references/bookings/FLOW.md +93 -32
  34. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +8 -3
  35. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +60 -0
  36. package/skills/wix-headless/references/custom/bookings/WIRING.md +60 -9
  37. package/skills/wix-headless/references/shared/DESIGN_MD.md +2 -3
  38. package/skills/wix-headless/references/shared/IMPLEMENTER.md +4 -4
  39. package/skills/wix-headless/references/shared/STYLING.md +15 -18
  40. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +2 -2
  41. package/skills/wix-headless/references/verticals/bookings.md +5 -3
  42. package/skills/wix-headless/scripts/compose.mjs +4 -19
  43. package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -3
  44. package/skills/wix-manage/references/bookings/create-appointment-service.md +3 -28
  45. package/skills/wix-manage/references/bookings/create-booking-service-from-prompt.md +1 -8
  46. package/skills/wix-manage/references/bookings/create-class-service.md +3 -28
  47. package/skills/wix-manage/references/bookings/create-course-service.md +3 -28
@@ -32,16 +32,17 @@ Client-side `@wix/sdk` — CDN imports for `none`-build, bundled for `own`-build
32
32
  ## The client (acquire once)
33
33
  ```js
34
34
  import { createClient, OAuthStrategy } from "https://esm.sh/@wix/sdk@1"; // bundled for own-build
35
- import { services, availabilityTimeSlots, eventTimeSlots, bookings } from "https://esm.sh/@wix/bookings@1";
35
+ import { services, availabilityTimeSlots, eventTimeSlots, bookings, categoriesV2 } from "https://esm.sh/@wix/bookings@1";
36
36
  import { forms } from "https://esm.sh/@wix/forms@1";
37
37
  import * as cartV2 from "https://esm.sh/@wix/auto_sdk_ecom_cart-v-2@1";
38
38
  import { redirects } from "https://esm.sh/@wix/redirects@1";
39
39
 
40
40
  const wix = createClient({
41
- modules: { services, availabilityTimeSlots, eventTimeSlots, bookings, forms, redirects, ...cartV2 },
41
+ modules: { services, availabilityTimeSlots, eventTimeSlots, bookings, categoriesV2, forms, redirects, ...cartV2 },
42
42
  auth: OAuthStrategy({ clientId: "REPLACE_WITH_APP_ID" }),
43
43
  });
44
44
  ```
45
+ (`categoriesV2` + `services.queryLocations` power the optional catalog filters; drop them if you don't surface filters.)
45
46
 
46
47
  ## Render services
47
48
  ```js
@@ -54,21 +55,68 @@ const { items } = await wix.services.queryServices({
54
55
  const visible = items.filter((s) => !s.hidden);
55
56
  // name s.name · tagline s.tagLine · slug s.mainSlug?.name ·
56
57
  // duration s.schedule?.availabilityConstraints?.sessionDurations?.[0] ·
57
- // price s.payment?.fixed?.price ({ value, currency } — value is a string).
58
+ // price s.payment?.fixed?.price ({ value, currency } — value is a string) ·
59
+ // staff s.staffMemberDetails?.staffMembers ([{ staffMemberId, name }] — staffMemberId IS the resource id).
60
+ ```
61
+
62
+ ## Optional catalog filters — location & category
63
+ Both auto-skip when there's nothing to choose (see `../../bookings/FLOW.md` §7).
64
+ Merge the chosen filter into the **same** `queryServices` filter and re-query.
65
+ ```js
66
+ // Locations — show the selector only when count > 1.
67
+ const loc = await wix.services.queryLocations();
68
+ const businessLocations = loc.businessLocations?.locations ?? []; // [{ _id, type, business: { name } }]
69
+ const count = businessLocations.length + (loc.customLocations?.exists ? 1 : 0) + (loc.customerLocations?.exists ? 1 : 0);
70
+ // Categories — non-fatal; show the bar only when > 1.
71
+ const cats = (await wix.categoriesV2.queryCategories().find()).items ?? []; // [{ _id, name }]
72
+
73
+ // Merge into the services filter:
74
+ const filter = { appId: BOOKING_APP_ID };
75
+ if (categoryId) filter["category.id"] = { $eq: categoryId };
76
+ if (locationId === "custom") filter["locations.type"] = { $hasSome: ["CUSTOM"] };
77
+ else if (locationId === "customer") filter["locations.type"] = { $hasSome: ["CUSTOMER"] };
78
+ else if (locationId) filter["locations.business.id"] = { $hasSome: [locationId] };
79
+ // → wix.services.queryServices({ query: { filter, paging: { limit: 100 } }, conditionalFields: ["STAFF_MEMBER_DETAILS"] }).find()
80
+ // Carry locationId/locationType into the availability call so slots are scoped to it.
58
81
  ```
59
82
 
60
83
  ## Availability (week calendar)
61
84
  Render a **week calendar** (day strip → the day's times), not a flat grid — see
62
85
  `../../bookings/FLOW.md` § 5. `fromLocalDate`/`toLocalDate` are **local** strings
63
86
  (`YYYY-MM-DDThh:mm:ss`, no `Z`) + a `timeZone`.
87
+
88
+ > **Multi-location: scope to ONE business location.** Unscoped,
89
+ > `listAvailabilityTimeSlots` returns **one slot per location** per time → duplicate
90
+ > rows. Source the location list from **`queryLocations()`** (the site's real business
91
+ > locations, whose ids the availability engine recognizes) intersected with the
92
+ > service's own location ids — NOT from `service.locations` alone (its entries can
93
+ > carry an id the engine doesn't recognize → scoping returns 0 slots). Default to the
94
+ > carried/first and pass the single-location filter below; with no business locations,
95
+ > leave it unscoped. (Staff does NOT multiply rows — only location does.) See FLOW.md §7.
64
96
  ```js
65
- // APPOINTMENT — serviceId is a single GUID STRING:
66
- const a = await wix.availabilityTimeSlots.listAvailabilityTimeSlots({ serviceId, fromLocalDate, toLocalDate, timeZone, bookable: true, cursorPaging: { limit: 100 } });
97
+ // APPOINTMENT — serviceId is a single GUID STRING. Staff (§8) OPTIONAL; location ALWAYS when >1:
98
+ const a = await wix.availabilityTimeSlots.listAvailabilityTimeSlots({
99
+ serviceId, fromLocalDate, toLocalDate, timeZone, bookable: true, cursorPaging: { limit: 100 },
100
+ // staff: resourceTypes: [{ resourceTypeId: STAFF_MEMBER_RESOURCE_TYPE_ID, resourceIds: [resourceId] }], includeResourceTypeIds: [STAFF_MEMBER_RESOURCE_TYPE_ID],
101
+ // location: locations: [{ _id: locationId, locationType: "BUSINESS" }],
102
+ });
67
103
  // slots a.timeSlots[] — localStartDate/localEndDate/scheduleId at the TOP level.
68
- // CLASS — different namespace, PLURAL serviceIds; slots carry eventInfo.eventId, no scheduleId:
69
- const c = await wix.eventTimeSlots.listEventTimeSlots({ serviceIds: [serviceId], fromLocalDate, toLocalDate, timeZone, includeNonBookable: false });
104
+ // CLASS — different namespace, PLURAL serviceIds; slots carry eventInfo.eventId, no scheduleId.
105
+ // CLASS filters staff + location via eventFilter:
106
+ const c = await wix.eventTimeSlots.listEventTimeSlots({
107
+ serviceIds: [serviceId], fromLocalDate, toLocalDate, timeZone, includeNonBookable: false,
108
+ // eventFilter: { "resources.id": { $hasSome: [resourceId] }, "location.id": [locationId] },
109
+ });
70
110
  ```
71
111
 
112
+ ## Optional staff selection
113
+ The staff list is on the service (`s.staffMemberDetails.staffMembers` → `[{ staffMemberId, name }]`;
114
+ `staffMemberId` IS the resource id despite the name). Show a picker only when >1 staff.
115
+ Filtering uses that `staffMemberId` (the `resourceId`/`resourceIds` above).
116
+ When a specific staff is chosen, set `slot.resource = { _id: staffMemberId, name }` on the
117
+ slot you pass to `createBooking` (the booking books that resource); leave it unset for
118
+ "any staff" → the **ANY_RESOURCE fallback** already in the booking snippet below.
119
+
72
120
  ## Booking form — schema-driven
73
121
  The booking form is a `@wix/forms` form on the service (`service.form._id`). Read
74
122
  its schema and render fields by `componentType`, collecting values keyed by
@@ -95,6 +143,8 @@ const STAFF_MEMBER_RESOURCE_TYPE_ID = "1cd44cf8-756f-41c3-bd90-3e2ffcaf1155";
95
143
 
96
144
  // Build the slot. APPOINTMENT carries scheduleId; CLASS carries eventId (Wix
97
145
  // derives the rest). No staff chosen → the ANY_RESOURCE fallback.
146
+ // When a specific staff was chosen, use `resource: { _id: resourceId, name }`
147
+ // INSTEAD of `resourceSelections` (drop the ANY_RESOURCE fallback for that slot).
98
148
  const slot =
99
149
  slotType === "CLASS"
100
150
  ? { serviceId, eventId, timezone }
@@ -140,7 +190,8 @@ if (checkoutRequired) {
140
190
  > Confirm the `@wix/auto_sdk_ecom_cart-v-2` function registration shape on a
141
191
  > CDN/own client at wiring time; the payloads above match the astro `bookingDriver.ts`.
142
192
 
143
- ## Out of v1
144
- Waitlist and on-site manage/cancel — out of scope (same as the astro vertical).
193
+ ## Out of scope
194
+ Waitlist and on-site manage/cancel — out of scope (same as the astro vertical;
195
+ neither has a headless SoT — display-only policy flags only, no join/cancel logic).
145
196
  Show bookable slots only; post-booking self-service is handled by the Wix-hosted
146
197
  flow / member area.
@@ -21,8 +21,6 @@ typography:
21
21
  fontWeight: <number> # optional
22
22
  lineHeight: <Dimension|number> # optional
23
23
  letterSpacing: <Dimension> # optional
24
- spacing:
25
- <scale-level>: <Dimension|number>
26
24
  rounded: # corner radii (DESIGN.md's name for radius tokens)
27
25
  <scale-level>: <Dimension>
28
26
  containers: # EXTENSION (this skill): content/reading widths
@@ -51,11 +49,12 @@ googleFontsHref: <string> # EXTENSION (this skill): the ready Google Fonts <li
51
49
  |---|---|---|
52
50
  | `colors` | `--color-<key>` | semantic role keys (see color roles below) |
53
51
  | `typography.<level>.fontFamily` | `--font-<level>` | `display` + `body` required; `mono` optional |
54
- | `spacing` | `--spacing-<key>` | full `2xs…4xl` rhythm scale |
55
52
  | `rounded` | `--radius-<key>` | `sm` + `md` required |
56
53
  | `containers` | `--container-<key>` | **extension** — content widths, a separate axis from spacing (`prose, md, 3xl, 6xl`) |
57
54
  | `googleFontsHref` | the Layout `<link>` href | **extension** — the ready stylesheet URL for the chosen families |
58
55
 
56
+ > **Spacing is not a DESIGN.md token.** The build uses Tailwind v4's built-in numeric spacing scale directly (`gap-4`, `py-24`, `px-6`, …). A named `--spacing-<size>` scale was removed because its t-shirt names (`md`, `3xl`, …) collided with the width utilities (`max-w-3xl` resolved to `--spacing-3xl` instead of `--container-3xl`). Do not author a `spacing` group.
57
+
59
58
  ### Color roles — wix-native keys are the contract
60
59
 
61
60
  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):
@@ -41,7 +41,7 @@ Every input you need is either inlined in your prompt or — for seeded entity I
41
41
  | Scope | Where its inputs come from |
42
42
  |---|---|
43
43
  | `seed` | All **inlined**: `brand`, `intent.<pack>`, `siteId`, recipe path(s). Do NOT re-derive these. |
44
- | `components` | **Inlined**: `brand`. **Read from disk**: the design tokens (the DESIGN.md vocabulary — `colors`/`typography`/`spacing`/`rounded`/`containers`) from `.wix/design-tokens.css` (gate-verified present; also the CSS variables the build consumes). Components do not need seeded IDs. |
44
+ | `components` | **Inlined**: `brand`. **Read from disk**: the design tokens (the DESIGN.md vocabulary — `colors`/`typography`/`rounded`/`containers`; spacing is Tailwind's numeric scale, not a token) from `.wix/design-tokens.css` (gate-verified present; also the CSS variables the build consumes). Components do not need seeded IDs. |
45
45
  | `pages` / `pages-*` | **Inlined:** `brand`. **Read from disk:** the design tokens (`.wix/design-tokens.css`, DESIGN.md vocabulary); your `seeded.<vertical>` slice from `.wix/seeded.json` (products, posts, collections IDs). Page data wiring uses live SDK queries; the `seeded` data is for path resolution + demo content authoring. |
46
46
 
47
47
  If a required **inlined** input is missing from your prompt, or your **`.wix/seeded.json` slice** is absent (e.g. you are dispatched as `pages-products` but `.wix/seeded.json` has no `seeded.stores`), fail fast — return `status: "failed"` with `errors: [{ code: "SEEDED_JSON_SLICE_MISSING", missing: "seeded.stores.products" }]` (or `PROMPT_INCOMPLETE` for an inlined gap). Do NOT re-fetch via curl — the gap means an upstream phase didn't complete, and re-querying would mask the real bug.
@@ -120,11 +120,11 @@ The full styling contract (tokens-as-utilities default, when global semantic cla
120
120
 
121
121
  - **camelCase for identifiers, kebab-case for filenames, PascalCase for components.** Example: `ProductCard.astro`, `queryBlogPosts` function, `cart-updated` event.
122
122
  - **No inline styles beyond design-token CSS variables.** `style={{ color: "red" }}` is forbidden; `style={{ color: "var(--color-accent)" }}` is fine.
123
- - **Tailwind v4 `@reference` is mandatory in any scoped CSS that uses `@apply`.** Tailwind v4 isolates `@apply` per file — utilities defined in the main entry CSS (where `@theme` lives) are NOT visible to `components-*.css` unless that file prepends `@reference "./global.css";` on line 1. If your scope writes a `components-<vertical>.css` that uses `@apply` with theme tokens (e.g., `@apply gap-sm font-display text-sm`), the file MUST start with:
123
+ - **Tailwind v4 `@reference` is mandatory in any scoped CSS that uses `@apply`.** Tailwind v4 isolates `@apply` per file — utilities defined in the main entry CSS (where `@theme` lives) are NOT visible to `components-*.css` unless that file prepends `@reference "./global.css";` on line 1. If your scope writes a `components-<vertical>.css` that uses `@apply` with theme tokens (e.g., `@apply gap-3 font-display text-sm`), the file MUST start with:
124
124
  ```css
125
125
  @reference "./global.css";
126
126
  ```
127
- Without it, the build breaks at release time with `Cannot apply unknown utility class 'gap-sm' …` even though `tsc` and `astro check` pass clean — only the bundler catches it.
127
+ Without it, the build breaks at release time with `Cannot apply unknown utility class 'gap-3' …` even though `tsc` and `astro check` pass clean — only the bundler catches it.
128
128
  - **Fail loud, never silently.** If data is missing, a required field is absent, or an REST call returns an unexpected shape, return `status: "failed"` with details. Do not invent placeholders or swallow errors.
129
129
 
130
130
  ## Return contract
@@ -188,7 +188,7 @@ The `data` shapes for the scopes this file owns — `components` and `pages`/`pa
188
188
  | Issuing REST calls from a `components` or `pages` scope | Components/Pages are frontend-only; read `seeded` data from your `.wix/seeded.json` slice (pages only) — never curl |
189
189
  | Re-querying when your `seeded.<vertical>` slice is missing from `.wix/seeded.json` | Fail fast with `SEEDED_JSON_SLICE_MISSING` — an upstream phase didn't complete (do NOT re-query) |
190
190
  | Depending on mutable shared state the orchestrator holds in scratch | Every input is inlined; the one shared file you may read is your `.wix/seeded.json` slice (read-only) |
191
- | Inventing class names for layout/spacing/typography (`.productCard`, `.heroSection`) | Tailwind utilities derived from `@theme` tokens (`class="flex flex-col gap-md"`, `class="py-4xl"`). For one-off page decoration, co-located `<style>` block. |
191
+ | Inventing class names for layout/spacing/typography (`.productCard`, `.heroSection`) | Tailwind utilities derived from `@theme` tokens (`class="flex flex-col gap-4"`, `class="py-24"`). For one-off page decoration, co-located `<style>` block. |
192
192
  | Removing a marker after inserting at it | Marker stays; other verticals may contribute after you |
193
193
  | Trailing narrative prose after the return JSON | JSON block must be the last content |
194
194
  | Fabricated timestamps in the return JSON | Do not include timing fields — orchestrator captures them |
@@ -8,15 +8,15 @@ Every visual decision in a generated site falls into one of three categories. Ea
8
8
 
9
9
  | Category | Lives in | Owned by | Use for |
10
10
  |---|---|---|---|
11
- | **Tokens (composed as utilities)** | the canonical `DESIGN.md` + its projections: the `@theme` block in `src/styles/global.css` (written by `scripts/compose.mjs`), plus `.wix/design-tokens.css` and `.wix/site.d.ts` (written by `scripts/emit-design-tokens.mjs`) — all from Designer's `DESIGN.md` | Designer picks values (Phase 2); `compose.mjs` writes `@theme` | All color, spacing, typography scale, radii, aspect ratios, shadows, transitions. Pages compose tokens at call sites as Tailwind utilities — `class="py-4xl bg-sand aspect-[16/5]"`. |
11
+ | **Tokens (composed as utilities)** | the canonical `DESIGN.md` + its projections: the `@theme` block in `src/styles/global.css` (written by `scripts/compose.mjs`), plus `.wix/design-tokens.css` and `.wix/site.d.ts` (written by `scripts/emit-design-tokens.mjs`) — all from Designer's `DESIGN.md` | Designer picks values (Phase 2); `compose.mjs` writes `@theme` | All color, typography scale, radii, aspect ratios, shadows, transitions (spacing is Tailwind's built-in numeric scale). Pages compose tokens at call sites as Tailwind utilities — `class="py-24 bg-sand aspect-[16/5]"`. |
12
12
  | **Global semantic classes** | `src/styles/global.css` (outside `@theme`) and `src/styles/components-<pack>.css` | Designer + Phase 3 component agents | Compound multi-element patterns, interactive states (`:hover`, `:focus`, `:disabled`), and JS/React DOM query targets. |
13
13
  | **Co-located styles** | `<style>` block at the bottom of the same `.astro` file (or component CSS module for islands) | Page or component author | One-off page decoration: hero stamps, custom dividers, ornamental overlays that won't be reused elsewhere. |
14
14
 
15
15
  ## Default direction
16
16
 
17
- **Tokens-as-utilities is the default.** When you're about to write a class for layout, spacing, typography, alignment, simple background/text color, or aspect ratio, write Tailwind utilities derived from `@theme` instead. The site's design tokens give you `py-4xl`, `gap-sm`, `bg-paper-warm`, `text-ink`, `font-display`, `aspect-[16/5]` etc. Compose them in markup; do not invent semantic classes for these concerns.
17
+ **Tokens-as-utilities is the default.** When you're about to write a class for layout, spacing, typography, alignment, simple background/text color, or aspect ratio, write Tailwind utilities derived from `@theme` instead. The site's design tokens give you `bg-paper-warm`, `text-ink`, `font-display`, `aspect-[16/5]` etc.; spacing is Tailwind-numeric (`py-24`, `gap-3`). Compose them in markup; do not invent semantic classes for these concerns.
18
18
 
19
- The token namespace is the contract. The design tokens (the DESIGN.md token vocabulary — `colors`/`typography`/`spacing`/`rounded`/`containers`) live on disk at `.wix/design-tokens.css` (gate-verified present before the build wave) — **read that file at the start of any pages or components scope** to know which tokens this run published. The orchestrator does **not** inline them in your prompt. (`.wix/site.d.ts` is also on disk for the build.) If a token you need isn't in `.wix/design-tokens.css`, that's a designer-side gap — flag it in your return JSON, don't paper over it with a custom class.
19
+ The token namespace is the contract. The design tokens (the DESIGN.md token vocabulary — `colors`/`typography`/`rounded`/`containers`) live on disk at `.wix/design-tokens.css` (gate-verified present before the build wave) — **read that file at the start of any pages or components scope** to know which tokens this run published. The orchestrator does **not** inline them in your prompt. (`.wix/site.d.ts` is also on disk for the build.) If a token you need isn't in `.wix/design-tokens.css`, that's a designer-side gap — flag it in your return JSON, don't paper over it with a custom class.
20
20
 
21
21
  ## Decision tree
22
22
 
@@ -32,24 +32,22 @@ If none fit, you're probably trying to do something the tokens don't support yet
32
32
 
33
33
  These are layout/spacing/typography concerns that should always be utilities, never standalone classes:
34
34
 
35
- - Section padding / margins (`py-4xl`, `mt-3xl`, `mb-2xl`)
36
- - Flex / grid layouts (`flex flex-col gap-md`, `grid grid-cols-3 gap-lg`)
35
+ - Section padding / margins (`py-24`, `mt-16`, `mb-12`)
36
+ - Flex / grid layouts (`flex flex-col gap-4`, `grid grid-cols-3 gap-6`)
37
37
  - Aspect ratios (`aspect-[4/5]`, `aspect-square`)
38
38
  - Plain typography choices (`text-display-lg font-display`, `text-mute uppercase tracking-wide`)
39
39
  - Background / foreground color application without state (`bg-paper`, `text-ink-soft`)
40
- - Container widths derived from tokens (`max-w-prose`, `w-full`) **only when** the designer declared matching `--container-*` keys in `@theme`
40
+ - Container widths (`max-w-prose`, `max-w-6xl`, `max-w-3xl`, `w-full`) — these resolve to the `--container-*` keys the designer declared.
41
41
 
42
- ### Prose / reading width (CMS, FAQ, About)
42
+ ### Spacing & reading width
43
43
 
44
- Tailwind v4 resolves `max-w-3xl` to `var(--container-3xl)`, **not** `var(--spacing-3xl)`. If the designer published `--spacing-3xl: 5rem` but no `--container-3xl`, FAQ/About columns collapse to ~80px.
44
+ **Spacing is Tailwind's built-in numeric scale** — `gap-4`, `py-24`, `px-6`, `mt-16`, etc. There is **no** named `--spacing-<size>` scale (it was removed: its t-shirt names `md`/`3xl`/… collided with the width utilities, so `max-w-3xl` resolved to `--spacing-3xl` ≈ 96px). Common steps: `1`=0.25rem, `2`=0.5, `3`=0.75, `4`=1rem, `6`=1.5, `8`=2, `12`=3, `16`=4, `24`=6rem.
45
45
 
46
- **Page agents (Phase 4):**
46
+ > **Never reintroduce a named `--spacing-*` scale.** In Tailwind v4 the `--spacing-*` namespace also generates the width/sizing families (`max-w-*`, `w-*`, `min-w-*`, …), so any `--spacing-<key>` token shadows the matching `max-w-<key>`. The current fix works because the skill's spacing steps happen to equal Tailwind's numeric defaults — but if a brand ever needs genuinely *custom* spacing **values**, put them under a different namespace (e.g. `--rhythm-*`) or use arbitrary values (`py-[5.5rem]`); do not revive `--spacing-*`.
47
47
 
48
- - **Do not** use `max-w-2xl`, `max-w-3xl`, etc. unless `global.css` `@theme` documents the matching `--container-*` key (grep `@theme` before choosing).
49
- - **Prefer** `container-reading` (designer `@utility`), `max-w-6xl` when `--container-6xl` exists, or explicit arbitrary width `max-w-[48rem]`.
50
- - **Do not** confuse spacing scale with container scale — `py-3xl` uses `--spacing-3xl`; `max-w-3xl` uses `--container-3xl`.
48
+ **Width / reading columns:** `max-w-md`, `max-w-3xl`, `max-w-6xl`, `max-w-prose` now resolve correctly to the `--container-*` keys (no spacing collision), so use them freely; `container-reading` (the designer `@utility`) or an arbitrary `max-w-[48rem]` also work.
51
49
 
52
- If a designer's `global.css` contains rules like `.featured-section { padding-block: var(--spacing-4xl); }` or `.product-card-body { display: flex; flex-direction: column; gap: var(--spacing-xs); }`, those are misplaced — they belong in markup as utilities. Inventing such classes ships broken layouts: every consumer needs the designer to have pre-declared the class, and Tailwind v4 silently drops the references when the rule is missing.
50
+ If a designer's `global.css` contains rules like `.featured-section { padding-block: 6rem; }` or `.product-card-body { display: flex; flex-direction: column; gap: 0.5rem; }`, those are misplaced — they belong in markup as utilities (`py-24`, `flex flex-col gap-2`). Inventing such classes ships broken layouts: every consumer needs the designer to have pre-declared the class, and Tailwind v4 silently drops the references when the rule is missing.
53
51
 
54
52
  ## Required tokens — the component-CSS template contract
55
53
 
@@ -68,11 +66,10 @@ The per-pack `components-<pack>.css` templates at `<SKILL_ROOT>/references/astro
68
66
  | `--color-error` | optional | `var(--color-accent)` or hardcode | ecom cart-item-unavailable, stores back-in-stock-error |
69
67
  | `--font-display` | **required** | — | every pack — headings + labels |
70
68
  | `--font-body` | **required** | — | every pack — body text + UI |
71
- | `--spacing-2xs` … `--spacing-4xl` | **required (full scale)** | — | every template uses `gap: var(--spacing-md)` and similar |
72
69
  | `--radius-sm`, `--radius-md` | **required** | — | buttons, inputs, cards |
73
70
  | `--radius-lg`, `--radius-xl` | optional | — | stores product-card |
74
71
 
75
- The templates do NOT use `@apply` — every rule is `property: var(--token);` directly. This means missing utilities don't fail at build time (the way `@apply gap-sm` would). Missing tokens degrade silently to `var(missing) → unset → initial`. That makes the failure mode "ugly component" not "broken build" — easier to recover from but harder to detect, so verify the full set above is in `@theme` before returning.
72
+ The templates do NOT use `@apply` — every rule is `property: var(--token);` directly. This means missing utilities don't fail at build time (the way `@apply gap-3` would). Missing tokens degrade silently to `var(missing) → unset → initial`. That makes the failure mode "ugly component" not "broken build" — easier to recover from but harder to detect, so verify the full set above is in `@theme` before returning.
76
73
 
77
74
  **Why this contract exists.** The component templates are authored against a stable, brand-agnostic token vocabulary so they don't need to be regenerated per run. Using `@apply` against brand-specific tokens (e.g. `bark`, `cream`, `parchment`) that designers don't publish fails the build with `Cannot apply unknown utility class`. Direct `var()` against the required-token list above avoids that class of failure entirely.
78
75
 
@@ -119,15 +116,15 @@ For any listed class the Composer's `global.css` declares: if a template referen
119
116
  Astro's `<style>` blocks scope automatically to the `.astro` file by default — no class-name collision risk across routes. When a page needs decoration that doesn't fit utilities and isn't reusable, the rule lives next to its only caller:
120
117
 
121
118
  ```astro
122
- <section class="relative py-4xl">
119
+ <section class="relative py-24">
123
120
  <div class="hero-stamp">Made in small batches</div>
124
121
  </section>
125
122
 
126
123
  <style>
127
124
  .hero-stamp {
128
125
  position: absolute;
129
- bottom: var(--spacing-lg);
130
- right: var(--spacing-lg);
126
+ bottom: 1.5rem;
127
+ right: 1.5rem;
131
128
  background: rgba(27, 26, 23, 0.75);
132
129
  color: var(--color-paper);
133
130
  padding: 0.5rem 0.875rem;
@@ -95,8 +95,8 @@ If you find one of these missing at runtime, that's an orchestrator-side bug —
95
95
 
96
96
  Stores-specific component CSS lives in `src/styles/components-stores.css` (pre-copied from the template by the orchestrator before Step 4.5 — see the `components` scope-routing note above and `../astro/stores/COMPONENTS_CSS.md`), NOT in the designer's `global.css`. The classes the pack owns:
97
97
 
98
- - `.product-card`, `.product-card-media`, `.product-card-ribbon`, `.product-card-index` — the product card itself, including the `overflow: hidden` + `border-radius` clipping context. Whoever writes the `border-radius` here also writes any inner padding required to keep child content inside the rounded edges. Without inner padding, a price `<p>` sits flush against the rounded bottom corner and descenders get clipped. Add `padding-bottom: var(--spacing-md)` on the card plus horizontal padding on each text block when you set the radius. See `references/shared/STYLING.md` § "Component-specific CSS is owned by the component, not the designer".
99
- - `.product-grid` — the layout that lists product cards. Both `/products` (pages-products scope) and `/category/[slug]` (pages-categories scope) consume it from one place. Include `display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--spacing-xl);` plus the View-Transitions opacity fade for in-flight navigations.
98
+ - `.product-card`, `.product-card-media`, `.product-card-ribbon`, `.product-card-index` — the product card itself, including the `overflow: hidden` + `border-radius` clipping context. Whoever writes the `border-radius` here also writes any inner padding required to keep child content inside the rounded edges. Without inner padding, a price `<p>` sits flush against the rounded bottom corner and descenders get clipped. Add `padding-bottom: 1rem` on the card plus horizontal padding on each text block when you set the radius. See `references/shared/STYLING.md` § "Component-specific CSS is owned by the component, not the designer".
99
+ - `.product-grid` — the layout that lists product cards. Both `/products` (pages-products scope) and `/category/[slug]` (pages-categories scope) consume it from one place. Include `display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 2rem;` plus the View-Transitions opacity fade for in-flight navigations.
100
100
  - `.offer-callout` family (`.offer-callout`, `-item`, `-badge`, `-name`, `-detail`, `-foot`) — discount panel rendered above `<ProductPurchase>` on `/products/[slug]`.
101
101
 
102
102
  The designer's `global.css` declares only tokens, the `.btn` family, decorative slots, the editorial-rule, and the site-shell shells. If `global.css` ships with a partial rule for any class above, that's a designer bug — flag it in your return JSON's `errors` array (`{code: "GLOBAL_CSS_LEAK", class: "<name>"}`) and override with the complete rule in `components-stores.css`.
@@ -1,14 +1,16 @@
1
1
  ---
2
2
  name: bookings
3
- description: "Service-based booking — services catalog, availability calendar, and booking flow via Wix Bookings."
3
+ description: "Service-based booking — services catalog (with location + category filters and staff selection), availability calendar, and booking flow for appointments and classes via Wix Bookings."
4
4
  triggers: ["booking", "appointment", "schedule", "reserve", "class", "session", "consult", "therapy", "lesson", "coaching", "trainer", "tutor", "salon", "spa", "clinic"]
5
5
  requires: []
6
6
 
7
7
  features:
8
8
  - name: "Services catalog"
9
- description: "Browse bookable appointment services with descriptions, duration, and pricing."
9
+ description: "Browse bookable appointment and class services with descriptions, duration, and pricing — filterable by category and (for multi-location businesses) by location."
10
+ - name: "Staff selection"
11
+ description: "On multi-staff services, choose a specific staff member (or any) and see that staff's availability."
10
12
  - name: "Online booking"
11
- description: "Pick an available time slot on a calendar, complete the service's booking form, and confirm."
13
+ description: "Pick an available time slot on a day-grouped availability calendar, complete the service's booking form, and confirm."
12
14
  - name: "Secure checkout"
13
15
  description: "Free or pay-in-person bookings confirm instantly; paid services hand off to Wix's secure hosted checkout."
14
16
 
@@ -192,7 +192,6 @@ function designMdToTokens(fm) {
192
192
  return {
193
193
  colors,
194
194
  fonts,
195
- spacing: fm.spacing ?? {},
196
195
  radii: fm.rounded ?? {}, // DESIGN.md calls corner radii `rounded`
197
196
  containers: fm.containers ?? {}, // custom group
198
197
  ...(typeof fm.googleFontsHref === "string" ? { googleFontsHref: fm.googleFontsHref } : {}),
@@ -241,7 +240,6 @@ const SYSTEM_FONTS = new Set([
241
240
 
242
241
  const colors = { ...(designTokens.colors ?? {}) };
243
242
  const fonts = { ...(designTokens.fonts ?? {}) };
244
- const spacing = { ...(designTokens.spacing ?? {}) };
245
243
  const radii = { ...(designTokens.radii ?? {}) };
246
244
  const containers = { ...(designTokens.containers ?? {}) };
247
245
 
@@ -272,12 +270,10 @@ ensure(colors, "error", "#c0392b", "--color-");
272
270
  ensure(fonts, "display", "Georgia, serif", "--font-");
273
271
  ensure(fonts, "body", "system-ui, sans-serif", "--font-");
274
272
 
275
- // Spacing — full 2xs..4xl scale.
276
- const SPACING_DEFAULTS = {
277
- "2xs": "0.25rem", xs: "0.5rem", sm: "0.75rem", md: "1rem", lg: "1.5rem",
278
- xl: "2rem", "2xl": "3rem", "3xl": "4rem", "4xl": "6rem",
279
- };
280
- for (const [k, v] of Object.entries(SPACING_DEFAULTS)) ensure(spacing, k, v, "--spacing-");
273
+ // Spacing is NOT a named scale — Tailwind v4's built-in numeric spacing
274
+ // (`--spacing` base → gap-4, py-24, …) is used directly. Emitting named
275
+ // --spacing-<t-shirt> tokens collided with the width utilities (max-w-3xl etc.
276
+ // drew from --spacing-3xl), so the named scale was removed (CODEAI-696).
281
277
 
282
278
  // Radii — sm + md required.
283
279
  ensure(radii, "sm", "0.25rem", "--radius-");
@@ -296,8 +292,6 @@ emitGroup("--color-", colors);
296
292
  themeLines.push("");
297
293
  emitGroup("--font-", fonts);
298
294
  themeLines.push("");
299
- emitGroup("--spacing-", spacing);
300
- themeLines.push("");
301
295
  emitGroup("--radius-", radii);
302
296
  themeLines.push("");
303
297
  emitGroup("--container-", containers);
@@ -310,14 +304,12 @@ const errors = [];
310
304
  const REQUIRED = [
311
305
  ...["paper", "paper-warm", "ink", "mute", "rule", "accent"].map((k) => `--color-${k}`),
312
306
  "--font-display", "--font-body",
313
- ...["2xs", "xs", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl"].map((k) => `--spacing-${k}`),
314
307
  "--radius-sm", "--radius-md",
315
308
  ...["prose", "md", "3xl", "6xl"].map((k) => `--container-${k}`),
316
309
  ];
317
310
  const present = new Set([
318
311
  ...Object.keys(colors).map((k) => `--color-${k}`),
319
312
  ...Object.keys(fonts).map((k) => `--font-${k}`),
320
- ...Object.keys(spacing).map((k) => `--spacing-${k}`),
321
313
  ...Object.keys(radii).map((k) => `--radius-${k}`),
322
314
  ...Object.keys(containers).map((k) => `--container-${k}`),
323
315
  ]);
@@ -325,12 +317,6 @@ for (const tok of REQUIRED) {
325
317
  if (!present.has(tok)) errors.push({ code: "MISSING_REQUIRED_TOKEN", token: tok });
326
318
  }
327
319
 
328
- // Container ≠ spacing: a --container-* value must never equal a --spacing-* value.
329
- const spacingValues = new Set(Object.values(spacing));
330
- for (const [k, v] of Object.entries(containers)) {
331
- if (spacingValues.has(v)) errors.push({ code: "CONTAINER_EQUALS_SPACING", token: `--container-${k}`, value: v });
332
- }
333
-
334
320
  // ── skeleton load + substitution helpers ──────────────────────────────────────
335
321
  function readTemplate(name) {
336
322
  const p = join(TEMPLATES, name);
@@ -526,7 +512,6 @@ const manifest = {
526
512
  homeMarkers: homeMarkerPacks.map((p) => `home:${p}`),
527
513
  tokensApplied: {
528
514
  colors: Object.keys(colors).length,
529
- spacing: Object.keys(spacing).length,
530
515
  containers: Object.keys(containers).length,
531
516
  radii: Object.keys(radii).length,
532
517
  fonts: Object.keys(fonts).length,
@@ -115,7 +115,6 @@ if (!design || typeof design !== "object" || Object.keys(design).length === 0) {
115
115
 
116
116
  const colors = design.colors ?? {};
117
117
  const typography = design.typography ?? {};
118
- const spacing = design.spacing ?? {};
119
118
  const rounded = design.rounded ?? {};
120
119
  const containers = design.containers ?? {};
121
120
  const fontFamilyOf = (lvl) => (typography[lvl] && typeof typography[lvl] === "object" ? typography[lvl].fontFamily : typography[lvl]);
@@ -136,7 +135,6 @@ for (const lvl of Object.keys(typography)) {
136
135
  if (fam) cssLines.push(` --font-${lvl}: ${fam};`);
137
136
  }
138
137
  for (const [k, v] of Object.entries(rounded)) cssLines.push(` --radius-${k}: ${v};`);
139
- for (const [k, v] of Object.entries(spacing)) cssLines.push(` --spacing-${k}: ${v};`);
140
138
  for (const [k, v] of Object.entries(containers)) cssLines.push(` --container-${k}: ${v};`);
141
139
  cssLines.push("}", "");
142
140
  writeFileSync(join(wixDir, "design-tokens.css"), cssLines.join("\n"));
@@ -151,7 +149,6 @@ export type DesignTokens = {
151
149
  colors: ${recordType(Object.keys(colors))};
152
150
  fonts: ${recordType(Object.keys(typography))};
153
151
  radii: ${recordType(Object.keys(rounded))};
154
- spacing: ${recordType(Object.keys(spacing))};
155
152
  containers: ${recordType(Object.keys(containers))};
156
153
  };
157
154
  `;
@@ -13,7 +13,6 @@ description: "Create an appointment booking service — e.g. 'set up consultatio
13
13
 
14
14
  ## Prerequisites
15
15
 
16
- - **Wix Bookings app installed** (App ID: `13d21c63-b5ec-5912-8397-c3a5ddb27a97`). Use [List Installed Apps](../app-installation/list-installed-apps.md) to verify, and [Install Wix Apps](../app-installation/install-wix-apps.md) to install if missing.
17
16
  - For full API field definitions, validation rules, and troubleshooting, see [Create and Update Booking Services](./create-and-update-booking-services.md)
18
17
 
19
18
  ---
@@ -47,16 +46,7 @@ curl -X POST 'https://www.wixapis.com/bookings/v2/categories/query' \
47
46
  -d '{ "query": {} }'
48
47
  ```
49
48
 
50
- ### 1c. Get Site Currency
51
-
52
- ```bash
53
- curl -X GET 'https://www.wixapis.com/site-properties/v4/properties' \
54
- -H 'Authorization: <AUTH>'
55
- ```
56
-
57
- Extract `properties.paymentCurrency`. Fall back to `USD` if unavailable.
58
-
59
- ### 1d. Query Existing Services (Duplicate Check)
49
+ ### 1c. Query Existing Services (Duplicate Check)
60
50
 
61
51
  ```bash
62
52
  curl -X POST 'https://www.wixapis.com/bookings/v2/services/query' \
@@ -82,7 +72,6 @@ For any fields the user did not explicitly specify:
82
72
 
83
73
  ### Pricing (if not specified)
84
74
 
85
- - Use the site's currency from Step 1c
86
75
  - If user specifies a price → `rateType: "FIXED"`
87
76
  - If user says "free" → `rateType: "NO_FEE"`, `options.inPerson: true`, `options.online: false`
88
77
  - If no price mentioned → infer from context (consultations ~$50-100, sessions ~$30-60) or default to free
@@ -136,7 +125,7 @@ curl -X POST 'https://www.wixapis.com/bookings/v2/bulk/services/create' \
136
125
  "rateType": "FIXED",
137
126
  "options": { "online": true, "inPerson": false },
138
127
  "fixed": {
139
- "price": { "value": "<PRICE>", "currency": "<CURRENCY>" }
128
+ "price": { "value": "<PRICE>" }
140
129
  }
141
130
  },
142
131
  "category": {
@@ -186,19 +175,7 @@ Save the `serviceId` from the response: `results[0].item.service.id`
186
175
 
187
176
  ---
188
177
 
189
- ## Step 4: Navigate to Service Form
190
-
191
- Use the **RUN_IN_BROWSER** tool to navigate the user to the service form for final review:
192
-
193
- ```javascript
194
- window.location.href = `/bookings/services/form/${serviceId}?fromAria=true`;
195
- ```
196
-
197
- This executes in the user's browser and redirects them to the service editing page.
198
-
199
- ---
200
-
201
- ## Step 5: Summary Message
178
+ ## Step 4: Summary Message
202
179
 
203
180
  Provide a summary including:
204
181
 
@@ -225,7 +202,6 @@ Provide a summary including:
225
202
 
226
203
  | Error | Cause | Action |
227
204
  |---|---|---|
228
- | 428 "App not installed" | Bookings not installed | Install using [Install Wix Apps](../app-installation/install-wix-apps.md) |
229
205
  | 400 "staffMemberIds required" | No staff assigned | Query staff; if none exist, create one via [Bookings Staff Setup](./bookings-staff-setup.md) |
230
206
  | 400 "INVALID_PAYMENT_OPTIONS" | Payment misconfigured | Free: `inPerson: true`, `online: false`. Paid: price > 0 |
231
207
  | 403 | Permission denied | Inform user they lack permission |
@@ -261,6 +237,5 @@ Provide a summary including:
261
237
  - [Create Category](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/create-category)
262
238
  - [Query Staff Members](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/query-staff-members)
263
239
  - [Create Staff Member](https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/create-staff-member)
264
- - [Site Properties](https://dev.wix.com/docs/api-reference/business-management/site-management/site-properties/properties/read)
265
240
  - [About Service Types](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-types)
266
241
  - [About Service Payments](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-payments)
@@ -10,13 +10,6 @@ description: "Create a booking service from a user prompt — e.g. 'create a yog
10
10
  - User describes a service they want to create using natural language (e.g., "create a yoga class for $50", "set up consultation sessions", "add a personal training appointment")
11
11
  - The intent is autonomous creation — fill in reasonable defaults rather than asking the user for every field
12
12
 
13
- ## Prerequisites
14
-
15
- - **Wix Bookings app installed** (App ID: `13d21c63-b5ec-5912-8397-c3a5ddb27a97`)
16
- - If Bookings is not installed, use [Install Wix Apps](../app-installation/install-wix-apps.md) to install it first
17
-
18
- ---
19
-
20
13
  ## Step 1: Determine Service Type
21
14
 
22
15
  | User mentions | Type | Recipe |
@@ -30,7 +23,7 @@ description: "Create a booking service from a user prompt — e.g. 'create a yog
30
23
 
31
24
  Once the service type is determined, follow the corresponding recipe linked above. Each recipe covers:
32
25
 
33
- 1. Gathering business context (staff, categories, currency, duplicate check)
26
+ 1. Gathering business context (staff where required, categories, duplicate check)
34
27
  2. Applying type-specific defaults (pricing, capacity, duration, staff assignment)
35
28
  3. Creating the service via `bulkCreateServices`
36
29
  4. Navigating to the service form for user review
@@ -14,7 +14,6 @@ description: "Create a class booking service — e.g. 'create a yoga class for $
14
14
 
15
15
  ## Prerequisites
16
16
 
17
- - **Wix Bookings app installed** (App ID: `13d21c63-b5ec-5912-8397-c3a5ddb27a97`). Use [List Installed Apps](../app-installation/list-installed-apps.md) to verify, and [Install Wix Apps](../app-installation/install-wix-apps.md) to install if missing.
18
17
  - For full API field definitions, validation rules, and troubleshooting, see [Create and Update Booking Services](./create-and-update-booking-services.md)
19
18
 
20
19
  ---
@@ -32,16 +31,7 @@ curl -X POST 'https://www.wixapis.com/bookings/v2/categories/query' \
32
31
  -d '{ "query": {} }'
33
32
  ```
34
33
 
35
- ### 1b. Get Site Currency
36
-
37
- ```bash
38
- curl -X GET 'https://www.wixapis.com/site-properties/v4/properties' \
39
- -H 'Authorization: <AUTH>'
40
- ```
41
-
42
- Extract `properties.paymentCurrency`. Fall back to `USD` if unavailable.
43
-
44
- ### 1c. Query Existing Services (Duplicate Check)
34
+ ### 1b. Query Existing Services (Duplicate Check)
45
35
 
46
36
  ```bash
47
37
  curl -X POST 'https://www.wixapis.com/bookings/v2/services/query' \
@@ -67,7 +57,6 @@ For any fields the user did not explicitly specify:
67
57
 
68
58
  ### Pricing (if not specified)
69
59
 
70
- - Use the site's currency from Step 1b
71
60
  - If user specifies a price → `rateType: "FIXED"` (per session)
72
61
  - If user says "free" → `rateType: "NO_FEE"`, `options.inPerson: true`, `options.online: false`
73
62
  - If no price mentioned → infer from context (yoga/fitness classes ~$15-30, art/music ~$20-40) or default to free
@@ -118,7 +107,7 @@ curl -X POST 'https://www.wixapis.com/bookings/v2/bulk/services/create' \
118
107
  "rateType": "FIXED",
119
108
  "options": { "online": true, "inPerson": false },
120
109
  "fixed": {
121
- "price": { "value": "<PRICE>", "currency": "<CURRENCY>" }
110
+ "price": { "value": "<PRICE>" }
122
111
  }
123
112
  },
124
113
  "category": {
@@ -164,19 +153,7 @@ Save the `serviceId` from the response: `results[0].item.service.id`
164
153
 
165
154
  ---
166
155
 
167
- ## Step 4: Navigate to Service Form
168
-
169
- Use the **RUN_IN_BROWSER** tool to navigate the user to the service form for final review:
170
-
171
- ```javascript
172
- window.location.href = `/bookings/services/form/${serviceId}?fromAria=true`;
173
- ```
174
-
175
- This executes in the user's browser and redirects them to the service editing page.
176
-
177
- ---
178
-
179
- ## Step 5: Summary Message
156
+ ## Step 4: Summary Message
180
157
 
181
158
  Provide a summary including:
182
159
 
@@ -205,7 +182,6 @@ Provide a summary including:
205
182
 
206
183
  | Error | Cause | Action |
207
184
  |---|---|---|
208
- | 428 "App not installed" | Bookings not installed | Install using [Install Wix Apps](../app-installation/install-wix-apps.md) |
209
185
  | 400 "INVALID_PAYMENT_OPTIONS" | Payment misconfigured | Free: `inPerson: true`, `online: false`. Paid: price > 0 |
210
186
  | 403 | Permission denied | Inform user they lack permission |
211
187
 
@@ -240,6 +216,5 @@ Provide a summary including:
240
216
  - [Query Categories](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/query-categories)
241
217
  - [Create Category](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/create-category)
242
218
  - [Bulk Create Events](https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-create-event)
243
- - [Site Properties](https://dev.wix.com/docs/api-reference/business-management/site-management/site-properties/properties/read)
244
219
  - [About Service Types](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-types)
245
220
  - [About Service Payments](https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/about-service-payments)