@wix/agent-skills 1.16.1 → 1.16.3

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 (73) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +72 -8
  3. package/skills/wix-app/references/CODE_QUALITY.md +0 -1
  4. package/skills/wix-app/references/DASHBOARD_MODAL.md +21 -14
  5. package/skills/wix-app/references/DASHBOARD_PAGE.md +30 -184
  6. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +14 -6
  7. package/skills/wix-app/references/EMBEDDED_SCRIPT.md +6 -0
  8. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +172 -0
  9. package/skills/wix-app/references/dashboard-page/WDS_LAYOUT.md +187 -0
  10. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +32 -2
  11. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +38 -1
  12. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +27 -4
  13. package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +167 -0
  14. package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +19 -0
  15. package/skills/wix-app/references/editor-react-component/PARTS.md +1 -2
  16. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +2 -2
  17. package/skills/wix-base44-connector/SKILL.md +185 -0
  18. package/skills/wix-base44-connector/scripts/utils.js +212 -0
  19. package/skills/wix-design-system/SKILL.md +19 -15
  20. package/skills/wix-docs/SKILL.md +75 -1
  21. package/skills/wix-manage/SKILL.md +16 -18
  22. package/skills/wix-manage/references/bookings/create-class-service.md +1 -1
  23. package/skills/wix-manage/references/domains/domain-search-purchase-and-connect.md +2603 -0
  24. package/skills/wix-manage/references/events/create-wix-event.md +112 -90
  25. package/skills/wix-manage/references/events/manage-wix-events.md +33 -94
  26. package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +182 -5
  27. package/skills/wix-manage/references/sites/create-headless-site.md +1 -0
  28. package/skills/wix-manage/references/sites/manage-oauth-apps.md +154 -0
  29. package/skills/wix-manage/references/sites/read-site-context.md +125 -0
  30. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +273 -0
  31. package/skills/wix-vibe-headless/install/deploy.cjs +1 -2
  32. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +104 -0
  33. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +74 -0
  34. package/skills/wix-vibe-headless/platforms/base44.md +3 -3
  35. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +1 -1
  36. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +1 -1
  37. package/skills/wix-vibe-headless/references/events/seed/SEED.md +1 -1
  38. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +1 -1
  39. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +1 -1
  40. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +1 -1
  41. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +68 -2
  42. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +29 -86
  43. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +3 -8
  44. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +78 -105
  45. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +92 -0
  46. package/skills/wix-vibe-headless/references/storefront/app/hooks/useVariantOptions.js +76 -0
  47. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +1 -1
  48. package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +0 -326
  49. package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +0 -115
  50. package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +0 -264
  51. package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +0 -37
  52. package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +0 -86
  53. package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +0 -119
  54. package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +0 -103
  55. package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +0 -76
  56. package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +0 -82
  57. package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +0 -89
  58. package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +0 -124
  59. package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +0 -91
  60. package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +0 -71
  61. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +0 -70
  62. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +0 -73
  63. package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +0 -98
  64. package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +0 -278
  65. package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +0 -94
  66. package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +0 -43
  67. package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +0 -66
  68. package/skills/wix-app/references/auto-patterns-dashboard/views.md +0 -76
  69. package/skills/wix-app/scripts/generate-auto-patterns.js +0 -510
  70. package/skills/wix-manage/references/domains/domain-search-and-purchase.md +0 -437
  71. package/skills/wix-manage/references/stores/create-product-from-image.md +0 -1031
  72. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +0 -623
  73. package/skills/wix-manage/references/stores/setup-online-store-catalog-v3.md +0 -106
@@ -1,10 +1,12 @@
1
1
  ---
2
2
  name: "Author Ricos Rich Content"
3
- description: Hand-authoring valid Ricos rich-content JSON (the richContent/nodes tree) used across Wix Blog posts, Stores product descriptions, Events, and CMS rich-text fields. Covers every common node shape — paragraphs, headings, lists, blockquotes, dividers, tables (with cell fills), code blocks, images — plus inline text decorations and the nesting rules the format enforces.
3
+ description: Authoritative recipe for hand-authoring valid Ricos rich-content JSON (the richContent/nodes tree) used across Wix Blog posts, Stores product descriptions, Events, and CMS rich-text fields. Use whenever a user asks to create, output, or return Ricos, richContent, or nodes-tree JSON; retrieve and read this full recipe before API schema search or constructing the JSON. Covers paragraphs, headings, lists, blockquotes, dividers, tables, code blocks, images, buttons, audio, video, galleries, collapsible lists, HTML embeds, inline decorations, and nesting rules.
4
4
  ---
5
5
 
6
6
  # Author Ricos Rich Content
7
7
 
8
+ > **Routing rule (READ FIRST).** When hand-authoring or returning Ricos / `richContent` JSON, use **this recipe** — the shapes, nesting rules, spacer paragraphs, and plugin nodes below. Do not rely on API schema search alone; it misses those details. After this recipe loads, do not perform additional schema or documentation searches for node types covered here; compose and self-audit the JSON from this file. When the user only wants JSON output, **do not** call Ricos convert/validate APIs.
9
+
8
10
  Ricos is Wix's rich-content format — a tree of typed nodes serialized as JSON. The same structure is embedded by many products: a Blog post's `draftPost.richContent`, a Store product's rich description, an Events description, and CMS rich-text fields all expect a Ricos document. This recipe is the **authoring reference for that node tree**: the valid shape of each node, how nodes nest, and how to format text. It is intentionally product-agnostic — the consuming API decides *where* the document goes; this recipe governs *what a valid document looks like*.
9
11
 
10
12
  > A Ricos document is an object with a `nodes` array: `{ "nodes": [ /* block nodes */ ] }`. Whatever field the consuming API exposes (e.g. `richContent`), it holds this object. For validating or converting an existing document to/from HTML/Markdown, see [Ricos Converter Service](ricos-converter-service.md).
@@ -15,10 +17,58 @@ Ricos is Wix's rich-content format — a tree of typed nodes serialized as JSON.
15
17
  - Every node carries a `type`, an optional `id`, and (for container nodes) a `nodes` array of children. Node `id`s are optional when authoring for a create request — the API generates them; the examples below omit `id` for brevity.
16
18
  - **TEXT is a leaf.** A TEXT node only ever lives inside a `PARAGRAPH`, `HEADING`, or `CODE_BLOCK`. It must **never** sit directly in the root `nodes` array or inside a `LIST_ITEM`, `BLOCKQUOTE`, or `TABLE_CELL` — those must contain a `PARAGRAPH` (or `HEADING`) that then contains the TEXT. See [Nesting rules](#nesting-rules).
17
19
  - Failing to wrap TEXT correctly produces the parse error **"Expected a paragraph node but found TEXT"**.
20
+ - **Block nodes do not get automatic vertical gap when rendered** — insert empty `PARAGRAPH` spacer nodes between sibling blocks when you need breathing room. See [Vertical spacing between blocks](#vertical-spacing-between-blocks).
21
+
22
+ ## Required plugin shape checklist
23
+
24
+ Use this checklist while composing and again before returning JSON. Treat every path below as required for the described request:
25
+
26
+ - **Button CTA:** emit a root-level `BUTTON`, never a `PARAGRAPH` with an inline `LINK`. Include `buttonData.type: "LINK"`, `buttonData.text`, `buttonData.link.url`, `buttonData.link.target`, and `buttonData.containerData`.
27
+ - **Hosted audio:** emit `{ "type": "AUDIO", "nodes": [], "audioData": { ... } }`. The empty `nodes` array is on the AUDIO node beside `audioData` — never inside `audioData`. Include `audioData.containerData.alignment`, `width`, and `textWrap`, plus `audioData.audio.src.id`.
28
+ - **Video with thumbnail:** place `videoData.video.src` and `videoData.video.duration` inside `video`; place `videoData.thumbnail` beside `video`, with `src.id`, `width`, and `height`.
29
+ - **Gallery:** emit one root-level `GALLERY`. Put images in `galleryData.items`, not as child IMAGE nodes. Every item uses `image.media` with `src`, `width`, and `height`; include `galleryData.options.layout.type` and `numberOfColumns`.
30
+ - **Collapsible FAQ:** use `COLLAPSIBLE_LIST → COLLAPSIBLE_ITEM → COLLAPSIBLE_ITEM_TITLE | COLLAPSIBLE_ITEM_BODY → PARAGRAPH → TEXT`. Every PARAGRAPH includes `paragraphData`, and every item includes both title and body.
31
+ - **HTML embed:** emit a root-level `HTML` with `htmlData.source`, either `url` or `html`, and `htmlData.containerData.width`, `height`, and `alignment`.
32
+
33
+ ## Vertical spacing between blocks
34
+
35
+ The renderer does **not** add margin between stacked block nodes. Adjacent paragraphs, headings, images, videos, tables, collapsible lists, buttons, galleries, and other blocks will sit flush against each other unless you separate them explicitly.
36
+
37
+ **Use an empty `PARAGRAPH` as a spacer** — a paragraph with no `nodes` (no TEXT children):
38
+
39
+ ```json
40
+ { "type": "PARAGRAPH" }
41
+ ```
42
+
43
+ Place spacer paragraphs at the root `nodes` level (or inside a `CARD` page) wherever layout needs vertical rhythm:
44
+
45
+ - **After headings** — before the following body copy or media block.
46
+ - **Between paragraphs** — when two text blocks should not run together visually.
47
+ - **After block plugins** — images, videos, audio, galleries, tables, collapsible lists, HTML embeds, buttons, dividers, and lists often need a spacer before the **next distinct section** (not between every adjacent block in a minimal snippet the user enumerated).
48
+ - **After blockquotes** — only when the following block is a separate section; skip the spacer when the user asked for a blockquote immediately followed by a specific paragraph in one compact output.
49
+ - **Before major sections** — optional extra spacer when transitioning from one content group to another.
50
+
51
+ When the user requests **only** specific nodes in one JSON output (e.g. "a blockquote and then a paragraph"), include exactly those nodes — do not add spacer paragraphs they did not ask for.
52
+
53
+ Do **not** rely on `\n` inside `textData.text` for spacing — that does not create a real line break between blocks. Do **not** expect `paragraphData` margins or `containerData` alone to separate unrelated sibling nodes; the empty paragraph is the supported spacing mechanism.
54
+
55
+ **Example — spacer after an image and before a table:**
56
+
57
+ ```json
58
+ {
59
+ "nodes": [
60
+ { "type": "IMAGE", "imageData": { /* … */ } },
61
+ { "type": "PARAGRAPH" },
62
+ { "type": "TABLE", "nodes": [ /* … */ ], "tableData": { /* … */ } },
63
+ { "type": "PARAGRAPH" },
64
+ { "type": "PARAGRAPH", "nodes": [ { "type": "TEXT", "textData": { "text": "Next section.", "decorations": [] } } ], "paragraphData": {} }
65
+ ]
66
+ }
67
+ ```
18
68
 
19
69
  ## Block node shapes
20
70
 
21
- **PARAGRAPH** — the base text container. An empty paragraph — `{ "type": "PARAGRAPH" }` — acts as a vertical spacer. `paragraphData.textStyle.textAlignment` accepts `AUTO`·`LEFT`·`CENTER`·`RIGHT`·`JUSTIFY`:
71
+ **PARAGRAPH** — the base text container. An empty paragraph — `{ "type": "PARAGRAPH" }` — is the **vertical spacer** between block nodes (the renderer adds no gap on its own). See [Vertical spacing between blocks](#vertical-spacing-between-blocks). `paragraphData.textStyle.textAlignment` accepts `AUTO`·`LEFT`·`CENTER`·`RIGHT`·`JUSTIFY`:
22
72
 
23
73
  ```json
24
74
  {
@@ -142,6 +192,122 @@ Ricos is Wix's rich-content format — a tree of typed nodes serialized as JSON.
142
192
  }
143
193
  ```
144
194
 
195
+ **BUTTON** — a standalone call-to-action block. **Not the same as an inline `LINK` decoration** on TEXT (that is hyperlinked body copy; this is a labeled button control). **`buttonData.type` is required** on every BUTTON node — use `"LINK"` for URL navigation or `"ACTION"` for viewer click handlers (never omit `type` even when `link` is present). Two `buttonData.type` values:
196
+
197
+ - **`LINK`** — navigates to a URL when clicked (`link.url`, `link.target`: `BLANK`·`SELF`, optional `link.rel`).
198
+ - **`ACTION`** — triggers a viewer `onClick` handler (store the node in JSON; behavior is configured in the Ricos viewer, not in the document body).
199
+
200
+ ```json
201
+ {
202
+ "type": "BUTTON",
203
+ "buttonData": {
204
+ "type": "LINK",
205
+ "text": "Get Started",
206
+ "link": { "url": "https://example.com", "target": "BLANK", "rel": { "nofollow": true } },
207
+ "containerData": { "alignment": "CENTER", "width": { "size": "ORIGINAL" }, "textWrap": true },
208
+ "styles": { "borderRadius": 4, "borderWidth": 0, "backgroundColor": "#116DFF", "textColor": "#FFFFFF" }
209
+ }
210
+ }
211
+ ```
212
+
213
+ **AUDIO** — uploaded audio via Wix Media `src.id`, or an embed variant whose `audioData.html` holds an iframe (SoundCloud, Spotify). Include `audioData.containerData` with `alignment` and width settings, and use an empty `nodes: []` array because AUDIO has no child nodes. Optional fields include `coverImage` (`src.id`, `width`, `height`), `name`, `authorName`, and `disableDownload`:
214
+
215
+ ```json
216
+ {
217
+ "type": "AUDIO",
218
+ "nodes": [],
219
+ "audioData": {
220
+ "containerData": { "alignment": "CENTER", "width": { "size": "CONTENT" }, "textWrap": true },
221
+ "audio": { "src": { "id": "mp3/f0f74f_48772df0375c41cd88e8e29370ccf899" } },
222
+ "disableDownload": true,
223
+ "coverImage": { "src": { "id": "f0f74f_2973832f552e4002b58ec6abbe7fce71~mv2.png" }, "width": 436, "height": 524 },
224
+ "name": "Track title",
225
+ "authorName": "Artist name"
226
+ }
227
+ }
228
+ ```
229
+
230
+ **VIDEO** — Wix Media `video.src.id`, `duration` (seconds), and a `thumbnail` (`src.id`, `width`, `height`). YouTube and other embeds use the same `VIDEO` node shape with the appropriate media id:
231
+
232
+ ```json
233
+ {
234
+ "type": "VIDEO",
235
+ "videoData": {
236
+ "containerData": { "width": { "size": "CONTENT" }, "alignment": "CENTER" },
237
+ "video": { "src": { "id": "video/11062b_a552731f40854d16a91627687fb8d1a6/1080p/mp4/file.mp4" }, "duration": 14.08 },
238
+ "thumbnail": { "src": { "id": "media/11062b_a552731f40854d16a91627687fb8d1a6f000.jpg" }, "width": 1920, "height": 1080 }
239
+ }
240
+ }
241
+ ```
242
+
243
+ **GALLERY** — multiple images in one block. Each `items[]` entry wraps `image.media` with `src` (`id` or `url`), `width`, and `height`. `galleryData.options` controls layout (`layout.type`: `GRID`, `numberOfColumns`, `orientation`; `item.ratio`, `item.crop`; `thumbnails.placement`):
244
+
245
+ ```json
246
+ {
247
+ "type": "GALLERY",
248
+ "galleryData": {
249
+ "containerData": { "width": { "size": "CONTENT" }, "alignment": "CENTER", "textWrap": true },
250
+ "items": [
251
+ { "image": { "media": { "src": { "id": "8bb438_36726a2d14ec44ee9edc5693bade1092.jpg" }, "width": 3648, "height": 5472 } } },
252
+ { "image": { "media": { "src": { "id": "8bb438_6bbf8e82fe8f4b79b6e03ee79b66fd6a.jpg" }, "width": 1920, "height": 1280 } } }
253
+ ],
254
+ "options": {
255
+ "layout": { "type": "GRID", "horizontalScroll": false, "orientation": "COLUMNS", "numberOfColumns": 3 },
256
+ "item": { "ratio": 1, "crop": "FILL" },
257
+ "thumbnails": { "placement": "NONE" }
258
+ }
259
+ }
260
+ }
261
+ ```
262
+
263
+ **COLLAPSIBLE_LIST** — FAQ-style expandable items. Nesting is `COLLAPSIBLE_LIST → COLLAPSIBLE_ITEM → COLLAPSIBLE_ITEM_TITLE | COLLAPSIBLE_ITEM_BODY → PARAGRAPH → TEXT` (body cells may also contain other supported block plugins such as IMAGE or VIDEO). The item wrapper type is **`COLLAPSIBLE_ITEM`** — not `COLLAPSIBLE_LIST_ITEM` or other variants:
264
+
265
+ ```json
266
+ {
267
+ "type": "COLLAPSIBLE_LIST",
268
+ "nodes": [
269
+ {
270
+ "type": "COLLAPSIBLE_ITEM",
271
+ "nodes": [
272
+ {
273
+ "type": "COLLAPSIBLE_ITEM_TITLE",
274
+ "nodes": [
275
+ { "type": "PARAGRAPH", "nodes": [ { "type": "TEXT", "textData": { "text": "Question?", "decorations": [] } } ], "paragraphData": { "textStyle": { "textAlignment": "AUTO" } } }
276
+ ]
277
+ },
278
+ {
279
+ "type": "COLLAPSIBLE_ITEM_BODY",
280
+ "nodes": [
281
+ { "type": "PARAGRAPH", "nodes": [ { "type": "TEXT", "textData": { "text": "Answer text.", "decorations": [] } } ], "paragraphData": { "textStyle": { "textAlignment": "AUTO" } } }
282
+ ]
283
+ }
284
+ ]
285
+ }
286
+ ],
287
+ "collapsibleListData": {
288
+ "containerData": { "alignment": "CENTER", "textWrap": true },
289
+ "expandOnlyOne": false,
290
+ "initialExpandedItems": "FIRST",
291
+ "direction": "LTR"
292
+ }
293
+ }
294
+ ```
295
+
296
+ `initialExpandedItems`: `NONE`·`FIRST`·`ALL`. Set `isQapageData: true` in list metadata when the list should render as FAQ structured data in search results.
297
+
298
+ **HTML** — embeds external content in an iframe. Provide either `url` (page URL) or inline `html` markup; `source` is typically `"HTML"`. Size via `containerData.width` / `height` (`custom` pixel strings or `size`):
299
+
300
+ ```json
301
+ {
302
+ "type": "HTML",
303
+ "htmlData": {
304
+ "containerData": { "width": { "custom": "550" }, "height": { "custom": "550" }, "alignment": "CENTER" },
305
+ "url": "https://example.com/embed",
306
+ "source": "HTML"
307
+ }
308
+ }
309
+ ```
310
+
145
311
  ## Inline text formatting (decorations)
146
312
 
147
313
  Apply formatting with the `decorations` array on a TEXT node. Each decoration is an object with a `type` and (for some types) a data field:
@@ -169,6 +335,7 @@ Apply formatting with the `decorations` array on a TEXT node. Each decoration is
169
335
  | `COLOR` | `colorData: { foreground: "#hex" }` (add `background` for highlight) |
170
336
  | `LINK` | `linkData: { link: { url, target: "BLANK" } }` |
171
337
  | `FONT_SIZE` | `fontSizeData: { unit: "PX", value: 24 }` |
338
+ | `SPOILER` | _(none — `{ "type": "SPOILER" }` hides text behind a reveal control)_ |
172
339
 
173
340
  - **Mixed formatting in one paragraph → split into multiple TEXT nodes** (one per style run) inside the same PARAGRAPH. A single TEXT node carries one consistent set of decorations.
174
341
  - Use a plain hex string in `foreground` for colors.
@@ -229,12 +396,16 @@ Note the mixed-run paragraph at the end: the linked words are their own TEXT nod
229
396
 
230
397
  | Parent | Valid children |
231
398
  | ------------------------------------ | ----------------------------------------------------------------------------------------------------- |
232
- | Root `nodes` | PARAGRAPH, HEADING, BULLETED_LIST, ORDERED_LIST, BLOCKQUOTE, DIVIDER, IMAGE, TABLE, CODE_BLOCK |
399
+ | Root `nodes` | PARAGRAPH, HEADING, BULLETED_LIST, ORDERED_LIST, BLOCKQUOTE, DIVIDER, IMAGE, TABLE, CODE_BLOCK, BUTTON, AUDIO, VIDEO, GALLERY, COLLAPSIBLE_LIST, HTML |
233
400
  | PARAGRAPH / HEADING / CODE_BLOCK | TEXT |
234
401
  | BULLETED_LIST / ORDERED_LIST | LIST_ITEM |
235
402
  | LIST_ITEM / BLOCKQUOTE | PARAGRAPH (which then contains TEXT) |
236
403
  | TABLE → TABLE_ROW → TABLE_CELL | cell contains PARAGRAPH / HEADING / IMAGE |
237
- | IMAGE | CAPTION (optional) |
404
+ | IMAGE / VIDEO | CAPTION (optional) |
405
+ | COLLAPSIBLE_LIST | COLLAPSIBLE_ITEM |
406
+ | COLLAPSIBLE_ITEM | COLLAPSIBLE_ITEM_TITLE, COLLAPSIBLE_ITEM_BODY |
407
+ | COLLAPSIBLE_ITEM_TITLE / _BODY | PARAGRAPH (and other plugins supported inside collapsible cells — see COLLAPSIBLE_LIST above) |
408
+ | BUTTON / AUDIO / GALLERY / HTML | _(leaf — `nodes: []` or omit)_ |
238
409
 
239
410
  ## Self-audit before returning the document
240
411
 
@@ -246,4 +417,10 @@ All decidable from the JSON itself — check before handing the document to a co
246
417
  4. **Headings carry a `level`** (1–6) and nest logically (don't jump H2 → H4).
247
418
  5. **No `\n` inside `textData.text`** — split into sibling nodes; mixed inline formatting → split into multiple TEXT runs.
248
419
  6. **Images** use a Wix Media `id` (not a raw URL), with `width`, `height`, and meaningful `altText`.
249
- 7. **Links** — every `LINK` decoration has a valid `url` and `target`.
420
+ 7. **Links** — every `LINK` decoration has a valid `url` and `target`. Use a `BUTTON` block with `buttonData.type: "LINK"` for CTAs — not an inline `LINK` decoration styled to look like a button.
421
+ 8. **Buttons** — every BUTTON includes **`buttonData.type`** (`LINK` requires `link.url`; `ACTION` has no URL). Omitting `type` is invalid even when `link` is set. `LINK` buttons and inline `LINK` decorations serve different purposes.
422
+ 9. **Media blocks** — AUDIO has root-level `nodes: []` and `audioData.containerData`; VIDEO keeps `thumbnail` beside `video` under `videoData`; every GALLERY item is under `galleryData.items` and carries `image.media.src`, `width`, and `height`.
423
+ 10. **Collapsible lists** — every item has both `_TITLE` and `_BODY`, each wrapping content through `PARAGRAPH → TEXT`, and every PARAGRAPH has `paragraphData`.
424
+ 11. **HTML embeds** — `htmlData` includes `source`, `containerData.width`, `containerData.height`, and either `url` or `html` (not both empty).
425
+ 12. **Spoiler** — `SPOILER` is a decoration on `TEXT` (or `containerData.spoiler` on some block plugins in editor output); preserve it verbatim on edit.
426
+ 13. **Vertical spacing** — stacked block nodes that should not appear cramped are separated by empty `{ "type": "PARAGRAPH" }` spacers — especially after images, videos, tables, collapsible lists, galleries, buttons, and between consecutive paragraphs. Missing spacers produce a wall-of-blocks layout with no renderer-added margin.
@@ -50,3 +50,4 @@ To provision headless onto an existing site, pass `"existingMetasite": {}` inste
50
50
  After creating the site:
51
51
  - Install additional apps using [Install Wix Apps](../app-installation/install-wix-apps.md)
52
52
  - Add content (products, services, blog posts, etc.)
53
+ - Use the `appId` as the `client_id` to mint visitor tokens and make buyer-facing API calls — see [Manage OAuth Apps](manage-oauth-apps.md)
@@ -0,0 +1,154 @@
1
+ ---
2
+ name: "Manage OAuth Apps"
3
+ description: Create, read, update, and query OAuth apps for a Wix headless site. Each OAuth app's id is the client_id a frontend uses to mint anonymous visitor tokens and call Wix APIs.
4
+ ---
5
+ # Manage OAuth Apps
6
+
7
+ An OAuth app is a site-level credential holder. Its `id` is the `client_id` (the two terms are interchangeable — Wix uses `appId` in provisioning responses, `clientId` in token requests, and `id` in the OAuth Apps API; they all refer to the same value).
8
+
9
+ When a headless site is provisioned it gets one OAuth app automatically (see [Create Headless Site](create-headless-site.md)); use this recipe to create additional apps, inspect existing ones, or update their redirect configuration.
10
+
11
+ > **`client_id` is not a secret** — it is a public identifier safe to embed in frontend code. The visitor token it mints is also non-privileged: it represents an anonymous visitor, not an admin. The `client_secret` is different — shown once in the Headless Settings dashboard, never returned by the API, and rotation is dashboard-only.
12
+
13
+ ---
14
+
15
+ ## Create an OAuth App
16
+
17
+ **Endpoint**: `POST https://www.wixapis.com/oauth-app/v1/oauth-apps`
18
+
19
+ ```bash
20
+ curl -X POST \
21
+ 'https://www.wixapis.com/oauth-app/v1/oauth-apps' \
22
+ -H 'Authorization: <AUTH>' \
23
+ -H 'wix-site-id: <metaSiteId>' \
24
+ -H 'Content-Type: application/json' \
25
+ -d '{
26
+ "oAuthApp": {
27
+ "name": "My Storefront",
28
+ "loginUrl": "https://example.com/login",
29
+ "allowedRedirectUris": ["https://example.com/callback"],
30
+ "allowedRedirectDomains": ["example.com"]
31
+ }
32
+ }'
33
+ ```
34
+
35
+ **Response**:
36
+ ```json
37
+ {
38
+ "oAuthApp": {
39
+ "id": "<clientId>",
40
+ "name": "My Storefront",
41
+ "loginUrl": "https://example.com/login",
42
+ "allowedRedirectUris": ["https://example.com/callback"],
43
+ "allowedRedirectDomains": ["example.com"],
44
+ "createdDate": "2026-08-18T10:00:00Z"
45
+ }
46
+ }
47
+ ```
48
+
49
+ `id` is the OAuth `client_id`. After creating the app, retrieve the `client_secret` from the Headless Settings dashboard.
50
+
51
+ ---
52
+
53
+ ## Get an OAuth App
54
+
55
+ **Endpoint**: `GET https://www.wixapis.com/oauth-app/v1/oauth-apps/{id}`
56
+
57
+ ```bash
58
+ curl 'https://www.wixapis.com/oauth-app/v1/oauth-apps/<clientId>' \
59
+ -H 'Authorization: <AUTH>' \
60
+ -H 'wix-site-id: <metaSiteId>'
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Query OAuth Apps
66
+
67
+ **Endpoint**: `POST https://www.wixapis.com/oauth-app/v1/oauth-apps/query`
68
+
69
+ ```bash
70
+ curl -X POST \
71
+ 'https://www.wixapis.com/oauth-app/v1/oauth-apps/query' \
72
+ -H 'Authorization: <AUTH>' \
73
+ -H 'wix-site-id: <metaSiteId>' \
74
+ -H 'Content-Type: application/json' \
75
+ -d '{ "query": {} }'
76
+ ```
77
+
78
+ Returns all OAuth apps for the site.
79
+
80
+ ---
81
+
82
+ ## Update an OAuth App
83
+
84
+ **Endpoint**: `PATCH https://www.wixapis.com/oauth-app/v1/oauth-apps/{id}`
85
+
86
+ Update requires an explicit `mask.paths` — omitting it silently updates nothing.
87
+
88
+ Updatable fields: `name`, `description`, `loginUrl`, `logoutUrl`, `allowedRedirectUris`, `allowedRedirectDomains`, `technology`.
89
+
90
+ ```bash
91
+ curl -X PATCH \
92
+ 'https://www.wixapis.com/oauth-app/v1/oauth-apps/<clientId>' \
93
+ -H 'Authorization: <AUTH>' \
94
+ -H 'wix-site-id: <metaSiteId>' \
95
+ -H 'Content-Type: application/json' \
96
+ -d '{
97
+ "oAuthApp": {
98
+ "allowedRedirectUris": ["https://example.com/callback", "https://example.com/auth"]
99
+ },
100
+ "mask": { "paths": ["allowedRedirectUris"] }
101
+ }'
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Key Fields
107
+
108
+ | Field | Notes |
109
+ |---|---|
110
+ | `id` | The OAuth `client_id`. Read-only. |
111
+ | `name` | Required on create. 2–256 chars. |
112
+ | `loginUrl` | External login redirect. Defaults to Wix login if omitted. |
113
+ | `logoutUrl` | Called when the user logs out at Wix. |
114
+ | `allowedRedirectUris` | Exact-match URIs for post-authentication redirect. Max 20. |
115
+ | `allowedRedirectDomains` | Domain-level allow-list for non-auth redirects (e.g. checkout). Max 20. |
116
+ | `applicationType` | `WEB_APP`, `MOBILE`, `OTHER` |
117
+
118
+ ---
119
+
120
+ ## Minting a Visitor Token
121
+
122
+ Once you have a `client_id`, frontends use it to mint an anonymous visitor token for buyer-facing API calls.
123
+
124
+ **Endpoint**: `POST https://www.wixapis.com/oauth2/token`
125
+
126
+ ```bash
127
+ # Initial anonymous mint
128
+ curl -X POST 'https://www.wixapis.com/oauth2/token' \
129
+ -H 'Content-Type: application/json' \
130
+ -d '{ "clientId": "<clientId>", "grantType": "anonymous" }'
131
+
132
+ # Response: { "access_token": "...", "refresh_token": "...", "expires_in": 14400 }
133
+ ```
134
+
135
+ ```bash
136
+ # Refresh (use this instead of re-minting)
137
+ curl -X POST 'https://www.wixapis.com/oauth2/token' \
138
+ -H 'Content-Type: application/json' \
139
+ -d '{ "clientId": "<clientId>", "grantType": "refresh_token", "refreshToken": "<refreshToken>" }'
140
+ ```
141
+
142
+ Use the `access_token` as the `Authorization` header on subsequent API calls.
143
+
144
+ > **Never re-mint anonymous on every load.** The visitor token is the cart/session identity — a fresh anonymous mint creates a new visitor and silently empties the cart. Persist the `refresh_token` and use it to renew.
145
+
146
+ ---
147
+
148
+ ## API Reference
149
+
150
+ - [OAuth Apps — Create](https://dev.wix.com/docs/api-reference/business-management/headless/oauth-apps/create-o-auth-app)
151
+ - [OAuth Apps — Get](https://dev.wix.com/docs/api-reference/business-management/headless/oauth-apps/get-o-auth-app)
152
+ - [OAuth Apps — Query](https://dev.wix.com/docs/api-reference/business-management/headless/oauth-apps/query-o-auth-apps)
153
+ - [OAuth Apps — Update](https://dev.wix.com/docs/api-reference/business-management/headless/oauth-apps/update-o-auth-app)
154
+ - [Retrieve Tokens — `/oauth2/token` contract, all grant types](https://dev.wix.com/docs/api-reference/business-management/headless/authentication/retrieve-tokens)
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: "Read Account or Site Context"
3
+ description: Probe a Wix site or account for full context in one call — installed apps by display name, locale, currency, timezone, and status. Account token + siteId targets one site; account token alone returns up to 10; site-scoped token alone returns the site it is scoped to.
4
+ ---
5
+ # Read Account or Site Context
6
+
7
+ Returns a site's name, URL, status, locale/region, and all installed apps with human-readable display names.
8
+
9
+ ---
10
+
11
+ ## Markdown endpoint (recommended)
12
+
13
+ **Endpoint**: `POST https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context/markdown`
14
+
15
+ Returns `{ "markdown": "..." }`.
16
+
17
+ ### Account token + siteId — one specific site
18
+
19
+ ```bash
20
+ curl -X POST \
21
+ 'https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context/markdown' \
22
+ -H 'Authorization: <AUTH>' \
23
+ -H 'Content-Type: application/json' \
24
+ -d '{"siteId": "<metaSiteId>"}'
25
+ ```
26
+
27
+ Response:
28
+
29
+ ```
30
+ ## 1. Acme Store
31
+
32
+ **ID**: `<metaSiteId>`
33
+ **URL**: [https://example.wixsite.com/acme](https://example.wixsite.com/acme)
34
+ **Status**: Published
35
+ **Editor Type**: Editorless
36
+ **Created**: Aug 14, 2026, 05:21 · **Updated**: Aug 17, 2026, 20:44
37
+ **Velo**: Enabled
38
+
39
+ ### Properties
40
+
41
+ **Locale & Region**
42
+ - Language: **en**
43
+ - Country: **US**
44
+ - Timezone: **America/New_York**
45
+ - Currency: **USD**
46
+
47
+ ### Apps
48
+
49
+ - **Wix Stores** (ID: `215238eb-22a5-4c36-9e7b-e7c08025e04e`) — Catalog app version: **V3**
50
+ - **Wix Bookings** (ID: `13d21c63-b5ec-5912-8397-c3a5ddb27a97`)
51
+ - **Wix Blog** (ID: `14bcded7-0066-7c35-14d7-466cb3f09103`)
52
+ ```
53
+
54
+ ### Without siteId
55
+
56
+ ```bash
57
+ curl -X POST \
58
+ 'https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context/markdown' \
59
+ -H 'Authorization: <AUTH>' \
60
+ -H 'Content-Type: application/json' \
61
+ -d '{}'
62
+ ```
63
+
64
+ - **Account token**: returns up to 10 sites. If the account has more: `_Showing 10 sites (more available)_` — call again with a specific `siteId`.
65
+ - **Site-scoped token** (e.g. the Wix connector in Base44): returns the one site the token is scoped to.
66
+
67
+ ---
68
+
69
+ ## JSON endpoint
70
+
71
+ **Endpoint**: `POST https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context`
72
+
73
+ Same request shape. `installedApps` contains raw `appId` UUIDs — extract only what you need:
74
+
75
+ ```javascript
76
+ const res = await fetch(
77
+ "https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context",
78
+ {
79
+ method: "POST",
80
+ headers: { Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json" },
81
+ body: JSON.stringify({ siteId: metaSiteId }),
82
+ }
83
+ );
84
+ const { sites } = await res.json();
85
+ const site = sites[0];
86
+
87
+ const KNOWN_APPS = {
88
+ stores: "215238eb-22a5-4c36-9e7b-e7c08025e04e",
89
+ bookings: "13d21c63-b5ec-5912-8397-c3a5ddb27a97",
90
+ blog: "14bcded7-0066-7c35-14d7-466cb3f09103",
91
+ events: "140603ad-af8d-84a5-2c80-a0f60cb47351",
92
+ pricingPlans: "1522827f-c56c-a5c9-2ac9-00f9e6ae12d3",
93
+ restaurants: "13e8d036-5516-6f75-e025-2aca3b5d7930",
94
+ };
95
+
96
+ const appById = Object.fromEntries(
97
+ (site.installedApps ?? []).map((a) => [a.appId, a])
98
+ );
99
+
100
+ const context = {
101
+ id: site.id,
102
+ name: site.displayName,
103
+ url: site.url,
104
+ currency: site.properties?.paymentCurrency,
105
+ locale: `${site.properties?.locale?.languageCode}-${site.properties?.locale?.country}`,
106
+ timezone: site.properties?.timeZone,
107
+ hasStores: !!appById[KNOWN_APPS.stores],
108
+ storesCatalogV: appById[KNOWN_APPS.stores]?.catalogVersion ?? null, // "V3" | "V1" | null
109
+ hasBookings: !!appById[KNOWN_APPS.bookings],
110
+ hasBlog: !!appById[KNOWN_APPS.blog],
111
+ hasEvents: !!appById[KNOWN_APPS.events],
112
+ hasPricingPlans: !!appById[KNOWN_APPS.pricingPlans],
113
+ hasRestaurants: !!appById[KNOWN_APPS.restaurants],
114
+ };
115
+ ```
116
+
117
+ ---
118
+
119
+ ## API Reference
120
+
121
+ - [Get Dynamic Context — markdown](https://dev.wix.com/docs/api-reference/tools/dynamic-site-context/get-dynamic-context-markdown)
122
+ - [Get Dynamic Context — JSON](https://dev.wix.com/docs/api-reference/tools/dynamic-site-context/get-dynamic-context)
123
+ - [Query Sites](https://dev.wix.com/docs/api-reference/account-level/sites/sites/query-sites) — for paginating or filtering the full site list
124
+ - [Get Installed Apps](https://dev.wix.com/docs/api-reference/business-management/app-installation/app-installation/get-installed-apps) — raw app instances with fields not in the context snapshot
125
+ - [Get Site Properties](https://dev.wix.com/docs/api-reference/business-management/site-properties/properties/get-site-properties) — full properties including business description, address, social links