@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.
- package/package.json +1 -1
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +1 -1
- package/skills/wix-app/references/SERVICE_PLUGIN.md +14 -1
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +7 -2
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +53 -28
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +17 -4
- package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +71 -31
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +3 -4
- package/skills/wix-app/references/service-plugin/ADDITIONAL-FEES.md +4 -0
- package/skills/wix-app/references/service-plugin/AVAILABILITY-TIME-SLOTS-CONFIGURATION.md +118 -0
- package/skills/wix-app/references/service-plugin/BOOKING-POLICY.md +65 -0
- package/skills/wix-app/references/service-plugin/BOOKINGS-PRICING.md +71 -0
- package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +11 -3
- package/skills/wix-app/references/service-plugin/BOOKINGS-VALIDATION.md +137 -0
- package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +23 -16
- package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
- package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +4 -2
- package/skills/wix-app/references/service-plugin/REALTIME-PERMISSIONS.md +45 -0
- package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +15 -0
- package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +4 -0
- package/skills/wix-app/references/service-plugin/VALIDATIONS.md +4 -0
- package/skills/wix-base44-connector/SKILL.md +46 -24
- package/skills/wix-headless/SKILL.md +1 -0
- package/skills/wix-headless/references/CAPABILITIES.md +7 -2
- package/skills/wix-headless/references/SDK_HANDOFF.md +2 -1
- package/skills/wix-headless/references/inline-recipes/experience-store.md +49 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +431 -115
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +1 -1
- package/skills/wix-headless/references/managed/CREATE.md +5 -0
- package/skills/wix-headless/references/managed/DEPLOYMENT.md +8 -8
- package/skills/wix-headless-fast/install/fast-path.mjs +3 -1
- package/skills/wix-headless-fast/references/shared/app/wix/media.ts +13 -0
- package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +227 -56
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +37 -3
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +266 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +165 -0
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +48 -15
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +129 -11
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +36 -6
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +190 -24
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +62 -4
- package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +21 -2
- package/skills/wix-headless-fast/references/storefront/seed/SEED.md +5 -1
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +59 -6
- package/skills/wix-manage/SKILL.md +8 -5
- package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +4 -1
- package/skills/wix-manage/references/bookings/create-appointment-service.md +3 -1
- package/skills/wix-manage/references/bookings/create-class-service.md +3 -1
- package/skills/wix-manage/references/bookings/create-course-service.md +4 -2
- package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +68 -3
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-seasonal-promotion.md +1 -1
- package/skills/wix-manage/references/events/create-wix-event.md +46 -0
- package/skills/wix-manage/references/events/manage-wix-events.md +51 -1
- package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +6 -6
- package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +108 -14
- package/skills/wix-manage/references/seo/manage-content-plan.md +1 -1
- package/skills/wix-manage/references/seo/manage-seo-suggestions.md +351 -0
- package/skills/wix-manage/references/sites/upload-static-site.md +264 -34
- package/skills/wix-vibe-headless/install/deploy.cjs +33 -2
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +1 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +13 -4
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +1 -1
- package/skills/wix-vibe-headless/platforms/base44.md +19 -4
- package/skills/wix-vibe-headless/platforms/generic.md +6 -0
- package/skills/wix-vibe-headless/references/_shared/nav/nav.tanstack.js +30 -0
- package/skills/wix-vibe-headless/references/_shared/routing.md +86 -0
- package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +44 -0
- package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +1 -1
- package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +1 -1
- package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +1 -1
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +42 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +42 -0
- package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +42 -0
- package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +1 -1
- package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +1 -1
- package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +43 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +1 -1
- package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +43 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +1 -1
- package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +1 -1
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +36 -0
- package/skills/wix-vibe-headless/references/shared/app/lib/nav.js +9 -0
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +110 -27
- package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +32 -14
- package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +14 -3
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +47 -35
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +77 -30
- package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +31 -2
- 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:
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{ "siteUrl": "https://instant-hguwrvtcrniw-headlessstack-140d.wix-site-host.com" }
|
|
15
127
|
```
|
|
16
128
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
29
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
//
|
|
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
|
|
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,
|
|
22
|
-
scaffolds into `src/`, configured the Wix connector/client,
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
+
```
|