@wix/agent-skills 1.27.0 → 1.29.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 +2 -2
- package/skills/wix-app/SKILL.md +1 -1
- package/skills/wix-app/references/APP_VALIDATION.md +5 -1
- package/skills/wix-app/references/SDK_MODULE_MAP.md +1 -1
- package/skills/wix-app/references/editor-react-component/PARTS.md +1 -1
- package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +1 -1
- package/skills/wix-app/references/stores/GET_PRODUCT.md +9 -1
- package/skills/wix-app/references/stores/INVENTORY.md +2 -0
- package/skills/wix-app/references/stores/QUERY.md +2 -2
- package/skills/wix-app/references/stores/WRITE.md +1 -1
- package/skills/wix-headless/references/astro.md +1 -1
- package/skills/wix-headless-kit/SKILL.md +4 -0
- package/skills/wix-headless-kit/guides/no-machine.md +115 -0
- package/skills/wix-headless-kit/install/attach.mjs +5 -3
- package/skills/wix-headless-kit/install/bootstrap.mjs +3 -1
- package/skills/wix-headless-kit/install/context.mjs +4 -2
- package/skills/wix-headless-kit/install/deploy.mjs +4 -2
- package/skills/wix-headless-kit/install/pins.json +8 -0
- package/skills/wix-headless-kit/install/setup.mjs +10 -8
- package/skills/wix-headless-kit/install/templates.mjs +18 -8
- package/skills/wix-headless-templates/donations/INSTRUCTIONS.md +8 -9
- package/skills/wix-headless-templates/donations/app/wix/donations/donate.ts +18 -45
- package/skills/wix-headless-templates/donations/app/wix/donations/donations-core.ts +18 -19
- package/skills/wix-headless-templates/donations/project/src/wix/donations/donate.ts +18 -45
- package/skills/wix-headless-templates/donations/project/src/wix/donations/donations-core.ts +18 -19
- package/skills/wix-headless-templates/donations/rest/donate.ts +13 -39
- package/skills/wix-headless-templates/pricing-plans/INSTRUCTIONS.md +4 -2
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/types.ts +1 -1
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/types.ts +1 -1
- package/skills/wix-headless-templates/restaurants/seed/SEED.md +4 -4
- package/skills/wix-headless-templates/restaurants/seed/seed-restaurants.mjs +1 -1
- package/skills/wix-headless-templates/shared/capabilities/site-search/seed/install.mjs +2 -2
- package/skills/wix-headless-templates/shared/seed/wix-cli.mjs +6 -3
- package/skills/wix-headless-templates/storefront/app/wix/storefront/cart.ts +1 -2
- package/skills/wix-headless-templates/storefront/project/src/wix/storefront/cart.ts +1 -2
- package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +1 -1
- package/skills/wix-manage/references/ecommerce/ecom-shipping.md +2 -2
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-coupon.md +1 -1
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule.md +2 -2
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-bundle-and-save.md +1 -1
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-seasonal-promotion.md +1 -1
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-stock-mover.md +2 -2
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-upsell-boost.md +3 -3
- package/skills/wix-manage/references/ecommerce/shipping/ecom-shipping-free-shipping.md +3 -3
- package/skills/wix-manage/references/ecommerce/shipping/ecom-shipping-optimize-rates.md +1 -1
- package/skills/wix-manage/references/ecommerce/shipping/ecom-shipping-setup-rates.md +3 -3
- package/skills/wix-manage/references/sites/upload-static-site.md +61 -42
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +1 -1
- package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.cjs +1 -1
|
@@ -8,7 +8,7 @@ description: "SEASONAL sub-flow — load [Goal: Seasonal Revenue] FIRST (it owns
|
|
|
8
8
|
>
|
|
9
9
|
> This flow is a sub-step, not a direct entry point. If you have not yet called `ReadFullDocsArticle` on [Goal: Seasonal Revenue](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-seasonal-revenue) in this conversation, **stop and load it now**. The goal skill owns the SEASONAL classification rule, the time-window presentation requirement, and the priority rule that gates access to this flow.
|
|
10
10
|
>
|
|
11
|
-
> **Before executing this flow**, also read [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) with `ReadFullDocsArticle` — it contains the discount-rule mechanics **and** the pre-create guardrails (conflict/stacking, margin floor, %-
|
|
11
|
+
> **Before executing this flow**, also read [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) with `ReadFullDocsArticle` — it contains the discount-rule mechanics **and** the pre-create guardrails (conflict/stacking, margin floor, %-plausibility).
|
|
12
12
|
|
|
13
13
|
Creates event-driven promotional discounts tied to holidays, shopping events, or seasonal milestones. The flow identifies upcoming events based on the site's country and current date, calculates optimal campaign start/end windows, and targets event-relevant product categories with appropriately sized discounts.
|
|
14
14
|
|
package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-stock-mover.md
CHANGED
|
@@ -6,7 +6,7 @@ description: "Stock-mover clearance sub-flow — load [Goal: Clear Inventory] FI
|
|
|
6
6
|
|
|
7
7
|
> **Routing rule (READ FIRST).** This recipe is a sub-step of [Goal: Clear Inventory](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-clear-inventory). If you arrived here directly from the WixREADME index, load the goal recipe NOW before executing — it owns the velocity scoring, classification cues, and the per-recommendation presentation rules (including the **margin-floor guardrail** surfacing requirement).
|
|
8
8
|
>
|
|
9
|
-
> **Then** read [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) with `ReadFullDocsArticle` — it contains the discount-rule mechanics **and** the pre-create guardrails (conflict/stacking, margin floor, %-
|
|
9
|
+
> **Then** read [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) with `ReadFullDocsArticle` — it contains the discount-rule mechanics **and** the pre-create guardrails (conflict/stacking, margin floor, %-plausibility).
|
|
10
10
|
|
|
11
11
|
Creates a discount targeting slow-moving inventory — products with high stock levels and low sales velocity. The discount depth is proportional to how overstocked the product is, with deeper discounts for the most stagnant items. Margin protection guardrails are especially important here since clearance discounts tend to push closer to cost.
|
|
12
12
|
|
|
@@ -99,7 +99,7 @@ If scope is CATEGORY, call `getCategoryIds` to convert category names to GUIDs.
|
|
|
99
99
|
|
|
100
100
|
## Step 6: Run guardrail checks
|
|
101
101
|
|
|
102
|
-
**Run the pre-create guardrails in [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) → "Guardrails" before creating the rule** (conflict/stacking, %-
|
|
102
|
+
**Run the pre-create guardrails in [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) → "Guardrails" before creating the rule** (conflict/stacking, %-plausibility, margin floor). Clearance is the **most margin-sensitive** case: discounts push closest to cost, so the margin-floor check (effective margin ≥ 15% unless the merchant overrides) is the one most likely to fire here — verify it per candidate product.
|
|
103
103
|
|
|
104
104
|
---
|
|
105
105
|
|
package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-upsell-boost.md
CHANGED
|
@@ -4,7 +4,7 @@ description: "UPSELL_BOOST sub-flow — load [Goal: Increase AOV] FIRST (it owns
|
|
|
4
4
|
---
|
|
5
5
|
# Flow: Upsell Boost Campaign
|
|
6
6
|
|
|
7
|
-
> **Before executing this skill**, read [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) with `ReadFullDocsArticle` — it contains the discount-rule mechanics **and** the pre-create guardrails (conflict/stacking, margin floor, %-
|
|
7
|
+
> **Before executing this skill**, read [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) with `ReadFullDocsArticle` — it contains the discount-rule mechanics **and** the pre-create guardrails (conflict/stacking, margin floor, %-plausibility).
|
|
8
8
|
|
|
9
9
|
Creates a discount that incentivizes customers to spend more per order by setting a minimum subtotal threshold above the store's current AOV. The discount percentage is scaled to the store's average profit margin, and the scope targets high-margin categories or products.
|
|
10
10
|
|
|
@@ -29,7 +29,7 @@ Catalog analytics and product data are already in conversation context — do NO
|
|
|
29
29
|
- `siteData.aov` — site-level AOV (revenue / ordersCount). Loaded by eCommerce Load Context.
|
|
30
30
|
|
|
31
31
|
Extract from context:
|
|
32
|
-
- `effective_aov` — use `siteData.aov`; run AOV
|
|
32
|
+
- `effective_aov` — use `siteData.aov`; run AOV plausibility check: if AOV < price_p25, override with price_p50 as effective AOV
|
|
33
33
|
- `avg_profit_margin` — from the "All Products" group in `siteData.catalogAnalytics`
|
|
34
34
|
- `price_p50`, `price_p75`, `price_p90` — from quantiles in `siteData.catalogAnalytics`
|
|
35
35
|
- Top products by price and order volume — from `siteData.productCatalogData`
|
|
@@ -90,7 +90,7 @@ Max 3 categoryIds per discount rule.
|
|
|
90
90
|
|
|
91
91
|
## Step 6: Run guardrail checks
|
|
92
92
|
|
|
93
|
-
**Run the pre-create guardrails in [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) → "Guardrails" before creating the rule** — conflict/stacking (scope, time, coupon cross-stacking), the 25% cap, the 15% margin floor, and %-
|
|
93
|
+
**Run the pre-create guardrails in [Create Discount Rule](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/pricing-create-discount-rule) → "Guardrails" before creating the rule** — conflict/stacking (scope, time, coupon cross-stacking), the 25% cap, the 15% margin floor, and %-plausibility. Present any warnings to the merchant and get confirmation before proceeding.
|
|
94
94
|
|
|
95
95
|
---
|
|
96
96
|
|
|
@@ -8,7 +8,7 @@ description: Creates a free shipping option with an AOV-calibrated threshold to
|
|
|
8
8
|
|
|
9
9
|
> **Before executing this skill**, read [Setup: Shipping Rates](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/shipping-set-up-rates) with `ReadFullDocsArticle` for the rate-object mechanics.
|
|
10
10
|
|
|
11
|
-
## Rate pricing
|
|
11
|
+
## Rate pricing plausibility (inline guardrail)
|
|
12
12
|
|
|
13
13
|
Validate every rate you create or update against the store's AOV; flag any that fail:
|
|
14
14
|
|
|
@@ -101,7 +101,7 @@ If the threshold needs adjustment, update the shipping option via PATCH (see Ste
|
|
|
101
101
|
|
|
102
102
|
---
|
|
103
103
|
|
|
104
|
-
## Step 3: Run AOV
|
|
104
|
+
## Step 3: Run AOV plausibility check
|
|
105
105
|
|
|
106
106
|
Before calculating a threshold, validate that AOV is reliable by comparing it against catalog price distribution.
|
|
107
107
|
|
|
@@ -263,7 +263,7 @@ Report to the merchant:
|
|
|
263
263
|
| `deliveryRegionId is not a valid GUID` | Used `deliveryRegionIds` (plural) instead of `deliveryRegionId` (singular) | Use the singular `deliveryRegionId` field |
|
|
264
264
|
| `SHIPPING_OPTION_NOT_FOUND` | Option ID doesn't exist when trying to update | Re-query shipping options to get current IDs |
|
|
265
265
|
| `REVISION_MISMATCH` | Revision doesn't match the current version when updating | Re-fetch the option for the latest revision, then retry |
|
|
266
|
-
| Threshold seems unreasonable | AOV data is unreliable (too few orders, data anomaly) | Run the AOV
|
|
266
|
+
| Threshold seems unreasonable | AOV data is unreliable (too few orders, data anomaly) | Run the AOV plausibility check (Step 3) and use `effective_aov` instead of raw AOV |
|
|
267
267
|
| Free shipping not visible at checkout | Region linked to the option has `active=false` | Check region active status and activate if intended |
|
|
268
268
|
|
|
269
269
|
## References
|
|
@@ -6,7 +6,7 @@ description: Analyzes catalog price distribution and current rate structure to r
|
|
|
6
6
|
|
|
7
7
|
> **Routing rule:** BEFORE taking any action, call `ReadFullDocsArticle` on [Shipping API Reference](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/shipping-api-reference). The Query Shipping Options and Update/Create Shipping Option endpoints used in Steps 2–4 live there. Do NOT query or modify any shipping options without loading it first.
|
|
8
8
|
|
|
9
|
-
## Rate pricing
|
|
9
|
+
## Rate pricing plausibility (inline guardrail)
|
|
10
10
|
|
|
11
11
|
Validate every rate you create or update against the store's AOV; flag any that fail:
|
|
12
12
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Shipping: Set Up Rates"
|
|
3
|
-
description: Configures shipping option rates — rate types (flat, tiered, free), condition types and operators, free shipping threshold calibration, AOV
|
|
3
|
+
description: Configures shipping option rates — rate types (flat, tiered, free), condition types and operators, free shipping threshold calibration, AOV plausibility check, per-item penalty avoidance, and tier gap detection.
|
|
4
4
|
---
|
|
5
5
|
# Shipping Rates
|
|
6
6
|
|
|
7
|
-
## AOV
|
|
7
|
+
## AOV Plausibility Check
|
|
8
8
|
|
|
9
9
|
**MANDATORY before any threshold calculation that references AOV.** Raw AOV can be misleading due to data issues or bulk purchases.
|
|
10
10
|
|
|
@@ -80,6 +80,6 @@ When ALL of the following are true, flat rate is optimal and no change is needed
|
|
|
80
80
|
|
|
81
81
|
Sort all conditions by value and look for gaps between ranges. Gaps mean some cart totals have no matching rate, which can cause checkout failures.
|
|
82
82
|
|
|
83
|
-
## Shipping Cost
|
|
83
|
+
## Shipping Cost Plausibility Check
|
|
84
84
|
|
|
85
85
|
Any rate `amount > AOV x 0.15` (15% of average order value) should be flagged as a cart abandonment risk.
|
|
@@ -16,7 +16,7 @@ Five ways to get the files live; what you have decides which are open to you.
|
|
|
16
16
|
| Option | Needs | Carries | The user ends up with |
|
|
17
17
|
| --- | --- | --- | --- |
|
|
18
18
|
| **A.** `curl` + CLI token → [into the account](#publish-into-the-users-account) | A shell; a Wix CLI login | Anything on disk | A site in their account, final URL |
|
|
19
|
-
| **B.** `ExecuteWixAPI` → [into the account](#publish-into-the-users-account) | The Wix MCP |
|
|
19
|
+
| **B.** `ExecuteWixAPI` → [into the account](#publish-into-the-users-account) | The Wix MCP | Files already in the conversation — text as is, small binaries as base64 — and anything downloaded from the site | A site in their account, final URL |
|
|
20
20
|
| **C.** `curl` → [anonymous](#publish-anonymously) | A shell | Anything on disk | A live site for one hour; kept by a [claim](#claim-it-into-the-users-account) (through the Wix MCP or a CLI token) or the save link |
|
|
21
21
|
| **D.** [The drop page](#the-drop-page) | Nothing | Whatever the user uploads | The same, after they upload it themselves |
|
|
22
22
|
| **E.** [The headless skill](#keep-building-add-a-backend-when-you-need-one) | A shell; Node; a Wix CLI login | A project folder, source included (built for you) | A site in their account as a Wix Headless project, released with the Wix CLI, ready for Wix Business Solutions |
|
|
@@ -30,8 +30,13 @@ What sets them apart:
|
|
|
30
30
|
byte is written out inside the call. That costs nothing extra for a page you
|
|
31
31
|
generated or the user pasted (it's already in the conversation); for files on
|
|
32
32
|
disk it means reading them in and writing them back out, and each change
|
|
33
|
-
resends all of it.
|
|
34
|
-
|
|
33
|
+
resends all of it. Files travel in the tool's `files` param — text raw, a
|
|
34
|
+
binary file (PNG, JPG, fonts) as base64 — and `wix.multipart()` builds the
|
|
35
|
+
upload body (below). Base64 costs about a third more than the file and every
|
|
36
|
+
byte is tokens, so it suits small assets (an icon, a logo, a font) and files
|
|
37
|
+
you downloaded from the site to change; a photo goes in by absolute URL
|
|
38
|
+
(`<img src="https://…">`) or with `curl` from a shell. The bundle is capped at
|
|
39
|
+
4M characters.
|
|
35
40
|
- **A CLI login** is one approval by the user in the browser: run
|
|
36
41
|
`npx @wix/cli login` and have them approve; `npx @wix/cli token` then prints a
|
|
37
42
|
token (see [Before the calls](#before-the-calls)). It also unlocks later
|
|
@@ -43,8 +48,8 @@ What sets them apart:
|
|
|
43
48
|
the only one that takes framework source as is and leaves a project ready for a
|
|
44
49
|
backend. A drop site can still move to it [later](#keep-building-add-a-backend-when-you-need-one).
|
|
45
50
|
|
|
46
|
-
So: a
|
|
47
|
-
shell or not. Static files on disk — A with a CLI login, else C (claimed through
|
|
51
|
+
So: a site already in the conversation — pages, styles, a logo — with the Wix
|
|
52
|
+
MCP connected — B, shell or not. Static files on disk — A with a CLI login, else C (claimed through
|
|
48
53
|
the Wix MCP when it's connected). A framework project (a `package.json`), or a
|
|
49
54
|
site that needs stores, bookings, a CMS or members from the start — E. Files out
|
|
50
55
|
of your reach, or nothing above fits — D.
|
|
@@ -108,8 +113,27 @@ curl -sS -X POST \
|
|
|
108
113
|
"siteUrl": "https://headless-zjfqzddjtww-northwind-1406.wix-site-host.com" }
|
|
109
114
|
```
|
|
110
115
|
|
|
111
|
-
Option B — the same two calls as one `ExecuteWixAPI` script, for
|
|
112
|
-
|
|
116
|
+
Option B — the same two calls as one `ExecuteWixAPI` script, for files already
|
|
117
|
+
in the conversation. The files go in the tool's **`files` param**, not in
|
|
118
|
+
`code`: one bundle, each file introduced by a line `=== FILE: <path> ===` and
|
|
119
|
+
followed by its raw text, `<path>` relative to the site root. A binary file is
|
|
120
|
+
introduced by `=== FILE: <path> base64 ===` and followed by its base64. Nothing
|
|
121
|
+
in it is escaped, so quotes, backticks, `${}` and backslashes arrive as written.
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
=== FILE: index.html ===
|
|
125
|
+
<!doctype html><html><head><title>Northwind Studio</title>
|
|
126
|
+
<link rel="stylesheet" href="assets/styles.css"></head><body><h1>Northwind Studio</h1><img src="assets/logo.png"></body></html>
|
|
127
|
+
=== FILE: assets/styles.css ===
|
|
128
|
+
body { font-family: sans-serif; margin: 0; padding: 4rem; }
|
|
129
|
+
=== FILE: assets/logo.png base64 ===
|
|
130
|
+
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
In `code`, the bundle is the `files` global (`[{ path, content, encoding? }]`,
|
|
134
|
+
`encoding: 'base64'` on the binary entries) and `wix.multipart()` turns it into
|
|
135
|
+
the upload body: one part named `files` per file, the path as its filename, a
|
|
136
|
+
content type guessed from the extension, base64 entries decoded to their bytes.
|
|
113
137
|
|
|
114
138
|
```javascript
|
|
115
139
|
async function run() {
|
|
@@ -117,31 +141,21 @@ async function run() {
|
|
|
117
141
|
url: 'https://www.wixapis.com/headless-business-setup/v1/headless-business/provision',
|
|
118
142
|
body: { origin: 'drop', newMetasite: { namingStrategy: { metaSiteName: 'Northwind Studio' }, seedOptions: [] },
|
|
119
143
|
synchronousSteps: ['SET_METASITE_NAME', 'CONFIGURE_HEADLESS_APP'] } });
|
|
120
|
-
|
|
121
|
-
// (an unescaped \ is dropped or reinterpreted: /\d+/ would arrive as /d+/).
|
|
122
|
-
const files = {
|
|
123
|
-
'index.html': `<!doctype html><html><head><title>Northwind Studio</title>
|
|
124
|
-
<link rel="stylesheet" href="assets/styles.css"></head><body><h1>Northwind Studio</h1></body></html>`,
|
|
125
|
-
'assets/styles.css': `body { font-family: sans-serif; margin: 0; padding: 4rem; }`,
|
|
126
|
-
};
|
|
127
|
-
const boundary = '----wixdropboundary';
|
|
128
|
-
const body = Object.entries(files).flatMap(([path, text]) => [
|
|
129
|
-
'--' + boundary,
|
|
130
|
-
`Content-Disposition: form-data; name="files"; filename="${path}"`,
|
|
131
|
-
'', text,
|
|
132
|
-
]).concat('--' + boundary + '--', '').join('\r\n');
|
|
144
|
+
const mp = wix.multipart(); // the `files` param; or pass [{ path, content | base64 | bytes }]
|
|
133
145
|
return await wix.request({ scope: 'account', method: 'POST',
|
|
134
146
|
url: `https://www.wixapis.com/headless-business-setup/v1/headless-business/${created.data.metaSiteId}/drop`,
|
|
135
|
-
headers: { 'Content-Type':
|
|
136
|
-
body });
|
|
147
|
+
headers: { 'Content-Type': mp.contentType },
|
|
148
|
+
body: mp.body });
|
|
137
149
|
}
|
|
138
150
|
```
|
|
139
151
|
|
|
140
152
|
`wix.request` returns `{ status, data }`; read a response's fields from `data`
|
|
141
|
-
(`created.data.metaSiteId`).
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
153
|
+
(`created.data.metaSiteId`). Don't build the multipart body by hand — a missing
|
|
154
|
+
`\r\n` or a boundary mismatch is a bare `500` — and don't put file text inside
|
|
155
|
+
`code` as string literals: that second layer of escaping is what corrupts
|
|
156
|
+
backslashes and `${}`. Don't put image bytes in `code` either — they're a
|
|
157
|
+
`base64` entry in `files`. The one thing `files` cannot carry is a file with a
|
|
158
|
+
line that reads exactly `=== FILE: … ===`.
|
|
145
159
|
|
|
146
160
|
`siteUrl` is the site's final address — it's already in the user's account. Give
|
|
147
161
|
the user two links: `siteUrl`, and its dashboard at
|
|
@@ -169,24 +183,28 @@ unzip -o current.zip -d current # the site's files + wix.config.json
|
|
|
169
183
|
```
|
|
170
184
|
|
|
171
185
|
In an `ExecuteWixAPI` script, request the same URL with `responseType: 'base64'`
|
|
172
|
-
and
|
|
186
|
+
and unzip it in memory with `wix.unzip()`. Each entry is `{ path, bytes, text() }`:
|
|
187
|
+
`bytes` is the file as stored, `text()` decodes it when it's text. Don't decode
|
|
188
|
+
every entry — an image run through a text decoder is corrupted.
|
|
173
189
|
|
|
174
190
|
```javascript
|
|
175
191
|
const r = await wix.request({ scope: 'account', method: 'GET', responseType: 'base64',
|
|
176
192
|
url: `https://www.wix.com/_api/wixstro-deployments/v1/instant-sites/${metaSiteId}/download.zip` });
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
193
|
+
const entries = await wix.unzip(r.data);
|
|
194
|
+
// entries: [{ path: 'index.html', bytes, text() }, { path: 'assets/logo.png', bytes, text() }, { path: 'wix.config.json', … }]
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Edit in memory — text through `text()`, binaries left as they are — then drop
|
|
198
|
+
the full set back in the same script, leaving `wix.config.json` out. Entries go
|
|
199
|
+
to `wix.multipart()` as they are; an edited file replaces its entry with
|
|
200
|
+
`{ path, content }`:
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
const edited = entries.filter((e) => e.path !== 'wix.config.json').map((e) =>
|
|
204
|
+
e.path === 'index.html' ? { path: e.path, content: e.text().replace('Northwind Studio', 'Northwind Studio — Est. 1998') } : e);
|
|
205
|
+
const mp = wix.multipart(edited);
|
|
206
|
+
await wix.request({ scope: 'account', method: 'POST', headers: { 'Content-Type': mp.contentType }, body: mp.body,
|
|
207
|
+
url: `https://www.wixapis.com/headless-business-setup/v1/headless-business/${metaSiteId}/drop` });
|
|
190
208
|
```
|
|
191
209
|
|
|
192
210
|
The live URL itself (`*.wix-site-host.com`) can't be read from a script; this
|
|
@@ -219,7 +237,8 @@ Keep both: `metaSiteId` addresses the site, `projectId` builds the save link.
|
|
|
219
237
|
### 2. Upload the files
|
|
220
238
|
|
|
221
239
|
Same multipart shape as the [drop](#2-drop-the-files--the-site-goes-live), to the
|
|
222
|
-
upload path, with the attribution parameters:
|
|
240
|
+
upload path, with the attribution parameters (in a script: `wix.multipart()` with
|
|
241
|
+
the `files` param, posted to this URL):
|
|
223
242
|
|
|
224
243
|
```bash
|
|
225
244
|
curl -sS -X POST \
|
|
@@ -323,7 +342,7 @@ Failures come back as HTTP 400 with a code in `details.applicationError.code`:
|
|
|
323
342
|
- **`403 PERMISSION_DENIED` on a drop** — the token expired or is missing (see
|
|
324
343
|
[Before the calls](#before-the-calls)), or the site isn't the caller's. A site
|
|
325
344
|
that's still anonymous is changed by upload + release, not by a drop.
|
|
326
|
-
- **`500` on a drop or upload** — the multipart body is malformed (see the shape
|
|
345
|
+
- **`500` on a drop or upload** — the multipart body was built by hand and is malformed (see the shape
|
|
327
346
|
above). Rebuild it from the example; sending it again unchanged fails the
|
|
328
347
|
same way.
|
|
329
348
|
- **`404` on the anonymous route after step 1** — the hour passed or the site was
|
|
@@ -1624,7 +1624,7 @@ function normalizeV5Contact(contact = {}) {
|
|
|
1624
1624
|
return normalized;
|
|
1625
1625
|
}
|
|
1626
1626
|
// Legacy V4-style `info` payloads (pre-GA generated transforms) convert through this
|
|
1627
|
-
// STRICT
|
|
1627
|
+
// STRICT allowlist: unknown keys throw instead of silently dropping source data.
|
|
1628
1628
|
// `extendedFields` and `labelKeys` throw because they have no mechanical V5 equivalent —
|
|
1629
1629
|
// V5 custom fields live under extendedFields.namespaces (Data Extension Schema) and
|
|
1630
1630
|
// labels became tags (Tags API); both need a setup-time decision, not a converter guess.
|
|
@@ -326,7 +326,7 @@ async function enableOnlineReservations(ctx, reservationLocationId, revision) {
|
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
// ══ EXPERIENCES (setup-restaurant-experiences.md) ══════════════════════════════════════════════════
|
|
329
|
-
// An experience is a reservation that IS a curated dining occasion (
|
|
329
|
+
// An experience is a reservation that IS a curated dining occasion (chef's table, tasting menu). Feature
|
|
330
330
|
// of the Table Reservations app — no separate install. Created against a reservationLocationId (from
|
|
331
331
|
// listReservationLocations). The full create payload lives in the live docs (fields evolve) — build each
|
|
332
332
|
// `experience` from the Create-Experience doc; this only wires the loop. Set configuration.visible:true.
|