@wix/agent-skills 1.16.0 → 1.16.2
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/SKILL.md +72 -8
- package/skills/wix-app/references/CODE_QUALITY.md +0 -1
- package/skills/wix-app/references/DASHBOARD_MODAL.md +21 -14
- package/skills/wix-app/references/DASHBOARD_PAGE.md +30 -184
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +19 -3
- package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +172 -0
- package/skills/wix-app/references/dashboard-page/WDS_LAYOUT.md +187 -0
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +12 -7
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +31 -2
- package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +6 -1
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +60 -0
- package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +6 -6
- package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +167 -0
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +2 -2
- package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +187 -0
- package/skills/wix-app/scripts/scan-a11y-code.cjs +777 -0
- package/skills/wix-app/scripts/scan-a11y-eslint.cjs +201 -0
- package/skills/wix-base44-connector/SKILL.md +185 -0
- package/skills/wix-base44-connector/scripts/utils.js +212 -0
- package/skills/wix-design-system/SKILL.md +19 -15
- package/skills/wix-docs/SKILL.md +75 -1
- package/skills/wix-headless/references/CAPABILITIES.md +16 -3
- package/skills/wix-headless/references/SDK_HANDOFF.md +1 -1
- package/skills/wix-headless/references/SEED.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +560 -102
- package/skills/wix-headless/references/inline-recipes/setup-forms.md +210 -143
- package/skills/wix-manage/SKILL.md +20 -17
- package/skills/wix-manage/references/accessibility/scan-site-accessibility.md +98 -0
- package/skills/wix-manage/references/analytics/analytics-dashboard-navigation.md +1 -2
- package/skills/wix-manage/references/domains/domain-search-purchase-and-connect.md +2603 -0
- package/skills/wix-manage/references/events/create-wix-event.md +112 -90
- package/skills/wix-manage/references/events/manage-wix-events.md +33 -94
- package/skills/wix-manage/references/sites/create-headless-site.md +1 -0
- package/skills/wix-manage/references/sites/manage-oauth-apps.md +154 -0
- package/skills/wix-manage/references/sites/read-site-context.md +125 -0
- package/skills/wix-manage/references/sites/site-import.md +67 -15
- package/skills/wix-manage/references/stores/create-product-catalog-v3.md +273 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +1 -1
- package/skills/wix-vibe-headless/SKILL.md +2 -1
- package/skills/wix-vibe-headless/install/deploy.cjs +63 -3
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +104 -0
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +74 -0
- package/skills/wix-vibe-headless/platforms/base44.md +15 -40
- package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +7 -11
- package/skills/wix-vibe-headless/references/blog/seed/SEED.md +1 -1
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +7 -11
- package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +1 -1
- package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +1 -2
- package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +7 -12
- package/skills/wix-vibe-headless/references/events/seed/SEED.md +1 -1
- package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +7 -11
- package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +7 -11
- package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +1 -1
- package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +7 -11
- package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +1 -1
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +7 -11
- package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +1 -1
- package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +1 -1
- package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +5 -3
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +75 -13
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +29 -86
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +3 -8
- package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +78 -105
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +92 -0
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useVariantOptions.js +76 -0
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +1 -1
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +44 -5
- package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +0 -326
- package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +0 -115
- package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +0 -264
- package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +0 -37
- package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +0 -86
- package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +0 -119
- package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +0 -103
- package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +0 -76
- package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +0 -82
- package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +0 -89
- package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +0 -124
- package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +0 -91
- package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +0 -71
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +0 -70
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +0 -73
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +0 -98
- package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +0 -278
- package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +0 -94
- package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +0 -43
- package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +0 -66
- package/skills/wix-app/references/auto-patterns-dashboard/views.md +0 -76
- package/skills/wix-app/scripts/generate-auto-patterns.js +0 -510
- package/skills/wix-manage/references/domains/domain-search-and-purchase.md +0 -437
- package/skills/wix-manage/references/stores/create-product-from-image.md +0 -1031
- package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +0 -623
- package/skills/wix-manage/references/stores/setup-online-store-catalog-v3.md +0 -106
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Read Account or Site Context"
|
|
3
|
+
description: Probe a Wix site or account for full context in one call — installed apps by display name, locale, currency, timezone, and status. Account token + siteId targets one site; account token alone returns up to 10; site-scoped token alone returns the site it is scoped to.
|
|
4
|
+
---
|
|
5
|
+
# Read Account or Site Context
|
|
6
|
+
|
|
7
|
+
Returns a site's name, URL, status, locale/region, and all installed apps with human-readable display names.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Markdown endpoint (recommended)
|
|
12
|
+
|
|
13
|
+
**Endpoint**: `POST https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context/markdown`
|
|
14
|
+
|
|
15
|
+
Returns `{ "markdown": "..." }`.
|
|
16
|
+
|
|
17
|
+
### Account token + siteId — one specific site
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
curl -X POST \
|
|
21
|
+
'https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context/markdown' \
|
|
22
|
+
-H 'Authorization: <AUTH>' \
|
|
23
|
+
-H 'Content-Type: application/json' \
|
|
24
|
+
-d '{"siteId": "<metaSiteId>"}'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Response:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
## 1. Acme Store
|
|
31
|
+
|
|
32
|
+
**ID**: `<metaSiteId>`
|
|
33
|
+
**URL**: [https://example.wixsite.com/acme](https://example.wixsite.com/acme)
|
|
34
|
+
**Status**: Published
|
|
35
|
+
**Editor Type**: Editorless
|
|
36
|
+
**Created**: Aug 14, 2026, 05:21 · **Updated**: Aug 17, 2026, 20:44
|
|
37
|
+
**Velo**: Enabled
|
|
38
|
+
|
|
39
|
+
### Properties
|
|
40
|
+
|
|
41
|
+
**Locale & Region**
|
|
42
|
+
- Language: **en**
|
|
43
|
+
- Country: **US**
|
|
44
|
+
- Timezone: **America/New_York**
|
|
45
|
+
- Currency: **USD**
|
|
46
|
+
|
|
47
|
+
### Apps
|
|
48
|
+
|
|
49
|
+
- **Wix Stores** (ID: `215238eb-22a5-4c36-9e7b-e7c08025e04e`) — Catalog app version: **V3**
|
|
50
|
+
- **Wix Bookings** (ID: `13d21c63-b5ec-5912-8397-c3a5ddb27a97`)
|
|
51
|
+
- **Wix Blog** (ID: `14bcded7-0066-7c35-14d7-466cb3f09103`)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Without siteId
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
curl -X POST \
|
|
58
|
+
'https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context/markdown' \
|
|
59
|
+
-H 'Authorization: <AUTH>' \
|
|
60
|
+
-H 'Content-Type: application/json' \
|
|
61
|
+
-d '{}'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- **Account token**: returns up to 10 sites. If the account has more: `_Showing 10 sites (more available)_` — call again with a specific `siteId`.
|
|
65
|
+
- **Site-scoped token** (e.g. the Wix connector in Base44): returns the one site the token is scoped to.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## JSON endpoint
|
|
70
|
+
|
|
71
|
+
**Endpoint**: `POST https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context`
|
|
72
|
+
|
|
73
|
+
Same request shape. `installedApps` contains raw `appId` UUIDs — extract only what you need:
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
const res = await fetch(
|
|
77
|
+
"https://www.wixapis.com/_api/dynamic-context/v1/dynamic-context",
|
|
78
|
+
{
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers: { Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json" },
|
|
81
|
+
body: JSON.stringify({ siteId: metaSiteId }),
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
const { sites } = await res.json();
|
|
85
|
+
const site = sites[0];
|
|
86
|
+
|
|
87
|
+
const KNOWN_APPS = {
|
|
88
|
+
stores: "215238eb-22a5-4c36-9e7b-e7c08025e04e",
|
|
89
|
+
bookings: "13d21c63-b5ec-5912-8397-c3a5ddb27a97",
|
|
90
|
+
blog: "14bcded7-0066-7c35-14d7-466cb3f09103",
|
|
91
|
+
events: "140603ad-af8d-84a5-2c80-a0f60cb47351",
|
|
92
|
+
pricingPlans: "1522827f-c56c-a5c9-2ac9-00f9e6ae12d3",
|
|
93
|
+
restaurants: "13e8d036-5516-6f75-e025-2aca3b5d7930",
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const appById = Object.fromEntries(
|
|
97
|
+
(site.installedApps ?? []).map((a) => [a.appId, a])
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const context = {
|
|
101
|
+
id: site.id,
|
|
102
|
+
name: site.displayName,
|
|
103
|
+
url: site.url,
|
|
104
|
+
currency: site.properties?.paymentCurrency,
|
|
105
|
+
locale: `${site.properties?.locale?.languageCode}-${site.properties?.locale?.country}`,
|
|
106
|
+
timezone: site.properties?.timeZone,
|
|
107
|
+
hasStores: !!appById[KNOWN_APPS.stores],
|
|
108
|
+
storesCatalogV: appById[KNOWN_APPS.stores]?.catalogVersion ?? null, // "V3" | "V1" | null
|
|
109
|
+
hasBookings: !!appById[KNOWN_APPS.bookings],
|
|
110
|
+
hasBlog: !!appById[KNOWN_APPS.blog],
|
|
111
|
+
hasEvents: !!appById[KNOWN_APPS.events],
|
|
112
|
+
hasPricingPlans: !!appById[KNOWN_APPS.pricingPlans],
|
|
113
|
+
hasRestaurants: !!appById[KNOWN_APPS.restaurants],
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## API Reference
|
|
120
|
+
|
|
121
|
+
- [Get Dynamic Context — markdown](https://dev.wix.com/docs/api-reference/tools/dynamic-site-context/get-dynamic-context-markdown)
|
|
122
|
+
- [Get Dynamic Context — JSON](https://dev.wix.com/docs/api-reference/tools/dynamic-site-context/get-dynamic-context)
|
|
123
|
+
- [Query Sites](https://dev.wix.com/docs/api-reference/account-level/sites/sites/query-sites) — for paginating or filtering the full site list
|
|
124
|
+
- [Get Installed Apps](https://dev.wix.com/docs/api-reference/business-management/app-installation/app-installation/get-installed-apps) — raw app instances with fields not in the context snapshot
|
|
125
|
+
- [Get Site Properties](https://dev.wix.com/docs/api-reference/business-management/site-properties/properties/get-site-properties) — full properties including business description, address, social links
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Site Import"
|
|
3
|
-
description: Drive the Wix Site Import agent to migrate an existing store or site from another platform (Shopify, WooCommerce, Magento, or any URL) into Wix. Use this skill whenever the user wants to import, migrate, or clone a store/site into Wix, mentions moving off Shopify/WooCommerce/Magento, or gives a source store URL and asks to bring it into Wix. Covers starting the import, polling progress, answering the agent's mid-import questions, handling deploy/failure/auth-expiry states, and sending post-deploy follow-up changes.
|
|
3
|
+
description: Drive the Wix Site Import agent to migrate an existing store or site from another platform (Shopify, WooCommerce, Magento, or any URL) into Wix, or to import from CSV/TSV export files with no source site. Use this skill whenever the user wants to import, migrate, or clone a store/site into Wix, mentions moving off Shopify/WooCommerce/Magento, or gives a source store URL and asks to bring it into Wix. Covers starting the import, polling progress, answering the agent's mid-import questions, handling deploy/failure/auth-expiry states, and sending post-deploy follow-up changes.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Site Import
|
|
@@ -54,7 +54,20 @@ Example — Start:
|
|
|
54
54
|
|
|
55
55
|
```
|
|
56
56
|
POST https://www.wixapis.com/site-import/v1/imports
|
|
57
|
-
Body: {
|
|
57
|
+
Body: {
|
|
58
|
+
"request": "Import https://example-store.com into a new Wix site",
|
|
59
|
+
"source_url": "https://example-store.com"
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Example — Start from exported files (no source site, FILE run):
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
POST https://www.wixapis.com/site-import/v1/imports
|
|
67
|
+
Body: {
|
|
68
|
+
"request": "Import these product export files into a new Wix site",
|
|
69
|
+
"fileUrls": ["https://example.com/exports/products.csv"]
|
|
70
|
+
}
|
|
58
71
|
```
|
|
59
72
|
|
|
60
73
|
Example — Poll:
|
|
@@ -96,7 +109,8 @@ and act only on the user's explicit yes.
|
|
|
96
109
|
|
|
97
110
|
This creates real infrastructure and writes to the user's Wix account. Before
|
|
98
111
|
calling **Start**, confirm:
|
|
99
|
-
- The source URL and platform are correct
|
|
112
|
+
- The source URL and platform are correct — or, for a file-only import, the
|
|
113
|
+
export file URL(s) are correct
|
|
100
114
|
- The user understands it runs for up to ~60 minutes and may ask questions mid-way
|
|
101
115
|
|
|
102
116
|
Also confirm before calling **Cancel** — it's irreversible.
|
|
@@ -107,7 +121,7 @@ You are the user experience; the API is plumbing. Keep the protocol invisible:
|
|
|
107
121
|
|
|
108
122
|
- **Show the `importId` once, right after Start succeeds** — e.g. "Your import
|
|
109
123
|
ID is `abc123` — keep it handy." Never show raw JSON, HTTP codes, artifact
|
|
110
|
-
ids, or `sourcePlatform`/`sourceConfidence` values.
|
|
124
|
+
ids, or `sourcePlatform`/`sourceConfidence`/`destinationSiteId` values.
|
|
111
125
|
- **Write for a non-technical audience.** No jargon: no "endpoint", "API",
|
|
112
126
|
"poll", "HTTP", "rate limit", "JSON". Translate events into plain outcomes —
|
|
113
127
|
"the source store limits how fast it can be read" not "hit rate limit (429)".
|
|
@@ -148,12 +162,37 @@ You are the user experience; the API is plumbing. Keep the protocol invisible:
|
|
|
148
162
|
**Single `importId` for the whole import — assigned at Start, never changes.**
|
|
149
163
|
|
|
150
164
|
1. **Start** — `POST /v1/imports`
|
|
151
|
-
Body: `{"request": "<natural language; MUST include the source store URL>"}`
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
165
|
+
Body: `{"request": "<natural language; MUST include the source store URL when crawling a live site>", "source_url": "<the source store URL>", "fileUrls": ["<CSV/TSV export URL>", ...]}`
|
|
166
|
+
`request` is required (1–20000 chars). `source_url` and `fileUrls` are both
|
|
167
|
+
optional, but send whichever applies — never leave both out with no way to
|
|
168
|
+
identify what to import:
|
|
169
|
+
- **`source_url`** — send it whenever the user names a site to crawl. It's
|
|
170
|
+
the identity the service uses to select which migration the request joins,
|
|
171
|
+
not just an extra hint.
|
|
172
|
+
- **`fileUrls`** — send it when the user has CSV/TSV export file(s) to import
|
|
173
|
+
instead of crawling a live site. Setting it makes this a **FILE run**: no
|
|
174
|
+
source site is probed and no source credentials are requested, even if
|
|
175
|
+
`source_url` is also present — `source_url` only changes what the
|
|
176
|
+
migration is keyed on (see below), it does not add a crawl on top of the
|
|
177
|
+
file import. Up to 20 URLs, http/https only (ports 80/443), each ≤2048
|
|
178
|
+
chars. If `source_url` is absent, the file set itself is the migration
|
|
179
|
+
identity — re-sending the same URLs continues the same migration; a
|
|
180
|
+
different set starts a new one. If a URL isn't reachable, the whole call
|
|
181
|
+
is rejected with `INVALID_FILE_URL` (nothing is silently dropped).
|
|
182
|
+
- A request with neither `source_url` nor a URL/site identifiable in
|
|
183
|
+
`request`, and no `fileUrls`, is rejected with `SITE_UNIDENTIFIED`.
|
|
184
|
+
Returns: `importId`, `sourcePlatform`, `sourceConfidence`, `destinationSiteId`.
|
|
185
|
+
`sourcePlatform` comes back as `CSV` for a FILE run (no site was probed, so
|
|
186
|
+
`sourceConfidence` is meaningless there). `destinationSiteId` is the id of
|
|
187
|
+
the Wix site being imported into — returned as soon as Start succeeds,
|
|
188
|
+
even before a source is confirmed.
|
|
189
|
+
**One import per store at a time, keyed on `source_url`** (or the file set
|
|
190
|
+
when there's no `source_url`): re-starting with the same identity continues
|
|
191
|
+
the SAME migration (server returns the existing `importId`, no new import
|
|
192
|
+
created). A different identity always starts an independent migration, even
|
|
193
|
+
for the same user. If a different user on the account already owns an
|
|
194
|
+
import for that identity, Start returns
|
|
195
|
+
`409 { "code": "IMPORT_IN_PROGRESS" }` — tell the user and stop.
|
|
157
196
|
|
|
158
197
|
2. **Poll** — `GET /v1/imports/{importId}?includeRecentActivity=true`
|
|
159
198
|
Returns: `status`, `deployUrl`, `message`, `options[]` (only when
|
|
@@ -230,13 +269,26 @@ the user has no way to open a file.
|
|
|
230
269
|
- Never invent a `deployUrl` — only report the one returned with `DEPLOYED`.
|
|
231
270
|
- Treat `NEEDS_INPUT` and `AUTH_EXPIRED` as normal conversation turns, not
|
|
232
271
|
errors.
|
|
233
|
-
- **Site Import is in limited rollout
|
|
234
|
-
`"code": "NOT_ENABLED"`, tell the user
|
|
235
|
-
|
|
236
|
-
Do not
|
|
272
|
+
- **Site Import is in limited rollout, with no self-service enablement path.**
|
|
273
|
+
If Start returns `404` or `403` with `"code": "NOT_ENABLED"`, tell the user
|
|
274
|
+
plainly that site import isn't available on their account yet — then stop.
|
|
275
|
+
**Do not tell them to "contact Wix support"**: this API is unlisted and
|
|
276
|
+
ALPHA, Wix Support has no visibility into it or way to grant access, and the
|
|
277
|
+
public "importing a site created outside of Wix" help-center article is an
|
|
278
|
+
unrelated, long-stalled feature-request page — sending a user to either is a
|
|
279
|
+
dead end. If a Wix feedback tool is available in your environment, you may
|
|
280
|
+
offer to send feedback noting their interest; that is the only channel that
|
|
281
|
+
reaches the team. Do not retry or fall back to another site-creation tool.
|
|
237
282
|
- Any other `403` on Start means the caller is not authorized — tell the user
|
|
238
283
|
and stop. Do not probe other endpoints to diagnose this. A `400` means a
|
|
239
|
-
required field is missing (`request`/`message` must be 1–20000 chars)
|
|
284
|
+
required field is missing (`request`/`message` must be 1–20000 chars),
|
|
285
|
+
`source_url` exceeds 2048 chars, or `fileUrls` has more than 20 entries or
|
|
286
|
+
one over 2048 chars. A request with no identifiable site (no `source_url`
|
|
287
|
+
and no URL in `request`) and no `fileUrls` is rejected with
|
|
288
|
+
`SITE_UNIDENTIFIED` — ask the user for the store URL or export file(s) and
|
|
289
|
+
retry. A `fileUrls` entry that isn't a reachable http/https URL rejects the
|
|
290
|
+
whole call with `INVALID_FILE_URL` — tell the user which link failed and ask
|
|
291
|
+
for a working one.
|
|
240
292
|
- Requesting an unknown id in `artifactIds` is silently ignored — not an error.
|
|
241
293
|
A document simply may not exist yet on an earlier turn.
|
|
242
294
|
- **The user cannot open files.** If a message mentions a document by filename,
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Create Product (Catalog V3)"
|
|
3
|
+
description: Mandatory first recipe for every Wix Stores Catalog V3 create-product request. Before any mutation, require an explicit name and price for every product; an absent price is never 0. If no product is identified, offer both image-upload and text-description paths and stop. If name or price is missing, ask or offer a suggestion and stop. When both are present, create from the supplied details without requiring optional enrichment. Covers single/bulk creation, inventory, physical/digital products, images, options, variants, SKUs, and validation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Create Product (Catalog V3)
|
|
7
|
+
|
|
8
|
+
Use this recipe for one or multiple Catalog V3 products. Catalog V1 remains supported through [Create Product (Catalog V1)](create-product-catalog-v1.md).
|
|
9
|
+
|
|
10
|
+
> [!IMPORTANT]
|
|
11
|
+
> **Apply the no-product gate first.** A vague request such as “I’d like to add a new product” does not identify a product. Respond only:
|
|
12
|
+
>
|
|
13
|
+
> **“What product would you like to create? You can upload up to 3 images and I’ll generate the product information from them, or describe the product in text.”**
|
|
14
|
+
>
|
|
15
|
+
> Then end the turn. Do not ask for name, price, product type, options, SEO, inventory, or any other structured field yet. Do not replace the image-or-text choice with a checklist, form, or questionnaire. Reading this recipe must be the final tool call in that turn.
|
|
16
|
+
|
|
17
|
+
Canonical example:
|
|
18
|
+
|
|
19
|
+
- User: “For my Wix store, I’d like to add a new product.”
|
|
20
|
+
- Assistant: “What product would you like to create? You can upload up to 3 images and I’ll generate the product information from them, or describe the product in text.”
|
|
21
|
+
- Result: **Stop. Do not request structured product fields yet.**
|
|
22
|
+
|
|
23
|
+
## Preflight: respond and return before mutation
|
|
24
|
+
|
|
25
|
+
Name and price are mandatory **workflow inputs for every product**, even when the API schema accepts an omitted price or initializes it to zero. Evaluate the cases below in order. When a case says **RETURN**, end the turn immediately: do not call a create endpoint, do not continue to examples, and do not create first and ask afterward.
|
|
26
|
+
|
|
27
|
+
1. **No product identified:** Respond only: “What product would you like to create? You can upload up to 3 images and I’ll generate the product information from them, or describe the product in text.” **RETURN.** Do not replace the two paths with a form, checklist, questionnaire, text-only prompt, or requests for name, price, type, options, SEO, or inventory.
|
|
28
|
+
2. **Any product lacks an explicit name or price:** Ask for all missing mandatory values in one question and offer to suggest them. When only price is missing, respond only: “What price should I set for [product name]? I can suggest one if you’d like.” **RETURN.**
|
|
29
|
+
3. **Every name and price is known:** Creation may continue. Options, variations, description, SEO, info sections, type, SKU, inventory, and images are optional. Use them when supplied or requested; do not ask the user to resolve them before creation.
|
|
30
|
+
|
|
31
|
+
“Create it,” “create it now,” “for my store, create,” or similar mutation language does not satisfy a missing price. A usable price must be either explicitly supplied by the user or a suggestion the user accepted. Treat `0` as supplied only when the user explicitly requests a free or zero-priced product.
|
|
32
|
+
|
|
33
|
+
Before every create call, assert both conditions:
|
|
34
|
+
|
|
35
|
+
- Every product has a non-empty name from the user or an accepted suggestion.
|
|
36
|
+
- Every variant has a price from the user or an accepted suggestion; no price came from an API default, placeholder, example, or assumption.
|
|
37
|
+
|
|
38
|
+
If any product is missing a price, **do not call the API**. Ask for the missing price, using the product's supplied name when available, and offer to suggest one. Never put `"amount": "0"` in the request unless the user explicitly chose a zero price.
|
|
39
|
+
|
|
40
|
+
## Core flow
|
|
41
|
+
|
|
42
|
+
1. Apply the preflight. When it says **RETURN**, make no API call in that turn.
|
|
43
|
+
2. Send site-scoped calls with `Authorization`, `wix-site-id`, and `Content-Type: application/json`.
|
|
44
|
+
3. If the catalog version is unknown, run:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
curl --request GET \
|
|
48
|
+
--url 'https://www.wixapis.com/stores/v3/provision/version' \
|
|
49
|
+
--header 'Authorization: <AUTH>' \
|
|
50
|
+
--header 'wix-site-id: <SITE_ID>' \
|
|
51
|
+
--header 'Content-Type: application/json'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Continue here only for `V3_CATALOG`; use the V1 recipe for `V1_CATALOG`.
|
|
55
|
+
4. Resolve each product's supplied type, variants, SKUs, inventory intent, and images after its mandatory name and variant price are known. Do not invent optional attributes the user did not supply or request.
|
|
56
|
+
5. Choose the endpoint, build the products, upload any images, create, and validate every result. Continue until all requested products succeed or report the exact failed items.
|
|
57
|
+
|
|
58
|
+
## Choose the endpoint
|
|
59
|
+
|
|
60
|
+
| Request | No inventory | Quantity or in-stock state |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| One product | `POST /stores/v3/products` | `POST /stores/v3/products-with-inventory` |
|
|
63
|
+
| Multiple products | `POST /stores/v3/bulk/products/create` | `POST /stores/v3/bulk/products-with-inventory/create` |
|
|
64
|
+
|
|
65
|
+
- Bulk endpoints accept 1–100 products, so a compatible bulk endpoint is also valid for one product.
|
|
66
|
+
- For multiple products requested as one batch, send one bulk call. Use the with-inventory endpoint when any product needs inventory; include `inventoryItem` only on tracked variants.
|
|
67
|
+
- Never send `inventoryItem` to a no-inventory endpoint. Do not invent inventory.
|
|
68
|
+
- Digital products normally use a no-inventory endpoint.
|
|
69
|
+
- Per bulk request, allow at most 100 products, 100 total options, 100 modifiers, 100 info sections, and 1000 variants. Split larger input into compliant batches.
|
|
70
|
+
|
|
71
|
+
## Build each product
|
|
72
|
+
|
|
73
|
+
| Concern | Rule |
|
|
74
|
+
|---|---|
|
|
75
|
+
| Type | `PHYSICAL` uses product- and variant-level `physicalProperties`; `DIGITAL` omits physical properties and inventory. |
|
|
76
|
+
| Variants | Include at least one. Price, SKU, barcode, inventory, and digital file are variant-level fields. |
|
|
77
|
+
| Price | Use a string in `price.actualPrice.amount`; add `compareAtPrice` only when supplied. |
|
|
78
|
+
| SKU | Preserve supplied strings exactly, including `#`, punctuation, and leading zeroes. Keep variant SKUs unique unless explicitly requested otherwise. |
|
|
79
|
+
| Options | Define non-empty choices and create every requested Cartesian combination. Each variant references one choice from every option through `optionChoiceNames`. |
|
|
80
|
+
| Text | Prefer `plainDescription` for unformatted copy. Use `description` only for a valid Ricos document. |
|
|
81
|
+
| Media | Up to 3 images are supported per product. Preserve their supplied order in `media.itemsInfo.items`; `media.main` is read-only. |
|
|
82
|
+
|
|
83
|
+
This inventory-aware physical product is the reusable shape. Remove `inventoryItem` when using a no-inventory endpoint; remove `media` when no image was supplied.
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"name": "Canvas Tee",
|
|
88
|
+
"productType": "PHYSICAL",
|
|
89
|
+
"physicalProperties": {},
|
|
90
|
+
"media": {"itemsInfo": {"items": [{
|
|
91
|
+
"url": "https://static.wixstatic.com/media/example.jpg",
|
|
92
|
+
"altText": "Canvas Tee"
|
|
93
|
+
}]}},
|
|
94
|
+
"options": [{
|
|
95
|
+
"name": "Size",
|
|
96
|
+
"optionRenderType": "TEXT_CHOICES",
|
|
97
|
+
"choicesSettings": {"choices": [
|
|
98
|
+
{"choiceType": "CHOICE_TEXT", "name": "Small"},
|
|
99
|
+
{"choiceType": "CHOICE_TEXT", "name": "Large"}
|
|
100
|
+
]}
|
|
101
|
+
}],
|
|
102
|
+
"variantsInfo": {"variants": [
|
|
103
|
+
{
|
|
104
|
+
"choices": [{"optionChoiceNames": {
|
|
105
|
+
"optionName": "Size", "choiceName": "Small", "renderType": "TEXT_CHOICES"
|
|
106
|
+
}}],
|
|
107
|
+
"sku": "TEE-001-S",
|
|
108
|
+
"price": {
|
|
109
|
+
"actualPrice": {"amount": "18.50"},
|
|
110
|
+
"compareAtPrice": {"amount": "22.00"}
|
|
111
|
+
},
|
|
112
|
+
"inventoryItem": {"quantity": 13},
|
|
113
|
+
"physicalProperties": {},
|
|
114
|
+
"visible": true
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"choices": [{"optionChoiceNames": {
|
|
118
|
+
"optionName": "Size", "choiceName": "Large", "renderType": "TEXT_CHOICES"
|
|
119
|
+
}}],
|
|
120
|
+
"sku": "TEE-001-L",
|
|
121
|
+
"price": {"actualPrice": {"amount": "18.50"}},
|
|
122
|
+
"inventoryItem": {"inStock": true},
|
|
123
|
+
"physicalProperties": {},
|
|
124
|
+
"visible": true
|
|
125
|
+
}
|
|
126
|
+
]}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
For a color option, use `SWATCH_CHOICES`; each choice uses `choiceType: ONE_COLOR` and `colorCode`, and the variant reference uses `renderType: SWATCH_CHOICES`.
|
|
131
|
+
|
|
132
|
+
A digital product uses the smaller shape below. Add the supplied variant-level digital file only when one was provided.
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"name": "Focus Planner PDF",
|
|
137
|
+
"productType": "DIGITAL",
|
|
138
|
+
"variantsInfo": {"variants": [{
|
|
139
|
+
"sku": "PDF-FOCUS-01",
|
|
140
|
+
"price": {"actualPrice": {"amount": "9.99"}},
|
|
141
|
+
"visible": true
|
|
142
|
+
}]}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Generated descriptions and SEO
|
|
147
|
+
|
|
148
|
+
- When copy is generated from an image, every factual claim must be user-supplied or directly visible. Preserve user-supplied facts such as a stated material; do not reject them merely because the image alone cannot prove them. Color, shape, and visible decoration may come from the image. Dimensions, capacity, care instructions, durability, compatibility, performance, and any material the user did not identify must be omitted. For example, never write “dishwasher safe” or “microwave safe” unless the user supplied that fact. Omit uncertain claims instead of turning them into marketing language.
|
|
149
|
+
- Use `plainDescription` unless formatting is required. SEO tags use `seoData.tags`.
|
|
150
|
+
- For formatted bullets, the Ricos node is `BULLETED_LIST`, not `BULLET_LIST`, and its data field is `bulletedListData`:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"description": {"nodes": [{
|
|
155
|
+
"type": "BULLETED_LIST",
|
|
156
|
+
"nodes": [{"type": "LIST_ITEM", "nodes": [{
|
|
157
|
+
"type": "PARAGRAPH",
|
|
158
|
+
"nodes": [{"type": "TEXT", "textData": {"text": "Visible blue glaze"}}],
|
|
159
|
+
"paragraphData": {}
|
|
160
|
+
}]}],
|
|
161
|
+
"bulletedListData": {}
|
|
162
|
+
}]}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Add images
|
|
167
|
+
|
|
168
|
+
Skip this step when no image was supplied. Prefer the available dedicated Wix image-upload capability and upload all attachments and public image URLs together. Do not reconstruct that capability inside a general API-execution call. When no dedicated uploader is available, use `POST /site-media/v1/files/import` with the external URL in the body field named exactly `url`—not `importUrl`:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{"url":"https://example.com/product.jpg","mimeType":"image/jpeg","displayName":"Product.jpg","mediaType":"IMAGE"}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
A successful upload that returns the matching `wixstatic.com` URL may be used in product media while asynchronous processing is `PENDING`; do not treat `PENDING` alone as a failure. Stop if the upload reports `FAILED`. Poll `GET /site-media/v1/files/get-file-by-id?fileId=<FILE_ID>` until `file.operationStatus` is `READY` only when the workflow needs guaranteed processing, image metadata, transformations, or independent proof that the asset is ready. A pending URL proves submission, not completed processing, so do not describe it as ready or fully verified unless a later response proves that. Do not use a thumbnail URL or reuse the original external URL after upload.
|
|
175
|
+
|
|
176
|
+
Track every upload as its own product-to-file record. A poll or timeout fallback may return only that file's URL—never another product's URL. If an upload fails, retry the same asset through another supported transfer method when possible; never silently replace it with a different image. If the exact asset cannot be preserved, create only products whose requested images uploaded successfully and report every blocked product and failed source exactly; for a single required-image product, make no product-create call.
|
|
177
|
+
|
|
178
|
+
## Wrap the request
|
|
179
|
+
|
|
180
|
+
Use the chosen product object directly in either envelope:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{"product": PRODUCT}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{"products": [PRODUCT_1, PRODUCT_2], "returnEntity": true}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The first is for single endpoints; the second is for bulk endpoints. If the user supplies only a SKU pattern for variants, generate a stable unique SKU per combination and preserve the mapping in the result.
|
|
191
|
+
|
|
192
|
+
For one product when the user supplied no quantity, stock state, or inventory-tracking request, the complete direct path is `POST /stores/v3/products` with `{"product": PRODUCT}`. Do not infer `inStock: true`, add `inventoryItem`, or choose `/products-with-inventory`; physical product type does not imply inventory. If it has ready images, add `"fields": ["MEDIA_ITEMS_INFO"]` to the same no-inventory request.
|
|
193
|
+
|
|
194
|
+
For one physical product with inventory, the complete direct path is one `POST /stores/v3/products-with-inventory` call with `{"product": PRODUCT}`. Put `inventoryItem` on its priced variant. If it has ready images, add `"fields": ["MEDIA_ITEMS_INFO"]` to that same request. The product shape, envelope, endpoint, and validation paths are complete here: do not search another recipe or schema, probe an alternate endpoint, or make a post-create read unless the projected create response does not prove requested media.
|
|
195
|
+
|
|
196
|
+
### Request projected media when validating images
|
|
197
|
+
|
|
198
|
+
`media.itemsInfo.items` is a projected response field. Creating a product with media does not guarantee that the create response—or an ordinary Get Product call—returns the gallery. To receive it, pass `"MEDIA_ITEMS_INFO"` in the request-level `fields` array.
|
|
199
|
+
|
|
200
|
+
For a single create with images:
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{"product": PRODUCT_WITH_MEDIA, "fields": ["MEDIA_ITEMS_INFO"]}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
For a bulk create with images:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"products": [PRODUCT_1, PRODUCT_2],
|
|
211
|
+
"returnEntity": true,
|
|
212
|
+
"fields": ["MEDIA_ITEMS_INFO"]
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
If the create result still does not prove the stored gallery, make at most one read-only verification call:
|
|
217
|
+
|
|
218
|
+
```http
|
|
219
|
+
GET /stores/v3/products/<PRODUCT_ID>?fields=MEDIA_ITEMS_INFO
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Inspect `product.media.itemsInfo.items` from that projected response. Do not interpret an omitted `itemsInfo` as lost media, search the Update Product schema, or PATCH the same media merely to retrieve it. A PATCH is appropriate only when a projected response proves the stored media is actually wrong.
|
|
223
|
+
|
|
224
|
+
## Validate before reporting success
|
|
225
|
+
|
|
226
|
+
| Endpoint result | Required checks |
|
|
227
|
+
|---|---|
|
|
228
|
+
| Single, no inventory | Require `product.id`; report only response-backed fields as verified. For images, request `MEDIA_ITEMS_INFO` on create or use one projected Get Product verification call. |
|
|
229
|
+
| Single, with inventory | Require `product.id`; inspect `inventoryResults.results`, item metadata, and top-level error. |
|
|
230
|
+
| Bulk, no inventory | Inspect every `results[].itemMetadata`; with `returnEntity: true`, the created entity is `results[].item`, not `results[].product`. Reconcile `bulkActionMetadata.totalSuccesses` and `totalFailures` with the requested count. |
|
|
231
|
+
| Bulk, with inventory | Use the exact two-sibling response paths below. Inspect every product and inventory result, both bulk metadata objects, item metadata, and the inventory error before reporting success. |
|
|
232
|
+
|
|
233
|
+
`POST /stores/v3/bulk/products-with-inventory/create` does **not** return the same flat envelope as `/stores/v3/bulk/products/create`. Its response has two top-level sibling objects:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"productResults": {
|
|
238
|
+
"results": [{"itemMetadata": {}, "item": {}}],
|
|
239
|
+
"bulkActionMetadata": {}
|
|
240
|
+
},
|
|
241
|
+
"inventoryResults": {
|
|
242
|
+
"results": [{"itemMetadata": {}, "item": {}}],
|
|
243
|
+
"bulkActionMetadata": {},
|
|
244
|
+
"error": null
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Before claiming that an inventory-aware bulk create succeeded:
|
|
250
|
+
|
|
251
|
+
1. Inspect every `productResults.results[]` entry and require `itemMetadata.success`; with `returnEntity: true`, read the product from `item`.
|
|
252
|
+
2. Reconcile `productResults.bulkActionMetadata.totalSuccesses`, `totalFailures`, and `undetailedFailures` with the requested product count.
|
|
253
|
+
3. Separately inspect every top-level `inventoryResults.results[]` entry and require `itemMetadata.success`; with `returnEntity: true`, read the inventory entity from `item`.
|
|
254
|
+
4. Reconcile `inventoryResults.bulkActionMetadata.totalSuccesses`, `totalFailures`, and `undetailedFailures` with the expected inventory-item count, and inspect `inventoryResults.error`.
|
|
255
|
+
|
|
256
|
+
The inventory error check is mandatory even when every item and metadata count succeeded. Explicitly read the sibling field—for example, normalize `inventoryResults.error ?? null`—and report success only when it is absent or null. Do not infer that value from HTTP 200, item metadata, or bulk metadata.
|
|
257
|
+
|
|
258
|
+
For `POST /stores/v3/products-with-inventory`, inspect the returned `product.id`, every `inventoryResults.results[].itemMetadata`, and top-level `inventoryResults.error` directly from the create response. Do not issue inventory queries, product searches, Get Product calls, or PATCH calls merely to reconfirm values already proven by that response. If item success proves the inventory write but the response omits the requested quantity, report the quantity as submitted; if the user needs it independently verified, make one targeted inventory read using the returned product ID without first fetching the product again. The only other allowed extra read is the single projected media verification described above when requested images are not present in the projected create result. GET and HEAD requests must not include a request body.
|
|
259
|
+
|
|
260
|
+
Never read `productResults.inventoryResults`: that path does not exist. A successful product result or HTTP 200 does not prove inventory creation succeeded.
|
|
261
|
+
|
|
262
|
+
Retry only failed transient items, not successful products. If a requested field is absent from the response, call it submitted rather than API-verified; never echo the request as proof that it was stored.
|
|
263
|
+
|
|
264
|
+
`product.visible: true` proves catalog visibility, not that an unpublished site is live. Say “created” or “visible in the catalog”; say “live” only when site publication is independently confirmed.
|
|
265
|
+
|
|
266
|
+
## Failure guide
|
|
267
|
+
|
|
268
|
+
- Inventory missing: use the with-inventory endpoint and include `inventoryItem` on each tracked variant.
|
|
269
|
+
- Multiple requested products sent separately: use one compatible bulk call unless they cannot form a compliant batch or specific failed items are being retried.
|
|
270
|
+
- `variantsInfo must not be empty`: include at least one priced variant per product.
|
|
271
|
+
- Option/variant mismatch: create every requested combination and reference every option once per variant.
|
|
272
|
+
- Media not visible: use the uploaded `wixstatic.com` URL in `media.itemsInfo.items`; do not set `media.main`.
|
|
273
|
+
- Digital product rejected: omit physical properties and inventory; keep price, SKU, and any supplied digital file on the variant.
|
|
@@ -324,7 +324,7 @@ function applySafeModeToRequestBody(body, safeModeOptions) {
|
|
|
324
324
|
// media import, Contacts manage/schema, and Members manage.
|
|
325
325
|
//
|
|
326
326
|
// Auth scheme normalization: Wix API keys (`IST.…`) are sent RAW in the Authorization
|
|
327
|
-
// header; OAuth access tokens (e.g. a Wix CLI token from `npx @wix/cli token --site …`)
|
|
327
|
+
// header; OAuth access tokens (e.g. a Wix CLI token from `npx @wix/cli@latest token --site …`)
|
|
328
328
|
// must be sent as `Bearer <token>`. Detect and prefix so both credential kinds work.
|
|
329
329
|
function authHeaderValue(token) {
|
|
330
330
|
const t = String(token).trim();
|
|
@@ -149,7 +149,8 @@ installed, not what the business is about. Never default to store/bookings on si
|
|
|
149
149
|
`INSTRUCTIONS.md`.
|
|
150
150
|
3. **Ensure the vertical's files are in place** — copy `references/<vertical>/app/` and
|
|
151
151
|
`references/shared/app/` into the app's `src/`, and set `WIX_CLIENT_ID` in `wix-config.js`. (Where
|
|
152
|
-
and how they get there is your platform's call — see its instructions.
|
|
152
|
+
and how they get there is your platform's call — see its instructions. On base44 the install step
|
|
153
|
+
writes and verifies `wix-config.js` for you, so there's nothing to set by hand.)
|
|
153
154
|
4. **Wire the shipped client** following the vertical's INSTRUCTIONS: the components are themed by
|
|
154
155
|
base44's design tokens (`src/index.css` — shadcn palette, already set by the design phase), so
|
|
155
156
|
there's no re-skin step; just wire routes + header/footer through the Layout. The UI ships as
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Post-install deploy — run by base44.md STEP 1 with the vertical(s) the app needs:
|
|
2
|
-
// node deploy.cjs <vertical> [<vertical> …]
|
|
2
|
+
// node deploy.cjs <vertical> [<vertical> …] --client-id <id> --metasite-id <id>
|
|
3
3
|
// (storefront | bookings | blog | cms | portfolio | pricing-plans | events | members)
|
|
4
|
+
// Pass the two ids from the prompt and this writes src/rest/wix-config.js for you — see WRITE below.
|
|
5
|
+
// Retyping those ids into the file by hand is how a storefront ships with a dead client id.
|
|
4
6
|
// ONE mechanism: recursively copy `app/` -> /app/src. The shared transport (app/rest/wix-client.js,
|
|
5
7
|
// wix-config.js) is copied always; then each named vertical's app/ (its UI + app/rest/ helpers).
|
|
6
8
|
// Deploy every vertical the app actually uses, in one call or across several — an app that needs both
|
|
@@ -13,9 +15,10 @@
|
|
|
13
15
|
// No vertical arg -> deploys just the shared transport; re-run with the vertical(s) once known.
|
|
14
16
|
// NOTE: .cjs on purpose — the app is an ESM package ("type":"module"); a .js here would load as ESM
|
|
15
17
|
// and require()/module.exports would throw.
|
|
16
|
-
const { existsSync, cpSync, readFileSync } = require('fs');
|
|
18
|
+
const { existsSync, cpSync, readFileSync, writeFileSync } = require('fs');
|
|
17
19
|
|
|
18
20
|
const REF = '/app/.agents/skills/wix-vibe-headless/references';
|
|
21
|
+
const WIX_CONFIG = '/app/src/rest/wix-config.js';
|
|
19
22
|
const VERTICALS = ['storefront', 'bookings', 'blog', 'cms', 'portfolio', 'pricing-plans', 'events', 'members', 'restaurants'];
|
|
20
23
|
|
|
21
24
|
// force:false + errorOnExist:false — fill in only files that AREN'T there yet; never overwrite.
|
|
@@ -66,11 +69,55 @@ function replaceMembersAuthLeftovers() {
|
|
|
66
69
|
return result;
|
|
67
70
|
}
|
|
68
71
|
|
|
72
|
+
// --- WRITE the credentials ----------------------------------------------------------------------
|
|
73
|
+
//
|
|
74
|
+
// The two ids arrive as flags so this script writes them once, character-for-character, instead of a
|
|
75
|
+
// later hand-edit of the placeholder file.
|
|
76
|
+
//
|
|
77
|
+
// An id already in the file wins; the flags only fill what is unset. A host that writes this file
|
|
78
|
+
// at app creation (Base44) has each id as an exact value rather than a copy read out of a prompt.
|
|
79
|
+
// Per id, so a host that resolved one but not the other still gets the gap filled.
|
|
80
|
+
//
|
|
81
|
+
// This briefly worked the other way round for WIX_METASITE_ID, while Base44 could write a different
|
|
82
|
+
// site than the business: it shared one field between the launch and a metasite it provisions per
|
|
83
|
+
// app, and the launch's id lost. Fixed on that side, and the ids it stores now verify against the
|
|
84
|
+
// site each launch came from, so the file is trusted again.
|
|
85
|
+
function readWixConfig() {
|
|
86
|
+
if (!existsSync(WIX_CONFIG)) return {};
|
|
87
|
+
const src = readFileSync(WIX_CONFIG, 'utf8');
|
|
88
|
+
const pick = (name) => {
|
|
89
|
+
const v = (src.match(new RegExp(`${name}\\s*=\\s*["']([^"']*)["']`)) || [])[1] || '';
|
|
90
|
+
return v.startsWith('<') ? '' : v; // the shipped file's `<YOUR-…>` placeholders count as unset
|
|
91
|
+
};
|
|
92
|
+
return { clientId: pick('WIX_CLIENT_ID'), metaSiteId: pick('WIX_METASITE_ID') };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function writeWixConfig(clientId, metaSiteId) {
|
|
96
|
+
const body = [
|
|
97
|
+
'// Wix credentials — written by the skill\'s deploy step from the ids in your prompt.',
|
|
98
|
+
'// Safe to commit: WIX_CLIENT_ID is a public, buyer-facing id (it only mints anonymous visitor',
|
|
99
|
+
'// tokens); WIX_METASITE_ID just identifies the site.',
|
|
100
|
+
`export const WIX_CLIENT_ID = "${clientId}";`,
|
|
101
|
+
`export const WIX_METASITE_ID = "${metaSiteId}";`,
|
|
102
|
+
'',
|
|
103
|
+
].join('\n');
|
|
104
|
+
writeFileSync(WIX_CONFIG, body);
|
|
105
|
+
}
|
|
106
|
+
|
|
69
107
|
// --- main ---------------------------------------------------------------------------------------
|
|
70
108
|
|
|
71
109
|
// Accept one or many: `deploy.cjs members cms`. Duplicates collapse; order is preserved so the
|
|
72
110
|
// first vertical listed wins any same-path file (the copy never overwrites).
|
|
73
|
-
const
|
|
111
|
+
const argv = process.argv.slice(2);
|
|
112
|
+
const flag = (name) => {
|
|
113
|
+
const i = argv.indexOf(`--${name}`);
|
|
114
|
+
return i !== -1 && argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[i + 1] : null;
|
|
115
|
+
};
|
|
116
|
+
const clientId = flag('client-id');
|
|
117
|
+
const metaSiteId = flag('metasite-id');
|
|
118
|
+
// Verticals are the positional args — drop the flags and their values.
|
|
119
|
+
const flagArgs = new Set(['--client-id', '--metasite-id', clientId, metaSiteId].filter(Boolean));
|
|
120
|
+
const requested = [...new Set(argv.filter((a) => !flagArgs.has(a)))];
|
|
74
121
|
const deployed = { verticals: [] };
|
|
75
122
|
|
|
76
123
|
// Shared transport — always (app/rest/wix-client.js, wix-config.js -> src/rest/).
|
|
@@ -92,4 +139,17 @@ if (!requested.length) {
|
|
|
92
139
|
deployed.note = 'no vertical given — deployed the shared transport only; re-run: node deploy.cjs <vertical> [<vertical> …]';
|
|
93
140
|
}
|
|
94
141
|
|
|
142
|
+
const onDisk = readWixConfig();
|
|
143
|
+
const finalClientId = onDisk.clientId || clientId;
|
|
144
|
+
const finalMetaSiteId = onDisk.metaSiteId || metaSiteId;
|
|
145
|
+
|
|
146
|
+
if (!finalClientId || !finalMetaSiteId) {
|
|
147
|
+
deployed.wixConfig = 'skipped — no ids provided';
|
|
148
|
+
} else if (finalClientId === onDisk.clientId && finalMetaSiteId === onDisk.metaSiteId) {
|
|
149
|
+
deployed.wixConfig = 'already_set';
|
|
150
|
+
} else {
|
|
151
|
+
writeWixConfig(finalClientId, finalMetaSiteId);
|
|
152
|
+
deployed.wixConfig = 'written';
|
|
153
|
+
}
|
|
154
|
+
|
|
95
155
|
console.log(JSON.stringify(deployed));
|