@wix/agent-skills 1.29.0 → 1.31.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/agent-skills",
3
- "version": "1.29.0",
3
+ "version": "1.31.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": {
@@ -23,11 +23,13 @@ doesn't express — or once the site exists and the work turns to managing or ex
23
23
 
24
24
  - **Shipped code is the implementation.** Every vertical ships in the repository's
25
25
  `wix-headless-templates` skill (`skills/wix-headless-templates/<vertical>/`), not in this skill's
26
- folder: `node <SKILL_ROOT>/install/templates.mjs`
27
- fetches all of it once into `<SKILL_ROOT>/templates/` (a second) and prints the path; every
28
- script below fetches it itself when the folder is missing. The folder stays with the project
29
- (only the composed `project/` scaffolds are left out of its repository), so a later session
30
- reads the version the project was built from. Each vertical holds:
26
+ folder. `node <SKILL_ROOT>/install/templates.mjs` prints where that skill is: the sibling folder
27
+ `<SKILL_ROOT>/../wix-headless-templates/` when the install carried both skills (the cold start
28
+ does), else a one-time fetch into `<SKILL_ROOT>/templates/` (a second); every script below
29
+ resolves it the same way. **Every `templates/...` path in this document is relative to that
30
+ printed root** — there is no `templates/` folder inside this skill when the sibling exists.
31
+ The folder stays with the project (only the composed `project/` scaffolds are left out of its
32
+ repository), so a later session reads the version the project was built from. Each vertical holds:
31
33
  - `app/` — the framework-agnostic core (TypeScript): a data layer that returns **plain,
32
34
  serializable DTOs** (images resolved to https URLs, prices pre-formatted), React hooks, and
33
35
  routing-free headless components. Works in Astro islands, Vite SPAs, and Next.
@@ -251,9 +253,7 @@ only after an explicit yes, never automatically. Step 5 ends with the same self-
251
253
  INSTRUCTIONS and the shared floors — `templates/shared/DESIGN.md` +
252
254
  `templates/shared/CONTENT.md` — now (not earlier — their contracts matter only from this
253
255
  step on); the hook/DTO
254
- contracts are inlined there, so don't open the shipped files themselves. **Author your
255
- surfaces in as few messages as possible** — batch multiple Write calls in one message
256
- (components are independent files); don't pay a round-trip per file.
256
+ contracts are inlined there, so don't open the shipped files themselves.
257
257
  If the brief needs a core operation that shipped code does not cover, read
258
258
  `templates/shared/CUSTOM_OPERATIONS.md` before writing it. Use one documented path and
259
259
  implement it; do not reverse-engineer SDK internals.
@@ -284,7 +284,9 @@ only after an explicit yes, never automatically. Step 5 ends with the same self-
284
284
  that fix it: **Accept payments** `https://manage.wix.com/dashboard/<siteId>/wix-cashier/payments`
285
285
  (connect a payment method; "manual payments" is enough for free and pay-in-person flows) and
286
286
  **Upgrade the plan** `https://www.wix.com/upgrade/website?metaSiteId=<siteId>` (online payments
287
- need a premium plan). Both are the owner's steps, not a defect in the site. **Copy the live URL verbatim from the
287
+ need a premium plan). Both are the owner's steps, not a defect in the site. When the run started
288
+ from the owner's own pages, name what those pages promised that the released site does not do.
289
+ **Copy the live URL verbatim from the
288
290
  `wix release` output — never retype it from memory** (a mistyped subdomain hands the user
289
291
  a 404). Before you sign off, run the feedback self-check over the whole session
290
292
  (`guides/feedback.md`): anything that cost more turns than it should have, including what you
@@ -303,7 +305,7 @@ how to close such a run. A public site is still better served by managed Astro;
303
305
  close.
304
306
 
305
307
  Without a machine at all, or when the install, the CLI or the login is blocked where you are,
306
- read `<SKILL_ROOT>/guides/no-machine.md`: the same run, step by step, as the Wix API calls the
308
+ read `<SKILL_ROOT>/guides/api-run.md`: the same run, step by step, as the Wix API calls the
307
309
  scripts make and the files beside this skill that carry the contracts.
308
310
 
309
311
  ## Verticals
@@ -0,0 +1,123 @@
1
+ # The kit's run as Wix API calls
2
+
3
+ Read when the commands this skill is built on cannot run where you are, or stopped: no shell, no
4
+ file system, a sandbox that blocks the install, the CLI or the login, or a host that only talks to
5
+ Wix through the Wix MCP. It walks the run of SKILL.md step by step and names, for each, the Wix
6
+ API call the CLI or the script performs and the file beside this skill that carries the contract;
7
+ where a script can run where you are, it says so.
8
+
9
+ ## Where these skills are
10
+
11
+ This skill is one of a set, and the guide reads from three of them:
12
+
13
+ - `{SKILL_ROOT}` — this skill, `wix-headless-kit`: the run, its guides, the Verticals table.
14
+ - `{TEMPLATES}` — `wix-headless-templates`: the shipped, verified code per Wix Business Solution,
15
+ one folder each, with its `INSTRUCTIONS.md` (the contracts), `seed/` (the seed script and
16
+ `SEED.md`) and `rest/` (the data layer over plain `fetch`). Installed beside this skill, or
17
+ fetched to `{SKILL_ROOT}/templates/`.
18
+ - `{MANAGE}` — `wix-manage`: REST recipes to configure and manage a site's business solutions, one
19
+ recipe per operation with the exact endpoint and payload; its `SKILL.md` is the index.
20
+ - `{DOCS}` — `wix-docs`: how to look up the Wix API and SDK documentation and confirm a method's
21
+ exact shape before writing a call.
22
+
23
+ Installed, they sit beside each other under `.agents/skills/`. Online, they are published alongside
24
+ each other under the same names, each with a manifest of its files, and in the `wix/skills`
25
+ repository on GitHub under `skills/{skill}/`; a sandbox that reaches GitHub has the whole set on
26
+ disk from a clone.
27
+
28
+ What such a run does not produce: the Astro build and its release. Those need a machine with the
29
+ CLI. Everything else the kit does to a site, it does through calls you can make.
30
+
31
+ ## 0. Identity
32
+
33
+ Every call below runs as the site owner, with whatever identity your host gives you: the Wix
34
+ MCP's `ExecuteWixAPI` carries the user's login; an API key from the user's account goes in the
35
+ `Authorization` header of any call, as `{MANAGE}/SKILL.md` describes; a site token from the Wix CLI
36
+ works the same way when the user runs the CLI for you. The site's OAuth app (`client_id`) mints
37
+ visitor tokens only, which cover what a visitor may see and nothing here.
38
+
39
+ ## 1. The brief → the solutions
40
+
41
+ Unchanged from SKILL.md step 2 and its Verticals table: the brief names the business, the table
42
+ names the solutions it needs. Read each solution's `{TEMPLATES}/{solution}/INSTRUCTIONS.md` for
43
+ what it covers and `{TEMPLATES}/{solution}/seed/SEED.md` for what a seeded site holds.
44
+
45
+ ## 2. The site
46
+
47
+ The CLI's `npm create @wix/new` is one call: `POST /headless-business-setup/v1/headless-business/provision`,
48
+ with `origin: agent-<your-id>`, a name, and the solutions to install as `seedOptions`. The recipe
49
+ is `{MANAGE}/references/sites/create-headless-site.md`; it returns the `metaSiteId` and the
50
+ site's OAuth client `appId`. Do not create a site any other way: a project from Create Project or
51
+ a template is neither headless nor publishable, and a later run with a machine cannot attach to it.
52
+
53
+ A site that already exists (the brief names it) is read first, never seeded unasked: SKILL.md
54
+ step 2 and `{SKILL_ROOT}/guides/existing-site.md` apply as written.
55
+
56
+ ## 3. The apps
57
+
58
+ A solution the provision call did not install, or a capability's app (Members Area, Forms,
59
+ Restaurants, Donations, FAQ), goes on with the Apps Installer:
60
+ `{MANAGE}/references/app-installation/install-wix-apps.md`. The app ids are in each
61
+ `seed-{solution}.mjs`, which installs them before seeding.
62
+
63
+ ## 4. The seed
64
+
65
+ `seed-{solution}.mjs` is a sequence of REST calls, and `SEED.md` is its contract: the plan shape
66
+ (what to create, how many, which images), the order the entities need, and the traps the script
67
+ encodes (a Bookings service needs a category to be visible and takes resource ids, not staff ids;
68
+ a Forms field is registered by its `validation` block; a product's choice photos are linked after
69
+ the gallery holds them). Read `SEED.md`, read the script for any call `SEED.md` only names, and make the same
70
+ calls through `{MANAGE}`'s recipe for each (services, products, posts, events, collections). Keep
71
+ the script's rules: create, never delete, and report what the site already held. Image prompts
72
+ need the Media Manager; without it, products and services stay text-only, say so.
73
+
74
+ ## 5. The frontend
75
+
76
+ The Astro pages cannot be released here: that is a run with a machine and a CLI login, which
77
+ attaches to this site (`guides/existing-site.md`) rather than making a new one. What ships from here
78
+ is static files, dropped onto the site from step 2 through
79
+ `{MANAGE}/references/sites/upload-static-site.md`. Which files depends on whether the compose can
80
+ run.
81
+
82
+ **When the compose can run** (the skills on disk and Node), the frontend is the kit's own shipped code. The compose
83
+ `{SKILL_ROOT}/install/deploy.mjs {solution} --stack static --out site --client-id {appId}` fetches the
84
+ templates and writes the solution's REST data layer and stores to `site/js/wix/` as plain ES modules
85
+ (`guides/reference-mode.md`, the static site): the transport, the cores, the state machines, verified,
86
+ with the `.ts` beside each `.js` for reading. You write the pages and the rendering on those stores,
87
+ imported relative to `site/` in a `<script type="module">`, and nothing of the data layer. The drop
88
+ takes the complete file set in one call and a response has a hard size limit; the recipe's "Change it
89
+ later" section downloads what the site serves, so a later drop adds files to a live set without
90
+ resending what is already there.
91
+
92
+ **When it cannot**, a page that loads the Wix SDK from a package CDN and talks to the site as a
93
+ visitor. A few files at most, each written in full before it is dropped; the same size limit and
94
+ the same way to add files to a live set apply. The
95
+ SDK comes from a pinned package URL, `https://esm.sh/@wix/sdk@{version}` and the solution's package
96
+ (`@wix/bookings`, `@wix/stores`, `@wix/blog`, …); the client is
97
+ `createClient({ modules: { … }, auth: OAuthStrategy({ clientId }) })` with the `appId` the provision
98
+ call returned, and the SDK mints and refreshes the visitor token itself. Markup, a render function
99
+ per state, the event handlers: that is what you write. Keep what the page shows to what the site
100
+ holds; nothing invented, as in SKILL.md step 4.
101
+
102
+ **The calls**, on that second path, take their shape from the kit's own transport for the solution,
103
+ `{TEMPLATES}/{solution}/app/wix/{solution}/*.ts` (`services.ts`, `booking.ts`, `catalog.ts`, …,
104
+ with `{TEMPLATES}/shared/app/wix/sdk.ts` for the client wiring): those files call the same SDK
105
+ modules the page imports, and they are verified. Copy the form of the call, not the file. The
106
+ cores beside them (`*-core.ts`) hold the rules the page needs and nothing else does: which fields
107
+ to read, how a price or a duration is formatted, which slot is bookable, how an id is read.
108
+
109
+ **A call those files don't cover** is confirmed before it is written, the way `{DOCS}` describes:
110
+ the method's SDK page, and when the page and the package disagree, the package's own type
111
+ declarations (the `@wix/auto_sdk_{solution}_<module>` package the solution package depends on,
112
+ its `index.d.ts`) are the truth. Two shapes that recur, as examples of what the types settle and
113
+ the kit's files already encode: SDK query methods return a query builder finished with `.find()`;
114
+ and an entity's id arrives as `_id` on some objects and `id` on others (the kit reads both,
115
+ `rawId`). Dates travel as local wall-clock strings in the business time zone. A page cannot be run
116
+ here, so a wrong shape fails silently in the browser; the file beside the skill is the check that is
117
+ available.
118
+
119
+ ## 6. Closing
120
+
121
+ SKILL.md step 5's closing, with two additions: the site id, so a run with a machine attaches to this
122
+ site (`guides/existing-site.md`) instead of making a new one; and, when files were dropped, that a
123
+ change re-drops the whole set.
@@ -3,6 +3,6 @@
3
3
  "@wix/create-new": "0.0.124",
4
4
  "typescript": "5.8.3",
5
5
  "templates": {
6
- "ref": "v1.29.0"
6
+ "ref": "v1.31.0"
7
7
  }
8
8
  }
@@ -151,10 +151,13 @@ export async function importImage(ctx, url, displayName = "image.png") {
151
151
  * THE seed entry point. Resolves a batch of image specs to Wix Media files in ONE parallel
152
152
  * wave. Each spec: { path } (LOCAL file — the user's own asset, uploaded) OR { url }
153
153
  * (verified external URL — imported) OR { prompt } (generated, ~1 credit) — plus optional
154
- * displayName, width, height. Returns an array aligned with the input: { id, url } per
155
- * success, null per failure or empty spec. Never throws.
154
+ * displayName, width, height. Returns an array aligned with the input: { file, error } per
155
+ * spec — `file` is { id, url } on success and null otherwise; `error` is the reason it is null
156
+ * (the thrown message, "empty spec", or "timed out"). Never throws. Every failure is also
157
+ * printed to stderr, so a seed log names the image and the reason even when the seed's
158
+ * own report does not.
156
159
  */
157
- export async function resolveItemImages(ctx, specs, { perImageBudgetMs = 120_000 } = {}) {
160
+ export async function resolveItemImagesDetailed(ctx, specs, { perImageBudgetMs = 120_000 } = {}) {
158
161
  // unref: the budget timer must never keep the seed process alive after the work is done —
159
162
  // a lingering timer delays the seed's exit (and the run's .seed-exit marker) by the budget.
160
163
  const deadline = new Promise((r) => {
@@ -179,5 +182,22 @@ export async function resolveItemImages(ctx, specs, { perImageBudgetMs = 120_000
179
182
  return Promise.race([resolve, deadline]);
180
183
  }),
181
184
  );
182
- return results.map((r) => (r.status === "fulfilled" ? r.value : null));
185
+ return results.map((r, i) => {
186
+ const spec = specs?.[i] ?? {};
187
+ const label = spec.displayName ?? spec.path ?? spec.url ?? (spec.prompt ? "(prompt)" : "(empty)");
188
+ if (r.status === "fulfilled") {
189
+ if (r.value) return { file: r.value, error: null };
190
+ const error = !spec.path && !spec.url && !spec.prompt ? "empty spec" : `timed out after ${perImageBudgetMs} ms`;
191
+ if (error !== "empty spec") console.error(`image ${label}: ${error}`);
192
+ return { file: null, error };
193
+ }
194
+ const error = r.reason?.message ?? String(r.reason);
195
+ console.error(`image ${label}: ${error.slice(0, 200)}`);
196
+ return { file: null, error };
197
+ });
198
+ }
199
+
200
+ /** The plain array of { id, url } | null the seeds consume today; failures are still printed. */
201
+ export async function resolveItemImages(ctx, specs, opts) {
202
+ return (await resolveItemImagesDetailed(ctx, specs, opts)).map((r) => r.file);
183
203
  }
@@ -29,7 +29,7 @@
29
29
  import { setSiteCurrency } from "../../shared/seed/site.mjs";
30
30
  import { basename } from "node:path";
31
31
  import { readFileSync } from "node:fs";
32
- import { resolveItemImages } from "../../shared/seed/images.mjs";
32
+ import { resolveItemImages, resolveItemImagesDetailed } from "../../shared/seed/images.mjs";
33
33
  import { seedSiteId } from "../../shared/seed/site-context.mjs";
34
34
  import { wixToken } from "../../shared/seed/wix-cli.mjs";
35
35
 
@@ -686,7 +686,7 @@ export async function setupStore(ctx, { products = [], categories = {}, category
686
686
  const planNames = new Set(products.map((p) => p.name));
687
687
  let all = [];
688
688
  try { all = await readAllProducts(ctx); } catch (e) { console.error(`catalog read failed (skipping the pre-existing check): ${String(e.message).slice(0, 120)}`); }
689
- const preexisting = all.filter((p) => !planNames.has(p.name));
689
+ let preexisting = all.filter((p) => !planNames.has(p.name));
690
690
 
691
691
  // Idempotent by name: an errored bulk create (429/5xx) may still have applied server-side,
692
692
  // and SKILL.md tells the agent to re-run a failed seed — creating only the names that don't
@@ -739,12 +739,13 @@ export async function setupStore(ctx, { products = [], categories = {}, category
739
739
  .map((c) => ({
740
740
  optionName: o.name,
741
741
  choiceName: c.name,
742
+ productName: pl.name,
742
743
  altText: c.altText ?? `${pl.name} — ${c.name}`,
743
744
  spec: { url: c.imageUrl, path: c.imagePath, prompt: c.imagePrompt, displayName: `${withNames[i].slug || "product"}-${String(c.name).toLowerCase().replace(/[^a-z0-9]+/g, "-")}.png` },
744
745
  })),
745
746
  ));
746
747
  const flatChoiceSpecs = choiceSpecs.flat();
747
- const files = await resolveItemImages(ctx, [
748
+ const resolved = await resolveItemImagesDetailed(ctx, [
748
749
  ...withNames.map((p, i) => ({
749
750
  url: products[i]?.imageUrl,
750
751
  path: products[i]?.imagePath,
@@ -753,7 +754,9 @@ export async function setupStore(ctx, { products = [], categories = {}, category
753
754
  })),
754
755
  ...flatChoiceSpecs.map((c) => c.spec),
755
756
  ]);
757
+ const files = resolved.map((r) => r.file);
756
758
  const choiceFiles = files.slice(withNames.length);
759
+ const choiceResolved = resolved.slice(withNames.length);
757
760
  let cursor = 0;
758
761
  const choiceLinks = choiceSpecs.map((specs) =>
759
762
  specs.map((c) => ({ ...c, file: choiceFiles[cursor++] })).filter((c) => c.file));
@@ -774,6 +777,15 @@ export async function setupStore(ctx, { products = [], categories = {}, category
774
777
  // the same plan reuses the products and attaches again.
775
778
  let imagesAttached = 0;
776
779
  const imageFailures = [];
780
+ // A product whose image never resolved (a bad path, an unsupported file type, a refused
781
+ // prompt, a timeout) is not in imageItems at all, so the attach step below never sees it:
782
+ // it is reported here with the resolver's reason, or it ships text-only in silence.
783
+ withNames.forEach((p, i) => {
784
+ const src = products[i] ?? {};
785
+ if ((src.imageUrl || src.imagePath || src.imagePrompt) && !files[i]) {
786
+ imageFailures.push({ name: p.name, error: resolved[i]?.error ?? "image did not resolve" });
787
+ }
788
+ });
777
789
  const nameOf = (id) => withNames.find((p) => p.id === id)?.name;
778
790
  try {
779
791
  if (imageItems.length) {
@@ -788,6 +800,9 @@ export async function setupStore(ctx, { products = [], categories = {}, category
788
800
  // Pass 3 — link each choice's image to its choice, by the gallery item's id.
789
801
  let choiceImagesLinked = 0;
790
802
  const choiceImageFailures = [];
803
+ flatChoiceSpecs.forEach((c, j) => {
804
+ if (!choiceFiles[j]) choiceImageFailures.push({ name: c.productName, choice: c.choiceName, error: choiceResolved[j]?.error ?? "image did not resolve" });
805
+ });
791
806
  for (const [i, p] of withNames.entries()) {
792
807
  const links = choiceLinks[i];
793
808
  if (!links.length || !p.id || !imagesAttached) continue;
@@ -800,6 +815,17 @@ export async function setupStore(ctx, { products = [], categories = {}, category
800
815
  }
801
816
  }
802
817
 
818
+ // The pre-existing list is read again now: on a fresh site the Stores app was installed moments
819
+ // before the first read, and Wix creates its sample catalog asynchronously after the install, so
820
+ // that read often came back empty and the closing message said nothing about a dozen samples the
821
+ // live shop lists. The early read still serves the idempotency check above; this one serves the report.
822
+ try {
823
+ const after = await readAllProducts(ctx);
824
+ preexisting = after.filter((p) => !planNames.has(p.name));
825
+ } catch (e) {
826
+ console.error(`catalog re-read failed (reporting the pre-existing list from the first read): ${String(e.message).slice(0, 120)}`);
827
+ }
828
+
803
829
  // failures is part of the result, not an exception: a partial seed still leaves a usable
804
830
  // store, and the agent needs the names to report rather than silently shipping a short
805
831
  // catalog. Re-run the seed to retry them — existing names are skipped, not duplicated.
@@ -112,7 +112,13 @@ fails. You can finish without waiting for those images or replacing their placeh
112
112
 
113
113
  **Never paste a Wix dashboard link or path.**
114
114
 
115
- **Before writing your final text response, make one handoff call** — `search_base44_docs(query="how do I manage my store's products, orders and inventory?", prefer_dashboard=true)`. Use its handoff guidance, note that the seeded catalog is mock data they can edit, replace or delete, and state any requested workflows that remain unfinished and what is needed to complete them.
115
+ **Before writing your final text response, make one handoff call** — `search_base44_docs(query="how do I manage my store's products, orders, inventory and payments?", prefer_dashboard=true)`. Use its handoff guidance, note that the seeded catalog is mock data they can edit, replace or delete, and state any requested workflows that remain unfinished and what is needed to complete them.
116
+
117
+ **A payment ask is a store ask.** The store carries its own checkout, in every region, so
118
+ nothing separate connects payments and no payment provider is installed alongside it — send
119
+ the user to the same dashboard page the handoff call names. A note that Base44 Payments /
120
+ Wix Payments is unavailable in their region is about a provider installed into the app, and
121
+ says nothing about their store's checkout.
116
122
 
117
123
  ## Additional Wix functionality
118
124
 
@@ -106,7 +106,13 @@ fails. You can finish without waiting for those images or replacing their placeh
106
106
 
107
107
  **Never paste a Wix dashboard link or path.**
108
108
 
109
- **Before writing your final text response, make one handoff call** — `search_base44_docs(query="how do I manage my store's products, orders and inventory?", prefer_dashboard=true)`. Use its handoff guidance, note that the seeded catalog is mock data they can edit, replace or delete, and state any requested workflows that remain unfinished and what is needed to complete them.
109
+ **Before writing your final text response, make one handoff call** — `search_base44_docs(query="how do I manage my store's products, orders, inventory and payments?", prefer_dashboard=true)`. Use its handoff guidance, note that the seeded catalog is mock data they can edit, replace or delete, and state any requested workflows that remain unfinished and what is needed to complete them.
110
+
111
+ **A payment ask is a store ask.** The store carries its own checkout, in every region, so
112
+ nothing separate connects payments and no payment provider is installed alongside it — send
113
+ the user to the same dashboard page the handoff call names. A note that Base44 Payments /
114
+ Wix Payments is unavailable in their region is about a provider installed into the app, and
115
+ says nothing about their store's checkout.
110
116
 
111
117
  ## Additional Wix functionality
112
118
 
@@ -72,7 +72,13 @@ fails. You can finish without waiting for those images or replacing their placeh
72
72
 
73
73
  **Never paste a Wix dashboard link or path.**
74
74
 
75
- **Before writing your final text response, make one handoff call** — `search_base44_docs(query="how do I manage my store's products, orders and inventory?", prefer_dashboard=true)`. Use its handoff guidance, state any requested workflows that remain unfinished and what is needed to complete them.
75
+ **Before writing your final text response, make one handoff call** — `search_base44_docs(query="how do I manage my store's products, orders, inventory and payments?", prefer_dashboard=true)`. Use its handoff guidance, state any requested workflows that remain unfinished and what is needed to complete them.
76
+
77
+ **A payment ask is a store ask.** The store carries its own checkout, in every region, so
78
+ nothing separate connects payments and no payment provider is installed alongside it — send
79
+ the user to the same dashboard page the handoff call names. A note that Base44 Payments /
80
+ Wix Payments is unavailable in their region is about a provider installed into the app, and
81
+ says nothing about their store's checkout.
76
82
 
77
83
  ## Additional Wix functionality
78
84
 
@@ -1,115 +0,0 @@
1
- # No machine: the kit's run through the Wix APIs
2
-
3
- Read when you cannot run the commands this skill is built on: no shell, no file system, no Node, a
4
- sandbox that blocks the install, the CLI or the login, or a host that only talks to Wix through
5
- the Wix MCP. Nothing in this guide installs, downloads or runs anything. It walks the run of
6
- SKILL.md step by step and names, for each, the Wix API call the CLI or the script performs, and
7
- the file beside this skill that carries the contract.
8
-
9
- ## Where these skills are
10
-
11
- This skill is one of a set, and the guide reads from three of them:
12
-
13
- - `<SKILL_ROOT>` — this skill, `wix-headless-kit`: the run, its guides, the Verticals table.
14
- - `<TEMPLATES>` — `wix-headless-templates`: the shipped, verified code per Wix Business Solution,
15
- one folder each, with its `INSTRUCTIONS.md` (the contracts), `seed/` (the seed script and
16
- `SEED.md`) and `rest/` (the data layer over plain `fetch`). Installed beside this skill, or
17
- fetched to `<SKILL_ROOT>/templates/`.
18
- - `<MANAGE>` — `wix-manage`: REST recipes to configure and manage a site's business solutions, one
19
- recipe per operation with the exact endpoint and payload; its `SKILL.md` is the index.
20
- - `<DOCS>` — `wix-docs`: how to look up the Wix API and SDK documentation and confirm a method's
21
- exact shape before writing a call.
22
-
23
- They install together and sit beside each other. When you are reading this skill online rather
24
- than from an install, the others are published alongside it, by those names, and each skill's
25
- manifest lists its files. Read each file in full: a fetch tool that summarizes drops the exact
26
- calls and shapes; a tool that returns the file's text, or one that runs code and can fetch a URL,
27
- does not.
28
-
29
- Two things such a run does not produce, and never claims: a frontend built from the shipped `app/`
30
- code (that needs a build), and a release of one. Everything else the kit does to a site, it does
31
- through calls you can make.
32
-
33
- ## 0. Identity
34
-
35
- Every call below runs as the site owner, with whatever identity your host gives you: the Wix
36
- MCP's `ExecuteWixAPI` carries the user's login; an API key from the user's account goes in the
37
- `Authorization` header of any call, as `<MANAGE>/SKILL.md` describes; a site token from the Wix CLI
38
- works the same way when the user runs the CLI for you. The site's OAuth app (`client_id`) mints
39
- visitor tokens only, which cover what a visitor may see and nothing here.
40
-
41
- ## 1. The brief → the solutions
42
-
43
- Unchanged from SKILL.md step 2 and its Verticals table: the brief names the business, the table
44
- names the solutions it needs. Read each solution's `<TEMPLATES>/<solution>/INSTRUCTIONS.md` for
45
- what it covers and `<TEMPLATES>/<solution>/seed/SEED.md` for what a seeded site holds.
46
-
47
- ## 2. The site
48
-
49
- The CLI's `npm create @wix/new` is one call: `POST /headless-business-setup/v1/headless-business/provision`,
50
- with `origin: agent-<your-id>`, a name, and the solutions to install as `seedOptions`. The recipe
51
- is `<MANAGE>/references/sites/create-headless-site.md`; it returns the `metaSiteId` and the
52
- site's OAuth client `appId`. Do not create a site any other way: a project from Create Project or
53
- a template is neither headless nor publishable, and a later run with a machine cannot attach to it.
54
-
55
- A site that already exists (the brief names it) is read first, never seeded unasked: SKILL.md
56
- step 2 and `<SKILL_ROOT>/guides/existing-site.md` apply as written.
57
-
58
- ## 3. The apps
59
-
60
- A solution the provision call did not install, or a capability's app (Members Area, Forms,
61
- Restaurants, Donations, FAQ), goes on with the Apps Installer:
62
- `<MANAGE>/references/app-installation/install-wix-apps.md`. The app ids are in each
63
- `seed-<solution>.mjs`, which installs them before seeding.
64
-
65
- ## 4. The seed
66
-
67
- `seed-<solution>.mjs` is a sequence of REST calls, and `SEED.md` is its contract: the plan shape
68
- (what to create, how many, which images), the order the entities need, and the traps the script
69
- encodes (a Bookings service needs a category to be visible and takes resource ids, not staff ids;
70
- a Forms field is registered by its `validation` block; a product's choice photos are linked after
71
- the gallery holds them). Read `SEED.md`, read the script for any call `SEED.md` only names, and make the same
72
- calls through `<MANAGE>`'s recipe for each (services, products, posts, events, collections). Keep
73
- the script's rules: create, never delete, and report what the site already held. Image prompts
74
- need the Media Manager; without it, products and services stay text-only, say so.
75
-
76
- ## 5. The frontend
77
-
78
- The shipped `app/` code cannot be built here, and the Astro pages cannot be released. A page can
79
- still be shipped: one self-contained `index.html` that loads the Wix SDK from a package CDN and
80
- talks to the site as a visitor, dropped onto the site from step 2 through
81
- `<MANAGE>/references/sites/upload-static-site.md`. The kit's own frontend for this site is a run
82
- with a machine, which attaches to this site (`guides/existing-site.md`) rather than making a new one.
83
-
84
- **The page.** One file, a few hundred lines, written in full before the first drop: the drop takes
85
- the complete file set in one call, and a response has a hard size limit, so there is no second
86
- pass. The SDK comes from a pinned package URL, `https://esm.sh/@wix/sdk@<version>` and the
87
- solution's package (`@wix/bookings`, `@wix/stores`, `@wix/blog`, …); the client is
88
- `createClient({ modules: { … }, auth: OAuthStrategy({ clientId }) })` with the `appId` the provision
89
- call returned, and the SDK mints and refreshes the visitor token itself. Markup, a render function
90
- per state, the event handlers: that is what you write. Keep what the page shows to what the site
91
- holds; nothing invented, as in SKILL.md step 4.
92
-
93
- **The calls.** Take every SDK call's shape from the kit's own transport for the solution,
94
- `<TEMPLATES>/<solution>/app/wix/<solution>/*.ts` (`services.ts`, `booking.ts`, `catalog.ts`, …,
95
- with `<TEMPLATES>/shared/app/wix/sdk.ts` for the client wiring): those files call the same SDK
96
- modules the page imports, and they are verified. Copy the form of the call, not the file. The
97
- cores beside them (`*-core.ts`) hold the rules the page needs and nothing else does: which fields
98
- to read, how a price or a duration is formatted, which slot is bookable, how an id is read.
99
-
100
- **A call those files don't cover** is confirmed before it is written, the way `<DOCS>` describes:
101
- the method's SDK page, and when the page and the package disagree, the package's own type
102
- declarations (the `@wix/auto_sdk_<solution>_<module>` package the solution package depends on,
103
- its `index.d.ts`) are the truth. Two shapes that recur, as examples of what the types settle and
104
- the kit's files already encode: SDK query methods return a query builder finished with `.find()`;
105
- and an entity's id arrives as `_id` on some objects and `id` on others (the kit reads both,
106
- `rawId`). Dates travel as local
107
- wall-clock strings in the business time zone. A page cannot be run here, so a wrong shape fails
108
- silently in the browser; the file beside the skill is the check that is available.
109
-
110
- ## 6. Closing
111
-
112
- As in SKILL.md step 5, minus the live URL when nothing was released: what exists on the site, by
113
- name; the dashboard link `https://manage.wix.com/dashboard/<metaSiteId>` and each solution's own
114
- pages from its INSTRUCTIONS.md table; what is placeholder; payments, when the site takes money;
115
- and what this run could not do, with the site id, so a run with a machine continues here.