@wix/agent-skills 1.19.1 → 1.20.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 (99) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +1 -1
  3. package/skills/wix-app/references/SERVICE_PLUGIN.md +14 -1
  4. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +7 -2
  5. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +53 -28
  6. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +17 -4
  7. package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +71 -31
  8. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +3 -4
  9. package/skills/wix-app/references/service-plugin/ADDITIONAL-FEES.md +4 -0
  10. package/skills/wix-app/references/service-plugin/AVAILABILITY-TIME-SLOTS-CONFIGURATION.md +118 -0
  11. package/skills/wix-app/references/service-plugin/BOOKING-POLICY.md +65 -0
  12. package/skills/wix-app/references/service-plugin/BOOKINGS-PRICING.md +71 -0
  13. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +11 -3
  14. package/skills/wix-app/references/service-plugin/BOOKINGS-VALIDATION.md +137 -0
  15. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +23 -16
  16. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
  17. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +4 -2
  18. package/skills/wix-app/references/service-plugin/REALTIME-PERMISSIONS.md +45 -0
  19. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +15 -0
  20. package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +4 -0
  21. package/skills/wix-app/references/service-plugin/VALIDATIONS.md +4 -0
  22. package/skills/wix-base44-connector/SKILL.md +46 -24
  23. package/skills/wix-headless/SKILL.md +1 -0
  24. package/skills/wix-headless/references/CAPABILITIES.md +7 -2
  25. package/skills/wix-headless/references/SDK_HANDOFF.md +2 -1
  26. package/skills/wix-headless/references/inline-recipes/experience-store.md +49 -0
  27. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +431 -115
  28. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +1 -1
  29. package/skills/wix-headless/references/managed/CREATE.md +5 -0
  30. package/skills/wix-headless/references/managed/DEPLOYMENT.md +8 -8
  31. package/skills/wix-headless-fast/install/fast-path.mjs +3 -1
  32. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +13 -0
  33. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +227 -56
  34. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +37 -3
  35. package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +266 -0
  36. package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +165 -0
  37. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +48 -15
  38. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +129 -11
  39. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +36 -6
  40. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +190 -24
  41. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +62 -4
  42. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +21 -2
  43. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +5 -1
  44. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +59 -6
  45. package/skills/wix-manage/SKILL.md +8 -5
  46. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +4 -1
  47. package/skills/wix-manage/references/bookings/create-appointment-service.md +3 -1
  48. package/skills/wix-manage/references/bookings/create-class-service.md +3 -1
  49. package/skills/wix-manage/references/bookings/create-course-service.md +4 -2
  50. package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +68 -3
  51. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-seasonal-promotion.md +1 -1
  52. package/skills/wix-manage/references/events/create-wix-event.md +46 -0
  53. package/skills/wix-manage/references/events/manage-wix-events.md +51 -1
  54. package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +6 -6
  55. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +108 -14
  56. package/skills/wix-manage/references/seo/manage-content-plan.md +1 -1
  57. package/skills/wix-manage/references/seo/manage-seo-suggestions.md +351 -0
  58. package/skills/wix-manage/references/sites/upload-static-site.md +264 -34
  59. package/skills/wix-vibe-headless/install/deploy.cjs +33 -2
  60. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +1 -1
  61. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +13 -4
  62. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +1 -1
  63. package/skills/wix-vibe-headless/platforms/base44.md +19 -4
  64. package/skills/wix-vibe-headless/platforms/generic.md +6 -0
  65. package/skills/wix-vibe-headless/references/_shared/nav/nav.tanstack.js +30 -0
  66. package/skills/wix-vibe-headless/references/_shared/routing.md +86 -0
  67. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +44 -0
  68. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +1 -1
  69. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +1 -1
  70. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +1 -1
  71. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +1 -1
  72. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +1 -1
  73. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +42 -0
  74. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +1 -1
  75. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +1 -1
  76. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +42 -0
  77. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +1 -1
  78. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +1 -1
  79. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +42 -0
  80. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +1 -1
  81. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +1 -1
  82. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +1 -1
  83. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +43 -0
  84. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +1 -1
  85. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +1 -1
  86. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +1 -1
  87. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +1 -1
  88. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +43 -0
  89. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +1 -1
  90. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +1 -1
  91. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +36 -0
  92. package/skills/wix-vibe-headless/references/shared/app/lib/nav.js +9 -0
  93. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +110 -27
  94. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +32 -14
  95. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +14 -3
  96. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +47 -35
  97. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +77 -30
  98. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +31 -2
  99. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +31 -6
@@ -1,53 +1,283 @@
1
1
  ---
2
2
  name: "Upload a Website or HTML Files"
3
- description: Get a user's ready-made website live on Wix when they already have the site files — an index.html, a zip, or a static build exported from an AI builder or any other tool — by sending them to the Wix Headless drop page, where they upload the files and instantly get a live hosted site they can claim into their account. Use whenever the user wants to upload, publish, or host their own HTML/CSS/JS files as a NEW site. Not for migrating a live store/site from another platform by URL or from CSV exports (use Site Import), not for adding HTML or custom code into an existing Wix site, and not for uploading images or documents to a site's media files.
3
+ description: Publish a user's ready-made website — an index.html, a static build, or a zip exported from an AI builder or any other tool — as a new live Wix site. Covers both ways to get there — handing the user the Wix Headless drop page, and calling the Wix Headless instant-site REST API yourself when you can reach the files and make outbound HTTPS requests. When you also hold the user's identity, covers putting the published site straight into their Wix account and reading back its final live URL. Use whenever the user wants to upload, publish, deploy, or host their own HTML/CSS/JS as a NEW site, including files generated for them earlier in the conversation, or to update a site already published this way (iterate on the same site instead of creating another). Not for migrating a live store/site from another platform by URL or from CSV exports (use Site Import), not for adding HTML or custom code into an existing Wix site, and not for uploading images or documents to a site's media files.
4
4
  ---
5
5
 
6
6
  # Upload a Website or HTML Files
7
7
 
8
- The user already has a finished website as files — hand-written HTML, a zip
9
- export, or the output of an AI site builder — and wants it live on Wix as a
10
- new site. There is no API call to make. Send them to the upload page and
11
- explain the flow:
8
+ The user has a finished website as files — hand-written HTML, a static build, a
9
+ zip, or the output of an AI site builder — and wants it live on Wix as a new
10
+ site. There are two ways to get there.
12
11
 
12
+ ## The two paths
13
+
14
+ **[Path A — hand the user the drop page](#path-a--hand-the-user-the-drop-page).**
15
+ One URL; the user uploads in the browser and gets a live site. This works for
16
+ **any** agent and any user — it's the default. Reach for it whenever you can't
17
+ clearly do Path B.
18
+
19
+ **[Path B — publish the files yourself](#path-b--publish-the-files-yourself).**
20
+ Three calls put the site live without the user touching a browser. Available only
21
+ when **both** hold: you can read the file bytes (you generated them here, or
22
+ they're reachable from where you run), **and** you can do a `multipart/form-data`
23
+ file upload from a shell (`curl` or equivalent). Reaching APIs *only* through the
24
+ Wix API-call/execute-API tools does **not** count — they can't upload a local
25
+ file.
26
+
27
+ Prefer Path B when you can genuinely do it — the user gets a live site without
28
+ uploading anything themselves. Otherwise, and by default, take Path A. Decide
29
+ honestly: if you can't read the bytes or can't upload from a shell, hand over the
30
+ drop page rather than attempting Path B and reporting an upload you couldn't
31
+ perform.
32
+
33
+ ## Path A — hand the user the drop page
34
+
35
+ Send the user here:
36
+
37
+ ```
38
+ https://www.wix.com/headless/drop?utm_campaign=mcp&agent=<your-agent-id>
39
+ ```
40
+
41
+ **Keep `utm_campaign=mcp`** (the drop-flow referral tag — don't change it) **and set
42
+ `agent` to your own identifier** — the coding agent or tool you are (e.g.
43
+ `claude-code`, `cursor`, `codex-cli`, `windsurf`, `github-copilot`, or your product's
44
+ name). Hand the URL with `agent` filled in and both params intact. There the user drags
45
+ in their files (no login), Wix hosts them immediately on a live URL, and a banner
46
+ offers to sign in and keep the site. Tell them the requirements from
47
+ [What the upload accepts](#what-the-upload-accepts-and-how-it-fails) so it doesn't
48
+ fail on the first try.
49
+
50
+ ## Path B — publish the files yourself
51
+
52
+ > **Run every call from your shell with `curl` — not the Wix API-call/execute-API
53
+ > tools.** The upload (step 2) and the download in
54
+ > [Add a backend](#keep-building-add-a-backend-when-you-need-one) move a **file**
55
+ > to or from disk; those tools proxy JSON and can't (hand-building a multipart
56
+ > body inline silently drops every image and font). Create and release are plain
57
+ > JSON and would work through anything, but the upload needs a real file client
58
+ > anyway, so keep it all in the shell. **None of steps 1–3 (or the download) need
59
+ > auth — they're anonymous.** Only [claim](#4-put-the-site-in-the-users-account)
60
+ > needs the user's identity.
61
+
62
+ ```
63
+ Base URL: https://www.wixapis.com/headless-business-setup
64
+ ```
65
+
66
+ Generate `anonymousId` yourself — any UUID, **once per site, not once per
67
+ request** — and reuse it (with the returned `metaSiteId`) for every call for that
68
+ site, including later changes ([Iterate](#iterate-while-anonymous-dont-create-a-new-site)).
69
+ **Finish within one hour of step 1**: after that the record expires and every
70
+ later step, claim included, returns `404`.
71
+
72
+ ### 1. Create the site
73
+
74
+ ```bash
75
+ curl -sS -X POST \
76
+ "https://www.wixapis.com/headless-business-setup/v1/headless-business/anonymous/$ANONYMOUS_ID"
77
+ ```
78
+
79
+ ```json
80
+ { "metaSiteId": "f0ad8672-09e9-4111-b6fe-070c70bd2df5",
81
+ "projectId": "54528d34-b23c-4fbe-b07d-2c522350abd7" }
82
+ ```
83
+
84
+ Keep both: `metaSiteId` addresses the site in every later call; `projectId`
85
+ builds the save link in step 3b.
86
+
87
+ ### 2. Upload the files
88
+
89
+ One `multipart/form-data` request carrying every file. Each file is a part named
90
+ `files` whose **filename is its path relative to the site root** — that is how
91
+ subdirectories survive; with `curl`, set it explicitly with `;filename=` whenever
92
+ it isn't just the basename. A single `.zip` part works too — send it alone and
93
+ it's unpacked server-side, a single wrapping folder stripped.
94
+
95
+ ```bash
96
+ AGENT=claude-code # ← replace with your own identifier (see note below)
97
+ curl -sS -X POST \
98
+ "https://www.wixapis.com/headless-business-setup/v1/headless-business/anonymous/$ANONYMOUS_ID/$META_SITE_ID/upload?campaign=mcp&agent=$AGENT" \
99
+ -F "files=@index.html;filename=index.html" \
100
+ -F "files=@assets/styles.css;filename=assets/styles.css" \
101
+ -F "files=@assets/logo.png;filename=assets/logo.png"
102
+ ```
103
+
104
+ ```json
105
+ { "uploadId": "03244542-d820-42f6-acfa-166c6658b1a6" }
106
+ ```
107
+
108
+ Keep `campaign=mcp` (the drop-flow referral tag — don't change it) and set
109
+ `agent=$AGENT` to **your own identifier**: the coding agent or tool performing this
110
+ drop, so the upload is attributed to the real client. Use a short, stable,
111
+ lowercase-hyphenated slug — e.g. `claude-code`, `cursor`, `codex-cli`, `windsurf`,
112
+ `github-copilot`, or your product's name; if you genuinely can't name yourself, use
113
+ `unknown-agent`. Send the **same** `agent` on every upload for this site, matching
114
+ the `agent` you'd use in Path A. Nothing is live yet; this only stages and validates.
115
+
116
+ ### 3. Release — the site goes live
117
+
118
+ ```bash
119
+ curl -sS -X POST \
120
+ "https://www.wixapis.com/headless-business-setup/v1/headless-business/anonymous/$ANONYMOUS_ID/$META_SITE_ID/release" \
121
+ -H 'Content-Type: application/json' \
122
+ -d "{\"uploadId\":\"$UPLOAD_ID\"}"
13
123
  ```
14
- https://www.wix.com/headless/drop?utm_campaign=mcp
124
+
125
+ ```json
126
+ { "siteUrl": "https://instant-hguwrvtcrniw-headlessstack-140d.wix-site-host.com" }
15
127
  ```
16
128
 
17
- **Always give the URL exactly as written above, including the
18
- `utm_campaign=mcp` query parameter.** It attributes the visit to an
19
- assistant/MCP referral; dropping or rewriting it breaks that attribution.
129
+ The site is live at `siteUrl` immediately.
130
+
131
+ #### Iterate while anonymous (don't create a new site)
132
+
133
+ Simple static changes — new copy, another page, a different look — happen here,
134
+ **while the site is still anonymous**, and this is the only window for them:
135
+ re-run steps 2–3 with the **same `anonymousId` and `metaSiteId`**; the upload
136
+ replaces the site's contents and `siteUrl` stays the same. Send the full file set
137
+ each time (release replaces, it doesn't merge). Don't go back to step 1 — a fresh
138
+ site per change leaves the user a trail of abandoned sites on changing URLs; only
139
+ create another for a genuinely separate site.
140
+
141
+ So **iterate first, claim last**: refine on the same ids until the site is right,
142
+ *then* finish. Once claimed, these anonymous endpoints stop working and the only
143
+ way to keep changing the site in code is a headless project
144
+ ([Keep building](#keep-building-add-a-backend-when-you-need-one)).
145
+
146
+ **When the site is final, finish based on identity:**
147
+
148
+ - **You have the user's access token** — claim it into their account (step 4).
149
+ Don't stop at a temporary site: an unclaimed site expires, so saving it is part
150
+ of publishing, not an extra favour to ask about.
151
+ - **You have no user identity** — stop here; this is a finished, legitimate result
152
+ (exactly what the drop page produces for every visitor). Give the user `siteUrl`
153
+ plus the save link, which is how the site survives:
154
+
155
+ ```
156
+ https://www.wix.com/live-headless-site/{projectId}?anonymousId={anonymousId}
157
+ ```
20
158
 
21
- ## What happens on that page
159
+ That page shows the site with a countdown and signs the user in to keep it.
160
+ Treat the link as a secret — whoever opens it while signed in to Wix claims the
161
+ site into *their* account — so give it only to the user who asked.
22
162
 
23
- 1. The user drags in their files (or a zip) — no login needed.
24
- 2. Wix hosts them immediately on a live URL they can open and share.
163
+ ### 4. Put the site in the user's account
25
164
 
26
- ## Tell the user before they upload
165
+ ```bash
166
+ curl -sS -X POST \
167
+ "https://www.wixapis.com/headless-business-setup/v1/headless-business/anonymous/$ANONYMOUS_ID/$META_SITE_ID/claim" \
168
+ -H "Authorization: Bearer $ACCESS_TOKEN"
169
+ ```
170
+
171
+ Returns `{}` on success; needs a user or account-level identity (else
172
+ `UNAUTHENTICATED`). It consumes the anonymous record, so it's the last call that
173
+ works against these endpoints — do it after the release, never before.
174
+
175
+ **The site's URL changes here.** The step-3 host stops resolving — the free host
176
+ is scoped to the owning account and re-minted under the user's. Read the new one
177
+ in step 5; never repeat the step-3 URL after a claim.
178
+
179
+ ### 5. Read the site's final URL
180
+
181
+ [Query Sites](https://dev.wix.com/docs/api-reference/account-level/sites/sites/query-sites)
182
+ filtered to the **`HEADLESS` namespace** — headless sites are omitted from the
183
+ default query, so the filter is required, and an `id` filter is rejected, so match
184
+ the id yourself.
185
+
186
+ ```bash
187
+ curl -sS -X POST "https://www.wixapis.com/site-list/v2/sites/query" \
188
+ -H "Authorization: Bearer $ACCESS_TOKEN" \
189
+ -H 'Content-Type: application/json' \
190
+ -d '{"query":{"filter":{"namespace":"HEADLESS"},"cursorPaging":{"limit":100}}}'
191
+ ```
192
+
193
+ Find the entry whose `id` equals your `metaSiteId`, read `viewUrl` (page with
194
+ `metadata.cursors.next` if needed):
195
+
196
+ ```json
197
+ { "id": "f0ad8672-09e9-4111-b6fe-070c70bd2df5",
198
+ "displayName": "Snake", "published": true, "namespace": "HEADLESS",
199
+ "viewUrl": "https://instant-hguwrvtcrniw-ayalg5-1406.wix-site-host.com/" }
200
+ ```
201
+
202
+ Give the user two links: `viewUrl` for the live site, and its dashboard at
203
+ `https://manage.wix.com/dashboard/{metaSiteId}` to manage it.
204
+
205
+ ### What the upload accepts, and how it fails
206
+
207
+ The requirements below apply to both paths — an upload that breaks them is why a
208
+ release never happens:
209
+
210
+ - **A top-level HTML file is required.** It needn't be named `index.html` (a lone
211
+ top-level HTML of any name becomes the homepage), but once there's more than
212
+ one, an `index.html` must be among them.
213
+ - **3 MB per file, 20 MB per site.**
214
+ - **Static files only** — HTML, CSS, JS, images, fonts. Framework source that
215
+ needs a build step (a `package.json`, React/Vue sources) must be built first;
216
+ upload the build output.
217
+
218
+ On Path B, failures come back as HTTP 400 with a code in
219
+ `details.applicationError.code`: `MISSING_INDEX_HTML` (add a top-level HTML),
220
+ `FILE_TOO_LARGE` (a file over 3 MB), `TOTAL_TOO_LARGE` (bundle over 20 MB). A
221
+ `404` after step 1 means the one-hour window passed or the site was already
222
+ claimed — start again from step 1.
223
+
224
+ **If Path B fails for any reason you can't quickly fix — a rejected upload, an
225
+ error, a call you can't make — fall back to [Path A](#path-a--hand-the-user-the-drop-page):
226
+ give the user the drop-page link so they can finish in the browser.** Never leave
227
+ them with a failed publish and no way forward; the drop page reaches the same
228
+ result without the step that broke.
229
+
230
+ ## Keep building: add a backend when you need one
231
+
232
+ The drop flow publishes **static** files. When the site needs a real backend —
233
+ stores, payments, bookings, a CMS, members, forms — it becomes a **Wix Headless
234
+ project**. This is a solution the user chooses when the need appears, not a
235
+ required step: a static site is a finished result on its own.
236
+
237
+ Offer it once the site is claimed/owned and you're in a coding environment with a
238
+ shell. It keeps the **same site, appId and URL** (the downloaded project already
239
+ carries a `wix.config.json` binding it), and is released with the Wix CLI from
240
+ then on:
241
+
242
+ ```bash
243
+ curl -sSL -o project.zip \
244
+ "https://www.wix.com/_api/wixstro-deployments/v1/instant-sites/$META_SITE_ID/download.zip"
245
+ unzip project.zip -d project # index.html + assets + wix.config.json
246
+ ```
27
247
 
28
- Share the requirements that match their situation — these are the common
29
- reasons an upload fails:
248
+ Then follow `https://wix.com/headless/skill.md`: it turns the static files into a
249
+ headless project (`@wix/sdk` + the business solutions the site needs), bound to
250
+ the same site.
30
251
 
31
- - The upload must contain an **HTML file at the top level of the site's
32
- files**. It does not need to be named `index.html` — a single HTML file of
33
- any name is served as the homepage — and a zip or folder that wraps
34
- everything in one top-level folder (e.g. `my-site/index.html`) is unwrapped
35
- automatically.
36
- - Size limits: **3 MB per file, 20 MB total.**
37
- - **Static files only** — HTML, CSS, JavaScript, and assets. If the user has
38
- framework source code that needs a build step (a `package.json`, React/Vue
39
- source, etc.), they must run their build first and upload the build output
40
- folder's contents, not the source.
252
+ This is the only way to keep changing a **claimed** site in code, and it's why it
253
+ needs `wix login`: re-releasing to a claimed site is authenticated *and*
254
+ file-based, and an authenticated file operation needs the token in your **shell**
255
+ (via `wix login`), not injected into a tool — the API-call/execute-API tools carry
256
+ the auth but can't do file operations. There's no lighter "re-upload static to my
257
+ claimed site" shortcut.
41
258
 
42
259
  ## Route the request correctly
43
260
 
44
- | The user has… | Do this |
45
- |---|---|
46
- | Site files on their machine (HTML/zip/AI-builder export), wants a new site | This recipe — send them to the drop URL above |
47
- | A live site or store on another platform (a URL), or CSV/TSV exports, and wants content/products migrated | [Site Import](site-import.md) |
48
- | An existing Wix site they want to add HTML, an embed, or custom code into | Not this recipe — that's embedding custom code in the site editor |
49
- | Images, videos, or documents to add to a site | [Upload Media to Wix](../media/upload-media-to-wix.md) — media goes to the site's media files, not a new site |
261
+ - **You can't read the files, can't make HTTP calls, or have no shell
262
+ (API-call/execute-API tools only, which can't upload a file)** — Path A, the
263
+ drop page. It's also the default whenever Path B isn't clearly available, and
264
+ the fallback whenever Path B fails partway — hand over the link, don't leave the
265
+ user stuck.
266
+ - **Files you generated here or can read, and you can upload from a shell** —
267
+ Path B. If you hold the user's identity, claim it into their account and return
268
+ the live URL + dashboard.
269
+ - **A change to a site you published this way here** —
270
+ [iterate in place](#iterate-while-anonymous-dont-create-a-new-site) on the same ids.
271
+ - **A published anonymous site the user wants to keep** — steps 4–5 with their
272
+ identity, else the step-3 save link.
273
+ - **A claimed site that now needs a backend** (stores, bookings, CMS, members,
274
+ forms) — [add a backend](#keep-building-add-a-backend-when-you-need-one).
275
+ - **Migrating a live site/store from another platform by URL, or CSV/TSV
276
+ exports** — [Site Import](site-import.md).
277
+ - **Adding HTML, an embed, or code to an existing Wix site** — not this recipe
278
+ (that's custom code in the editor).
279
+ - **Images, videos, or documents for a site** —
280
+ [Upload Media to Wix](../media/upload-media-to-wix.md).
50
281
 
51
- Do not try to perform the upload for the user through an API, and do not
52
- create a site for them with other site-creation tools instead — the drop page
53
- is the flow.
282
+ Don't create the site with other tools (meta-site templates, headless-business
283
+ provisioning) — those make an empty site, not a published copy of the user's files.
@@ -15,10 +15,11 @@
15
15
  // No vertical arg -> deploys just the shared transport; re-run with the vertical(s) once known.
16
16
  // NOTE: .cjs on purpose — the app is an ESM package ("type":"module"); a .js here would load as ESM
17
17
  // and require()/module.exports would throw.
18
- const { existsSync, cpSync, readFileSync, writeFileSync } = require('fs');
18
+ const { existsSync, cpSync, mkdirSync, readFileSync, writeFileSync } = require('fs');
19
19
 
20
20
  const REF = '/app/.agents/skills/wix-vibe-headless/references';
21
21
  const WIX_CONFIG = '/app/src/rest/wix-config.js';
22
+ const NAV_ADAPTER = '/app/src/lib/nav.js';
22
23
  const VERTICALS = ['storefront', 'bookings', 'blog', 'cms', 'forms', 'portfolio', 'pricing-plans', 'events', 'members', 'restaurants'];
23
24
 
24
25
  // force:false + errorOnExist:false — fill in only files that AREN'T there yet; never overwrite.
@@ -69,6 +70,32 @@ function replaceMembersAuthLeftovers() {
69
70
  return result;
70
71
  }
71
72
 
73
+ // --- nav adapter --------------------------------------------------------------------------------
74
+ //
75
+ // Every shipped component imports Link/useParams/etc from "@/lib/nav", so one set of sources runs on
76
+ // either Base44 template and the router is named in exactly one file. Which adapter belongs there is
77
+ // a filesystem fact, so resolve it here rather than leaving the agent to infer the template and
78
+ // hand-write the file: the react-router one is a re-export a model can guess, but the TanStack one
79
+ // normalises useParams (strict:false) and useNavigate (object arg), and a guess breaks every page.
80
+ //
81
+ // The react-router adapter ships INSIDE shared/app/ (-> src/lib/nav.js), so it lands on every
82
+ // install path, including hosts that copy that tree themselves and never run this script. Only the
83
+ // TanStack override needs writing, and it goes down BEFORE the shared copy — that copy is
84
+ // force:false, so whatever is at the path first wins.
85
+ function detectTemplate() {
86
+ return existsSync('/app/src/routes/__root.jsx') ? 'tanstack' : 'react-router';
87
+ }
88
+
89
+ function installNavAdapter(template) {
90
+ if (template !== 'tanstack') return 'from_shared_tree';
91
+ const src = `${REF}/_shared/nav/nav.tanstack.js`;
92
+ if (!existsSync(src)) return 'adapter_missing_from_skill';
93
+ if (existsSync(NAV_ADAPTER)) return 'already_present'; // same don't-clobber contract as COPY
94
+ mkdirSync('/app/src/lib', { recursive: true });
95
+ cpSync(src, NAV_ADAPTER);
96
+ return 'written';
97
+ }
98
+
72
99
  // --- WRITE the credentials ----------------------------------------------------------------------
73
100
  //
74
101
  // The two ids arrive as flags so this script writes them once, character-for-character, instead of a
@@ -128,7 +155,11 @@ const deployed = { verticals: [] };
128
155
  const aliased = [...new Set(positional.filter((a) => ALIASES[a]))].map((a) => `${a} -> ${ALIASES[a]}`);
129
156
  if (aliased.length) deployed.aliased = aliased;
130
157
 
131
- // Shared transport — always (app/rest/wix-client.js, wix-config.js -> src/rest/).
158
+ // Nav adapter — before the shared copy, which carries the react-router default at the same path.
159
+ deployed.template = detectTemplate();
160
+ deployed.navAdapter = installNavAdapter(deployed.template);
161
+
162
+ // Shared transport — always (app/rest/wix-client.js, wix-config.js -> src/rest/, lib/nav.js).
132
163
  if (existsSync(`${REF}/shared/app`)) cpSync(`${REF}/shared/app`, '/app/src', COPY);
133
164
 
134
165
  // Each named vertical — its app/ (UI + app/rest/ helpers) -> src/.
@@ -22,7 +22,7 @@ Install three skills — they land under `.agents/skills/`:
22
22
  - **`wix-base44-connector`** — Wix connector usage, API contracts, and documentation discovery.
23
23
 
24
24
 
25
- Run this through exec_tool, exactly as written — installs all three skills, deploys the `storefront` REST scaffolds + UI into `src/`, and pins the AGENTS.md note.
25
+ Run this through exec_tool, exactly as written — installs all three skills, deploys the `storefront` REST scaffolds + UI into `src/` (the nav adapter at `src/lib/nav.js` among them), and pins the AGENTS.md note. **Its `deploy` result reports this app's `template`** — `react-router` wires routes into `src/App.jsx`, `tanstack` mounts them as files under `src/routes/`; see [`../references/_shared/routing.md`](../references/_shared/routing.md).
26
26
 
27
27
  ```js
28
28
  const { execSync } = require('child_process');
@@ -18,11 +18,20 @@ These skills are already installed under `.agents/skills/`:
18
18
  - **`wix-manage`** — REST recipes for managing and configuring the Wix site.
19
19
  - **`wix-base44-connector`** — Wix connector usage, API contracts, and documentation discovery.
20
20
 
21
- Base44 has also deployed the storefront hooks, cart components/context, image helpers, and REST
22
- scaffolds into `src/`, configured the Wix connector/client, and added the Wix note to `AGENTS.md`.
23
- No installation, deployment, or AGENTS.md update is needed.
21
+ Base44 has also deployed the storefront hooks, cart components/context, image helpers, REST
22
+ scaffolds and the nav adapter (`src/lib/nav.js`) into `src/`, configured the Wix connector/client,
23
+ and added the Wix note to `AGENTS.md`. No installation, deployment, or AGENTS.md update is needed.
24
+
24
25
  The deployed implementation and configuration files do not need to be read; use the build and seed
25
- guides below for their contracts and usage. Continue with STEP 1.
26
+ guides below for their contracts and usage.
27
+
28
+ **Mount pages the way this app's template expects** — ask `src/routes/__root.jsx` first: present →
29
+ TanStack Start, where pages mount as route files and the deployed `src/lib/nav.js` needs swapping
30
+ for `_shared/nav/nav.tanstack.js`; absent → React Router, routes wired into `src/App.jsx`. Building for the wrong one
31
+ renders a blank preview with no error to explain it:
32
+ [`../references/_shared/routing.md`](../references/_shared/routing.md).
33
+
34
+ Continue with STEP 1.
26
35
 
27
36
  Follow STEPs 1–3 below exactly. Fire product image generations first, then build the client
28
37
  (STEP 1), and seed (STEP 2) **after** the client is built — generation finishes while you build.
@@ -21,7 +21,7 @@ Install three skills — they land under `.agents/skills/`:
21
21
  - **`wix-base44-connector`** — Wix connector usage, API contracts, and documentation discovery.
22
22
 
23
23
 
24
- Run this through exec_tool, exactly as written — installs all three skills, deploys the `storefront` REST scaffolds + UI into `src/`, and pins the AGENTS.md note.
24
+ Run this through exec_tool, exactly as written — installs all three skills, deploys the `storefront` REST scaffolds + UI into `src/` (the nav adapter at `src/lib/nav.js` among them), and pins the AGENTS.md note. **Its `deploy` result reports this app's `template`** — `react-router` wires routes into `src/App.jsx`, `tanstack` mounts them as files under `src/routes/`; see [`../references/_shared/routing.md`](../references/_shared/routing.md).
25
25
 
26
26
  ```js
27
27
  const { execSync } = require('child_process');
@@ -18,7 +18,7 @@ STEP 3, and **except a seed that attaches entity images**, which runs after the
18
18
 
19
19
  Install three skills under `.agents/skills/`: **`wix-vibe-headless`** (the client build + seed guide — your main source of truth), **`wix-manage`** (REST recipes to manage/configure the site), and **`wix-base44-connector`** (site context + API-doc discovery).
20
20
 
21
- Run this through exec_tool, exactly as written — installs all three skills, deploys REST scaffolds + UI into `src/`, writes `wix-config.js`, and pins the AGENTS.md note.
21
+ Run this through exec_tool, exactly as written — installs all three skills, deploys REST scaffolds + UI into `src/` (the nav adapter at `src/lib/nav.js` among them), writes `wix-config.js`, and pins the AGENTS.md note. **Its `deploy` result reports this app's `template`** (`react-router` or `tanstack`) — STEP 3 needs it.
22
22
 
23
23
  **Set `VERTICALS`** to what the prompt asks for — **list every vertical the app uses**, since several often join the main one (too vague to tell? do STEP 2 first, then set it). Adding one later: re-run with the extra name.
24
24
 
@@ -91,9 +91,24 @@ truth for how the client is built.
91
91
  file the seed writes. Read its `INSTRUCTIONS.md` **Prerequisites** before building any form UI; seed
92
92
  it first (STEP 4) and build the rest of the app meanwhile.
93
93
 
94
- **`src/App.jsx`: edit surgically, never rewrite.** It carries required platform auth scaffolding
95
- (`AuthProvider`/`useAuth` from `@/lib/AuthContext`); a full rewrite drops them → the validator
96
- rejects the write. Wire routes/imports in with `find_replace`, leave the rest as-is.
94
+ **Mount pages the way this app's template expects.** Base44 ships more than one and they route
95
+ differently; building for the wrong one renders a blank preview with no error to explain it. STEP 1
96
+ resolved which it is and reported it as `template`:
97
+
98
+ - `tanstack` → **TanStack Start**: file-based routes under `src/routes/`, no `src/App.jsx`, no
99
+ `index.html`, build output in `.output/` rather than `dist/`. Pages mount as route files; chrome
100
+ and providers live in `__root.jsx`.
101
+ - `react-router` → **React Router**: routes and providers are wired into `src/App.jsx`.
102
+
103
+ Read the app's own `AGENTS.md` first either way — both templates ship one and it states their
104
+ conventions. The mounting pattern for each, and what STEP 1 put in `src/lib/nav.js`:
105
+ [`../references/_shared/routing.md`](../references/_shared/routing.md).
106
+
107
+ **On the React Router template, `src/App.jsx` is edited surgically, never rewritten.** It carries
108
+ required platform auth scaffolding (`AuthProvider`/`useAuth` from `@/lib/AuthContext`); a full
109
+ rewrite drops them → the validator rejects the write. Wire routes/imports in with `find_replace`,
110
+ leave the rest as-is. TanStack keeps the same scaffolding in `src/routes/__root.jsx` and
111
+ `src/lib/AuthContext.jsx`, under the same rule: add around it, never replace it.
97
112
 
98
113
  ## STEP 4 — Manage and seed the business
99
114
 
@@ -17,6 +17,12 @@ Everything is under `.agents/skills/wix-vibe-headless/references/`.
17
17
  | `wix-client.js` | The transport: exchanges `WIX_CLIENT_ID` for an anonymous **visitor token**, persists + refreshes it (that token *is* the cart/session identity), and exposes `wixApiRequest(path, {method, body, query})` — plus the member-session swap (`setSessionTokens` / `clearSession` / `isMember`). Plain `fetch`; SSR-guards `window`/`localStorage`; maps 402 + error bodies. |
18
18
  | `wix-config.js` | Holds `WIX_CLIENT_ID` + `WIX_METASITE_ID` — the only values to fill in. |
19
19
 
20
+ **Plus `shared/app/lib/nav.js`.** The reference UI imports `Link`, `useParams`, `useNavigate`,
21
+ `useLocation` and `Navigate` from `@/lib/nav` rather than from a router, so one set of sources runs
22
+ on any of them. Point that path at your own router's equivalents — the shipped file re-exports
23
+ react-router's, and `_shared/nav/nav.tanstack.js` shows the kind of wrapping another router needs
24
+ (params scoped to the current match, a `navigate` you call with a path).
25
+
20
26
  **Every `references/<vertical>/` holds the same four things:**
21
27
 
22
28
  - `app/rest/wix-*.js` — the vertical's **data layer**: named calls carrying the exact request/response
@@ -0,0 +1,30 @@
1
+ // Navigation adapter — TanStack Start template (src/routes/ file-based routing).
2
+ // Copy to src/lib/nav.js. Shipped components import Link/useParams/etc from here so the same
3
+ // files run on either Base44 template; this file is the only place the router is named.
4
+ //
5
+ // Two shapes differ from react-router and are normalised here:
6
+ // useParams — TanStack scopes params to a route; `strict: false` returns the current match's
7
+ // params, which is what a shared component wants.
8
+ // useNavigate — TanStack takes an object; this returns a function you call with a path, and
9
+ // `navigate(-1)` still goes back.
10
+ import {
11
+ Link as RouterLink,
12
+ Navigate,
13
+ useLocation,
14
+ useNavigate as useRouterNavigate,
15
+ useParams as useRouterParams,
16
+ } from "@tanstack/react-router";
17
+
18
+ // `to` is an already-resolved path (`/blog/my-post`); the router matches it at runtime.
19
+ export const Link = RouterLink;
20
+ export { Navigate, useLocation };
21
+
22
+ export function useParams() {
23
+ return useRouterParams({ strict: false });
24
+ }
25
+
26
+ export function useNavigate() {
27
+ const navigate = useRouterNavigate();
28
+ return (to, options) =>
29
+ typeof to === "number" ? window.history.go(to) : navigate({ to, ...options });
30
+ }
@@ -0,0 +1,86 @@
1
+ # Mounting pages: which template is this app?
2
+
3
+ Base44 ships more than one app template, and they route differently — so which one you are on
4
+ decides how a page gets mounted. A page mounted the other template's way renders nothing, and the
5
+ preview comes back blank with no error to explain it.
6
+
7
+ **An install that ran `deploy.cjs` already told you** — its result carries the template it resolved
8
+ from disk, as `{ "template": "react-router" }` or `{ "template": "tanstack" }`. Where the host
9
+ deployed the tree itself there is no such line, and the same fact reads straight off the app —
10
+ **ask `src/routes/__root.jsx` first**: present → TanStack Start (file-based routes, build output in
11
+ `.output/` rather than `dist/`); absent → React Router SPA, routed from `src/App.jsx` with an
12
+ `index.html` beside it. That order matters, because an `src/App.jsx` on a TanStack app is
13
+ something an agent wrote believing the app was React Router — `__root.jsx` is never there by
14
+ mistake. The app's own `AGENTS.md` (both templates ship one) states its conventions — worth a read
15
+ before the first write.
16
+
17
+ ## On TanStack, four things differ from the React Router form
18
+
19
+ Routing guidance you meet elsewhere — routes wired into `src/App.jsx`, `react-router-dom` imports,
20
+ its `AuthProvider` / `QueryClientProvider` wrappers — describes the React Router template. On this
21
+ one:
22
+
23
+ - **There is no `src/App.jsx`, and that is the finished state.** Leave it absent; creating one
24
+ wires a router the app does not use, and the pages mounted in it never render.
25
+ - **Route files import `createFileRoute` and `Link` from `@tanstack/react-router`**, which this
26
+ template installs.
27
+ - **The wrappers live in `src/routes/__root.jsx`.** Same rule as `App.jsx` carries on the other
28
+ template: add around them, never replace them.
29
+ - **Telling the two apart costs nothing** — the app's files are already in your context.
30
+
31
+ ## The nav adapter is already installed
32
+
33
+ Shipped components import `Link`, `useParams` and friends from `@/lib/nav`, never from a router
34
+ package, so one set of sources runs on either template. `src/lib/nav.js` arrives with the rest of
35
+ the deployed tree, and it is the one place the router is named. Write your own pages against
36
+ `@/lib/nav` too and they stay portable for free.
37
+
38
+ **On TanStack, check what landed.** The deployed default is the React Router adapter, and
39
+ `deploy.cjs` swaps the TanStack one in when it runs — but a host that copies the tree itself lands
40
+ the default whatever the template. So on a TanStack app, open `src/lib/nav.js` and, if it
41
+ re-exports from `react-router-dom`, copy `_shared/nav/nav.tanstack.js` over it. That file carries
42
+ the two normalisations the imports depend on: `useParams` scoped with `strict: false`, and
43
+ `useNavigate` returning a function you call with a path (`navigate(-1)` included).
44
+
45
+ ## React Router template
46
+
47
+ One `Layout` holding your chrome renders `<Outlet/>`; every route nests under a single pathless
48
+ route so the chrome wraps all pages. Each vertical's `STEP 3` carries the exact snippet, including
49
+ where the preview banner sits.
50
+
51
+ ## TanStack Start template
52
+
53
+ Same structure, expressed as files. The chrome that lives in `Layout` goes in `src/routes/__root.jsx`
54
+ (it already renders the document and providers — add your header/footer around its `<Outlet/>`),
55
+ and each route is its own file exporting `createFileRoute`:
56
+
57
+ ```jsx
58
+ // src/routes/shop.jsx → /shop
59
+ import { createFileRoute } from "@tanstack/react-router";
60
+ import Shop from "@/pages/Shop"; // the shipped page, unchanged
61
+
62
+ export const Route = createFileRoute("/shop")({ component: Shop });
63
+ ```
64
+
65
+ ```jsx
66
+ // src/routes/product.$slug.jsx → /product/:slug
67
+ import { createFileRoute } from "@tanstack/react-router";
68
+ import ProductDetail from "@/pages/ProductDetail"; // shipped; reads its param via @/lib/nav
69
+
70
+ export const Route = createFileRoute("/product/$slug")({ component: ProductDetail });
71
+ ```
72
+
73
+ Three things to carry over from the React Router wiring:
74
+
75
+ - **Shipped pages stay where they are** (`src/pages/…`) and stay unedited. A route file is a
76
+ two-line mount, not a copy of the page.
77
+ - **Path params use `$name`**, so `/product/:slug` becomes the file `product.$slug.jsx` and the
78
+ route path `/product/$slug`. `useParams()` from `@/lib/nav` returns them the same way.
79
+ - **Providers** a vertical asks you to wrap the tree in (`CartProvider`, `MemberProvider`, …) go in
80
+ `__root.jsx` around `<Outlet/>`, once — not per route file.
81
+
82
+ Per-user routes should also set `ssr: false` so personal data never lands in cacheable HTML:
83
+
84
+ ```jsx
85
+ export const Route = createFileRoute("/my-plans")({ component: MyPlans, ssr: false });
86
+ ```