@wix/agent-skills 1.16.2 → 1.17.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 +134 -120
- package/skills/wix-app/references/EMBEDDED_SCRIPT.md +6 -0
- package/skills/wix-app/references/SITE_PLUGIN.md +2 -2
- package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +2 -2
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +182 -99
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +92 -47
- package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +15 -6
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +275 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +29 -42
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +153 -449
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +66 -19
- package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +53 -158
- package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +78 -0
- package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +42 -134
- package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +27 -0
- package/skills/wix-app/references/editor-react-component/PARTS.md +45 -24
- package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +63 -179
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +79 -163
- package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +36 -21
- package/skills/wix-app/references/editor-react-component/SSR.md +30 -99
- package/skills/wix-base44-connector/SKILL.md +34 -17
- package/skills/wix-base44-connector/scripts/utils.js +33 -25
- package/skills/wix-headless/entry/bootstrap.mjs +9 -2
- package/skills/wix-headless/references/SDK_HANDOFF.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +42 -23
- package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +10 -8
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +27 -24
- package/skills/wix-headless/references/managed/AUTHENTICATION.md +5 -0
- package/skills/wix-manage/SKILL.md +14 -2
- package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +20 -13
- package/skills/wix-manage/references/bookings/create-class-service.md +1 -1
- package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +24 -11
- package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +5 -5
- package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +182 -5
- package/skills/wix-manage/references/seo/manage-seo-tags.md +315 -0
- package/skills/wix-manage/references/seo/manage-url-redirects.md +250 -0
- package/skills/wix-manage/references/sites/query-sites.md +72 -161
- package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +5 -6
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +13 -9
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +10 -7
- package/skills/wix-vibe-headless/platforms/base44.md +13 -10
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +2 -0
- package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +9 -8
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +4 -1
- package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +23 -11
- package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +1 -1
- package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +29 -31
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +15 -8
- package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +37 -38
- package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +2 -2
- package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +35 -35
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +0 -172
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +0 -143
- package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +0 -484
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +0 -225
- package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +0 -6
- package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +0 -95
|
@@ -1,173 +1,58 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "Query Sites"
|
|
3
|
-
description:
|
|
3
|
+
description: List, count, and find the sites in a Wix account. Covers the namespace filter for headless sites, counting before enumerating, cursor pagination, and resolving a site by name.
|
|
4
4
|
---
|
|
5
5
|
# Query Sites
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
List, count, and find the sites in a Wix account.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- **Auth**: account-level (a Wix user token, or an account-level API key). `wix token` prints one.
|
|
10
|
+
- **Permission**: `SITE_LIST.READ` (scope `SCOPE.ACC-DC-OS.READ-SITE`).
|
|
11
|
+
- **Endpoints**: list `POST https://www.wixapis.com/site-list/v2/sites/query` · count
|
|
12
|
+
`POST https://www.wixapis.com/site-list/v2/sites/count`.
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
- Permission `SITE_LIST.READ` (scope `SCOPE.ACC-DC-OS.READ-SITE`)
|
|
14
|
+
## Include headless sites — filter by `namespace`
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
Both endpoints see only `WIX`-namespace sites by default; **headless sites** (anything built on a
|
|
17
|
+
connected OAuth app) are silently excluded. Filter on both namespaces to see everything:
|
|
15
18
|
|
|
16
|
-
- **Query Sites API**: [REST](https://dev.wix.com/docs/api-reference/account-level/sites/sites/query-sites)
|
|
17
|
-
|
|
18
|
-
> Returns up to **100** sites per request. Use cursor paging (below) to retrieve more.
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Query Sites
|
|
23
|
-
|
|
24
|
-
**Endpoint**: `POST https://www.wixapis.com/site-list/v2/sites/query`
|
|
25
|
-
|
|
26
|
-
The request takes a `query` object that supports `filter`, `sort`, and `cursorPaging`.
|
|
27
|
-
|
|
28
|
-
**Request Body**:
|
|
29
|
-
```json
|
|
30
|
-
{
|
|
31
|
-
"query": {
|
|
32
|
-
"filter": { "editorType": "EDITOR" },
|
|
33
|
-
"sort": [{ "fieldName": "createdDate", "order": "ASC" }],
|
|
34
|
-
"cursorPaging": { "limit": 50 }
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
All three fields are optional — `{ "query": { "cursorPaging": { "limit": 50 } } }` lists every site.
|
|
40
|
-
|
|
41
|
-
**Request**:
|
|
42
19
|
```bash
|
|
43
|
-
curl -X POST \
|
|
44
|
-
'
|
|
45
|
-
-
|
|
46
|
-
-H 'Content-Type: application/json' \
|
|
47
|
-
-d '{
|
|
48
|
-
"query": {
|
|
49
|
-
"filter": { "editorType": "EDITOR" },
|
|
50
|
-
"sort": [{ "fieldName": "createdDate", "order": "ASC" }],
|
|
51
|
-
"cursorPaging": { "limit": 50 }
|
|
52
|
-
}
|
|
53
|
-
}'
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## Response Structure
|
|
59
|
-
|
|
60
|
-
The response has the sites array plus **two** paging objects: a top-level `cursorPaging`
|
|
61
|
-
(echoes the applied limit and the next cursor) and `metadata` (count, `cursors.next`, `hasNext`).
|
|
62
|
-
|
|
63
|
-
> ⚠️ There is **no** `pagingMetadata` field. Read paging info from `metadata`.
|
|
64
|
-
|
|
65
|
-
```json
|
|
66
|
-
{
|
|
67
|
-
"sites": [
|
|
68
|
-
{
|
|
69
|
-
"id": "f6061c5f-6aa3-42f8-8822-36a4981dabb2",
|
|
70
|
-
"htmlAppId": "70df538d-906c-44ca-9f27-c186b62f2b2b",
|
|
71
|
-
"name": "my-site-47",
|
|
72
|
-
"displayName": "My Site 47",
|
|
73
|
-
"createdDate": "2023-02-01T14:56:09.831Z",
|
|
74
|
-
"updatedDate": "2026-06-22T03:55:49.031Z",
|
|
75
|
-
"published": true,
|
|
76
|
-
"premium": false,
|
|
77
|
-
"viewUrl": "https://username.wixsite.com/my-site-47",
|
|
78
|
-
"editUrl": "/editor/f6061c5f-6aa3-42f8-8822-36a4981dabb2?editorSessionId=...",
|
|
79
|
-
"thumbnail": "/site-thumbnail/f6061c5f-6aa3-42f8-8822-36a4981dabb2",
|
|
80
|
-
"ownerAccountId": "e6a89eda-d100-4b2d-8a47-3040e2134497",
|
|
81
|
-
"contributorAccountIds": [],
|
|
82
|
-
"editorType": "EDITOR",
|
|
83
|
-
"blocked": false,
|
|
84
|
-
"namespace": "WIX",
|
|
85
|
-
"domainConnected": false,
|
|
86
|
-
"parentChildRole": "NONE"
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
"cursorPaging": {
|
|
90
|
-
"limit": 50,
|
|
91
|
-
"cursor": "<cursor-for-next-page>"
|
|
92
|
-
},
|
|
93
|
-
"metadata": {
|
|
94
|
-
"count": 50,
|
|
95
|
-
"cursors": {
|
|
96
|
-
"next": "<cursor-for-next-page>"
|
|
97
|
-
},
|
|
98
|
-
"hasNext": true
|
|
99
|
-
}
|
|
100
|
-
}
|
|
20
|
+
curl -X POST 'https://www.wixapis.com/site-list/v2/sites/query' \
|
|
21
|
+
-H 'Authorization: <ACCOUNT_TOKEN>' -H 'Content-Type: application/json' \
|
|
22
|
+
-d '{ "query": { "filter": { "namespace": { "$in": ["WIX", "HEADLESS"] } }, "cursorPaging": { "limit": 100 } } }'
|
|
101
23
|
```
|
|
102
24
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
Each entry in `sites` has these fields (from the `Site` schema):
|
|
106
|
-
|
|
107
|
-
| Field | Type | Notes |
|
|
108
|
-
|---|---|---|
|
|
109
|
-
| `id` | string | Site ID — use for site-level API calls |
|
|
110
|
-
| `htmlAppId` | string | Internal HTML app ID |
|
|
111
|
-
| `name` | string | URL slug / internal name |
|
|
112
|
-
| `displayName` | string | Human-readable site name |
|
|
113
|
-
| `createdDate` / `updatedDate` | datetime | |
|
|
114
|
-
| `trashedDate` | datetime | Present only if the site is in the trash |
|
|
115
|
-
| `published` | boolean | Whether the site is published |
|
|
116
|
-
| `premium` | boolean | Whether the site has a Wix Premium (paid) plan |
|
|
117
|
-
| `viewUrl` | string | Public site address; empty string when unpublished. **There is no `siteUrl` field.** |
|
|
118
|
-
| `editUrl` | string | Relative editor path; prefix with `https://manage.wix.com` to open |
|
|
119
|
-
| `thumbnail` | string | Relative thumbnail path |
|
|
120
|
-
| `ownerAccountId` | string | |
|
|
121
|
-
| `contributorAccountIds` | string[] | |
|
|
122
|
-
| `editorType` | string | e.g. `EDITOR`, `ODEDITOR` — also a valid `filter` field |
|
|
123
|
-
| `blocked` | boolean | |
|
|
124
|
-
| `folderId` / `parentId` | string | Set for sites organized in folders / parent-child setups |
|
|
125
|
-
| `namespace` | string | e.g. `WIX` |
|
|
126
|
-
| `domainConnected` | boolean | |
|
|
127
|
-
| `parentChildRole` | string | e.g. `NONE` |
|
|
25
|
+
`query` takes optional `filter`, `sort` (e.g. `[{ "fieldName": "createdDate", "order": "DESC" }]`),
|
|
26
|
+
and `cursorPaging` (max `limit` 100).
|
|
128
27
|
|
|
129
|
-
|
|
28
|
+
## Count before you enumerate
|
|
130
29
|
|
|
131
|
-
|
|
30
|
+
An account can hold thousands of sites. To find one by name, search (see "Find a site by name")
|
|
31
|
+
rather than enumerate. To walk the whole list, count first and decide whether that's worth it:
|
|
132
32
|
|
|
133
|
-
|
|
134
|
-
|
|
33
|
+
```bash
|
|
34
|
+
curl -X POST 'https://www.wixapis.com/site-list/v2/sites/count' \
|
|
35
|
+
-H 'Authorization: <ACCOUNT_TOKEN>' -H 'Content-Type: application/json' \
|
|
36
|
+
-d '{ "filter": { "namespace": { "$in": ["WIX", "HEADLESS"] } } }' # → { "count": 1335 }
|
|
37
|
+
```
|
|
135
38
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
> want a non-default page size) — do **not** repeat `filter` or `sort`.
|
|
39
|
+
Enumerating costs **~0.7s per 100 sites** (100 → ~0.7s, 500 → ~3.4s, ~1,300 → ~9s). For a large
|
|
40
|
+
count, render the first N sites with a "…and N more" note instead of fetching all of them.
|
|
139
41
|
|
|
140
|
-
|
|
141
|
-
```json
|
|
142
|
-
{
|
|
143
|
-
"query": {
|
|
144
|
-
"filter": { "editorType": "EDITOR" },
|
|
145
|
-
"sort": [{ "fieldName": "createdDate", "order": "ASC" }],
|
|
146
|
-
"cursorPaging": { "limit": 50 }
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
```
|
|
42
|
+
## Paginate
|
|
150
43
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
{
|
|
154
|
-
"query": {
|
|
155
|
-
"cursorPaging": {
|
|
156
|
-
"limit": 50,
|
|
157
|
-
"cursor": "<metadata.cursors.next from previous response>"
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
```
|
|
44
|
+
The next cursor is at `metadata.cursors.next` (there is **no** `pagingMetadata` field); it already
|
|
45
|
+
encodes the filter/sort, so follow-up pages send only the cursor:
|
|
162
46
|
|
|
163
|
-
**Loop**:
|
|
164
47
|
```javascript
|
|
165
|
-
async function listAllSites() {
|
|
48
|
+
async function listAllSites(wixPost) {
|
|
166
49
|
const sites = [];
|
|
167
50
|
let cursor = null;
|
|
168
51
|
do {
|
|
169
|
-
const
|
|
170
|
-
|
|
52
|
+
const query = cursor
|
|
53
|
+
? { cursorPaging: { limit: 100, cursor } }
|
|
54
|
+
: { filter: { namespace: { $in: ["WIX", "HEADLESS"] } }, cursorPaging: { limit: 100 } };
|
|
55
|
+
const res = await wixPost("/site-list/v2/sites/query", { query });
|
|
171
56
|
sites.push(...res.sites);
|
|
172
57
|
cursor = res.metadata.hasNext ? res.metadata.cursors.next : null;
|
|
173
58
|
} while (cursor);
|
|
@@ -175,23 +60,49 @@ async function listAllSites() {
|
|
|
175
60
|
}
|
|
176
61
|
```
|
|
177
62
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
## Common Use Cases
|
|
63
|
+
## Find a site by name
|
|
181
64
|
|
|
182
|
-
|
|
183
|
-
|
|
65
|
+
Substring-search by display name with `GET manage.wix.com/account/sites/api/sites/search`. It
|
|
66
|
+
returns full site records (headless included) and, with `getCount=true`, the total:
|
|
184
67
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
68
|
+
```bash
|
|
69
|
+
curl 'https://manage.wix.com/account/sites/api/sites/search?query=kintsugi&getCount=true' \
|
|
70
|
+
-H 'Authorization: <ACCOUNT_TOKEN>' -H 'accept: application/json'
|
|
71
|
+
# → { "sites": [ { "metaSiteId", "displayName", "namespace", "published", "editUrl", … } ], "totalCount": 5 }
|
|
72
|
+
```
|
|
189
73
|
|
|
190
|
-
|
|
74
|
+
## Response — the `Site` object
|
|
75
|
+
|
|
76
|
+
`sites` is an array of:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
interface Site {
|
|
80
|
+
id: string; // site ID — use for site-level API calls
|
|
81
|
+
htmlAppId: string;
|
|
82
|
+
name: string; // URL slug / internal name; opaque `headless-<id>` for headless sites
|
|
83
|
+
displayName: string; // human-readable name
|
|
84
|
+
createdDate: string; // ISO datetime
|
|
85
|
+
updatedDate: string; // ISO datetime
|
|
86
|
+
trashedDate?: string; // present only when the site is in the trash
|
|
87
|
+
published: boolean;
|
|
88
|
+
premium: boolean; // has a Wix Premium (paid) plan
|
|
89
|
+
viewUrl: string; // public address; "" when unpublished (there is no `siteUrl` field)
|
|
90
|
+
editUrl: string; // relative; prefix with https://manage.wix.com to open
|
|
91
|
+
thumbnail: string;
|
|
92
|
+
ownerAccountId: string;
|
|
93
|
+
contributorAccountIds: string[];
|
|
94
|
+
editorType: string; // EDITOR | ODEDITOR | STUDIO | EDITORLESS
|
|
95
|
+
blocked: boolean;
|
|
96
|
+
folderId?: string; // set for sites organized in folders / parent-child setups
|
|
97
|
+
namespace: string; // WIX | HEADLESS
|
|
98
|
+
domainConnected: boolean;
|
|
99
|
+
parentChildRole: string; // e.g. NONE
|
|
100
|
+
}
|
|
101
|
+
```
|
|
191
102
|
|
|
192
103
|
## Next Steps
|
|
193
104
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
105
|
+
Use a site's `id` for site-level API calls — derive a site token from the account token
|
|
106
|
+
(`wix token --site <id>`, or the `oauth2/token` refresh-grant in wix-auth `device-flow`), then read
|
|
107
|
+
its context via [Read Site Context](read-site-context.md) or create sites with
|
|
108
|
+
[Create Site from Template](create-site-from-template.md).
|
|
@@ -25,8 +25,7 @@ This distinction must stay explicit in mapper output.
|
|
|
25
25
|
It owns the purchase flow and operational commerce entities that are reused across multiple vertical apps.
|
|
26
26
|
|
|
27
27
|
Typical `eCommerce` entities:
|
|
28
|
-
- carts
|
|
29
|
-
- checkouts
|
|
28
|
+
- carts (the unified cart + checkout entity)
|
|
30
29
|
- orders
|
|
31
30
|
- order billing / refunds
|
|
32
31
|
- payment and fulfillment state tied to orders
|
|
@@ -90,19 +89,19 @@ Main page:
|
|
|
90
89
|
- [Integrating with Wix's Business Solutions](https://dev.wix.com/docs/build-apps/get-started/overview/integrating-with-wix-s-business-solutions)
|
|
91
90
|
|
|
92
91
|
Short description:
|
|
93
|
-
- Shared commerce platform for purchase flow and order operations. It is the canonical target for carts
|
|
92
|
+
- Shared commerce platform for purchase flow and order operations. It is the canonical target for carts (Cart V2, which now also covers checkout) and orders, even when catalog data originates in a vertical app such as Stores or Bookings.
|
|
94
93
|
|
|
95
94
|
Primary entities:
|
|
96
95
|
|
|
97
96
|
| Entity | What it does | Docs |
|
|
98
97
|
| --- | --- | --- |
|
|
99
|
-
| `cart` |
|
|
100
|
-
| `current-cart` |
|
|
101
|
-
| `checkout` | Second phase of purchase flow; holds calculated prices, tax, billing, shipping, and discount state before order creation | [About the eCommerce Checkout API](https://dev.wix.com/docs/sdk/backend-modules/ecom/checkout/introduction) |
|
|
98
|
+
| `cart` | The unified purchase-flow entity — holds line items, buyer/contact info, discounts, delivery, billing, and payment context all the way through placing the order. | [About the Cart API](https://dev.wix.com/docs/rest/business-solutions/e-commerce/purchase-flow/cart-v2/introduction) |
|
|
99
|
+
| `current-cart` | The current cart for a visitor/member session — the same entity as `cart`, addressed by the shopper's session rather than a cart id. | [About the Cart API](https://dev.wix.com/docs/rest/business-solutions/e-commerce/purchase-flow/cart-v2/introduction) |
|
|
102
100
|
| `order` | Final commerce record for completed or externally recorded purchases | [About the Orders API](https://dev.wix.com/docs/rest/business-solutions/e-commerce/orders/orders/introduction) |
|
|
103
101
|
| `order-billing` | Payment capture, void, and refund operations for eCommerce orders | [About the Order Billing API](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/orders/order-billing/introduction) |
|
|
104
102
|
|
|
105
103
|
Mapper notes:
|
|
104
|
+
- **A source system's separate "checkout" has no distinct Wix target.** The cart is the unified purchase-flow entity (there's no separate checkout), so map a source checkout's *input* state onto `cart`: billing → `paymentInfo.billingAddress`, shipping/delivery → `deliveryInfo`, applied coupons → cart `coupons`. **Calculated price *and* payment figures are NOT stored on the cart** — both the price totals (`summary.priceSummary`) and the payment breakdown (`summary.paymentSummary` — amount due, gift-card deductions, and the like) are computed on demand by Calculate/Estimate Cart (returned in a `CartSummary`), and the final figures live on the `order` after placement — so don't try to persist a source checkout's computed totals on the cart.
|
|
106
105
|
- If the source platform exposes products and orders in one model, split catalog entities into the vertical app and transaction entities into `ecommerce`.
|
|
107
106
|
- If the source has historical orders but no cart or checkout history, map directly to `order` and document missing pre-purchase state.
|
|
108
107
|
|
|
@@ -6,24 +6,27 @@ initial prompt, and the Wix connector is already configured.
|
|
|
6
6
|
Your Wix client id is in your prompt — a public, buyer-facing credential (anonymous visitor tokens
|
|
7
7
|
only), safe in the frontend; use it directly for the Wix client setup.
|
|
8
8
|
|
|
9
|
-
>
|
|
9
|
+
> **The Wix skills installed below are the complete build and seed path for this app.** **Do NOT use the Base44 commerce kit (or any Base44 solution kit).**
|
|
10
10
|
|
|
11
11
|
Follow STEPs 1–4 below exactly (run STEP 3 in parallel with STEP 2).
|
|
12
12
|
|
|
13
13
|
## STEP 1 — Install the Wix skills and deploy the storefront vertical to the app
|
|
14
14
|
|
|
15
|
-
Install
|
|
15
|
+
Install three skills — they land under `.agents/skills/`:
|
|
16
16
|
- **`wix-vibe-headless`** — the storefront build + seed guide (STEPs 2–3): your main source of truth.
|
|
17
|
-
- **`wix-
|
|
18
|
-
|
|
17
|
+
- **`wix-manage`** — REST recipes for managing and configuring the site (install apps, seed
|
|
18
|
+
catalogs, business setup).
|
|
19
|
+
- **`wix-base44-connector`** — building on Wix from the Base44 sandbox: site context, API
|
|
20
|
+
contracts, and the docs **fallback** — find + read the Wix API docs for anything
|
|
21
|
+
`wix-vibe-headless` doesn't cover.
|
|
19
22
|
|
|
20
|
-
Run this through exec_tool, exactly as written — installs
|
|
23
|
+
Run this through exec_tool, exactly as written — installs all three skills, deploys the `storefront` REST scaffolds + UI into `src/`, and pins the AGENTS.md note.
|
|
21
24
|
|
|
22
25
|
```js
|
|
23
26
|
const { execSync } = require('child_process');
|
|
24
27
|
const { existsSync, readdirSync } = require('fs');
|
|
25
28
|
const results = {};
|
|
26
|
-
for (const skill of ['wix-vibe-headless', 'wix-
|
|
29
|
+
for (const skill of ['wix-vibe-headless', 'wix-manage', 'wix-base44-connector']) {
|
|
27
30
|
if (existsSync(`/app/.agents/skills/${skill}/SKILL.md`)) { results[skill] = 'already_installed'; continue; }
|
|
28
31
|
try {
|
|
29
32
|
const out = execSync(`CI=1 npx -y skills add wix/skills/skills/${skill} --yes 2>&1`,
|
|
@@ -58,7 +61,7 @@ cleanup truly seems needed, ask the user first.
|
|
|
58
61
|
Seed by calling the storefront's ready-made seed module — read
|
|
59
62
|
`.agents/skills/wix-vibe-headless/references/storefront/seed/SEED.md` and load its `seed-*.js` via
|
|
60
63
|
its loader snippet (build-time exec_tool); call its functions with your data. Gaps or an unexpected
|
|
61
|
-
shape → the **`wix-
|
|
64
|
+
shape → the **`wix-base44-connector`** skill's doc discovery.
|
|
62
65
|
|
|
63
66
|
**Auth for these admin calls is the already-configured Wix headless connector — nothing else.** Get its
|
|
64
67
|
access token and send it as a bearer token:
|
|
@@ -73,7 +76,8 @@ Inline via exec_tool, `base44` is already declared — use it directly; do **not
|
|
|
73
76
|
inline it throws *"Identifier 'base44' has already been declared."*).
|
|
74
77
|
|
|
75
78
|
**Product images.** Generate with **Base44's built-in image generation**, then attach via the
|
|
76
|
-
storefront seed module's image-attach step — `wix-
|
|
79
|
+
storefront seed module's image-attach step — `wix-base44-connector` doc discovery if the module
|
|
80
|
+
doesn't cover it.
|
|
77
81
|
|
|
78
82
|
**Seed images with the FINAL url, in one call.** Use the real `https://media.base44.com/...` url
|
|
79
83
|
from the **completed** `generate_image` result and pass it straight into your single `setupStore`
|
|
@@ -101,4 +105,4 @@ const res = await fetch("https://www.wixapis.com/<api-path>", {
|
|
|
101
105
|
return await res.json();
|
|
102
106
|
```
|
|
103
107
|
|
|
104
|
-
`base44` is already declared inline in exec_tool — use it directly; do **not** import `@base44/sdk` or call `createClient()`. For what to call, check the storefront seed module (`.agents/skills/wix-vibe-headless/references/storefront/seed/SEED.md`) or look up the endpoint via `wix-
|
|
108
|
+
`base44` is already declared inline in exec_tool — use it directly; do **not** import `@base44/sdk` or call `createClient()`. For what to call, check the storefront seed module (`.agents/skills/wix-vibe-headless/references/storefront/seed/SEED.md`) or look up the endpoint via the `wix-base44-connector` skill's doc discovery.
|
|
@@ -6,24 +6,27 @@ initial prompt, and the Wix connector is already configured.
|
|
|
6
6
|
Your Wix client id is in your prompt — a public, buyer-facing credential (anonymous visitor tokens
|
|
7
7
|
only), safe in the frontend; use it directly for the Wix client setup.
|
|
8
8
|
|
|
9
|
-
>
|
|
9
|
+
> **The Wix skills installed below are the complete build path for this app.** **Do NOT use the Base44 commerce kit (or any Base44 solution kit).** **This flow builds the client only — there is no seeding step.**
|
|
10
10
|
|
|
11
11
|
Follow STEPs 1–3 below exactly.
|
|
12
12
|
|
|
13
13
|
## STEP 1 — Install the Wix skills and deploy the storefront vertical to the app
|
|
14
14
|
|
|
15
|
-
Install
|
|
15
|
+
Install three skills — they land under `.agents/skills/`:
|
|
16
16
|
- **`wix-vibe-headless`** — the storefront build guide (STEP 2): your main source of truth.
|
|
17
|
-
- **`wix-
|
|
18
|
-
|
|
17
|
+
- **`wix-manage`** — REST recipes for managing and configuring the site (install apps, seed
|
|
18
|
+
catalogs, business setup).
|
|
19
|
+
- **`wix-base44-connector`** — building on Wix from the Base44 sandbox: site context, API
|
|
20
|
+
contracts, and the docs **fallback** — find + read the Wix API docs for anything
|
|
21
|
+
`wix-vibe-headless` doesn't cover.
|
|
19
22
|
|
|
20
|
-
Run this through exec_tool, exactly as written — installs
|
|
23
|
+
Run this through exec_tool, exactly as written — installs all three skills, deploys the `storefront` REST scaffolds + UI into `src/`, and pins the AGENTS.md note.
|
|
21
24
|
|
|
22
25
|
```js
|
|
23
26
|
const { execSync } = require('child_process');
|
|
24
27
|
const { existsSync, readdirSync } = require('fs');
|
|
25
28
|
const results = {};
|
|
26
|
-
for (const skill of ['wix-vibe-headless', 'wix-
|
|
29
|
+
for (const skill of ['wix-vibe-headless', 'wix-manage', 'wix-base44-connector']) {
|
|
27
30
|
if (existsSync(`/app/.agents/skills/${skill}/SKILL.md`)) { results[skill] = 'already_installed'; continue; }
|
|
28
31
|
try {
|
|
29
32
|
const out = execSync(`CI=1 npx -y skills add wix/skills/skills/${skill} --yes 2>&1`,
|
|
@@ -71,4 +74,4 @@ const res = await fetch("https://www.wixapis.com/<api-path>", {
|
|
|
71
74
|
return await res.json();
|
|
72
75
|
```
|
|
73
76
|
|
|
74
|
-
`base44` is already declared inline in exec_tool — use it directly; do **not** import `@base44/sdk` or call `createClient()`. For what to call, check the storefront seed module (`.agents/skills/wix-vibe-headless/references/storefront/seed/SEED.md`) or look up the endpoint via `wix-
|
|
77
|
+
`base44` is already declared inline in exec_tool — use it directly; do **not** import `@base44/sdk` or call `createClient()`. For what to call, check the storefront seed module (`.agents/skills/wix-vibe-headless/references/storefront/seed/SEED.md`) or look up the endpoint via the `wix-base44-connector` skill's doc discovery.
|
|
@@ -6,19 +6,22 @@ initial prompt, and the Wix connector is already configured; use it for all admi
|
|
|
6
6
|
Your Wix client id is in your prompt — a public, buyer-facing credential (anonymous visitor tokens
|
|
7
7
|
only), safe in the frontend; use it directly for the Wix client setup.
|
|
8
8
|
|
|
9
|
-
>
|
|
9
|
+
> **The Wix skills installed below are the complete build and seed path for this app — the Wix connector supplies the token for admin API calls.** **Do NOT use the Base44 commerce kit (or any Base44 solution kit).**
|
|
10
10
|
|
|
11
11
|
Follow STEPs 1–5 below exactly (run STEP 4 in parallel with STEP 3).
|
|
12
12
|
|
|
13
13
|
## STEP 1 — Install the Wix skills locally
|
|
14
14
|
|
|
15
|
-
Install
|
|
15
|
+
Install three skills — they land under `.agents/skills/`:
|
|
16
16
|
- **`wix-vibe-headless`** — the client build **and** seed guide (STEPs 3–4): your main source of
|
|
17
17
|
truth. Seeding lives here too, per-vertical under `references/<vertical>/seed/`.
|
|
18
|
-
- **`wix-
|
|
19
|
-
|
|
18
|
+
- **`wix-manage`** — REST recipes for managing and configuring the site (install apps, seed
|
|
19
|
+
catalogs, business setup).
|
|
20
|
+
- **`wix-base44-connector`** — building on Wix from the Base44 sandbox: site context, API
|
|
21
|
+
contracts, and the docs **fallback** — find + read the Wix API docs for anything
|
|
22
|
+
`wix-vibe-headless` doesn't cover.
|
|
20
23
|
|
|
21
|
-
Run this through exec_tool, exactly as written — installs
|
|
24
|
+
Run this through exec_tool, exactly as written — installs all three skills, deploys REST scaffolds + UI into `src/`, writes `wix-config.js`, and pins the AGENTS.md note.
|
|
22
25
|
|
|
23
26
|
**Set `VERTICALS`** to what the prompt asks for (too vague to tell? do STEP 2 first, then set it):
|
|
24
27
|
|
|
@@ -46,7 +49,7 @@ const VERTICALS = ['storefront']; // ← set from the prompt; list every
|
|
|
46
49
|
const WIX_CLIENT_ID = '<client id from the prompt>';
|
|
47
50
|
const WIX_METASITE_ID = '<site id from the prompt>';
|
|
48
51
|
const results = {};
|
|
49
|
-
for (const skill of ['wix-vibe-headless', 'wix-
|
|
52
|
+
for (const skill of ['wix-vibe-headless', 'wix-manage', 'wix-base44-connector']) {
|
|
50
53
|
if (existsSync(`/app/.agents/skills/${skill}/SKILL.md`)) { results[skill] = 'already_installed'; continue; }
|
|
51
54
|
try {
|
|
52
55
|
const out = execSync(`CI=1 npx -y skills add wix/skills/skills/${skill} --yes 2>&1`,
|
|
@@ -103,7 +106,7 @@ cleanup truly seems needed, ask the user first.
|
|
|
103
106
|
Seed by calling your vertical's ready-made seed module — read
|
|
104
107
|
`.agents/skills/wix-vibe-headless/references/<vertical>/seed/SEED.md` and load its `seed-*.js` via
|
|
105
108
|
its loader snippet (build-time exec_tool); call its functions with your data. Gaps or an unexpected
|
|
106
|
-
shape → the **`wix-
|
|
109
|
+
shape → the **`wix-base44-connector`** skill's doc discovery.
|
|
107
110
|
|
|
108
111
|
**Auth for these admin calls is the already-configured Wix connector — nothing else.** Get its
|
|
109
112
|
access token and send it as a bearer token:
|
|
@@ -119,8 +122,8 @@ inline it throws *"Identifier 'base44' has already been declared."*).
|
|
|
119
122
|
|
|
120
123
|
**Entity images.** For image-bearing entities (store products, blog covers, bookings services,
|
|
121
124
|
restaurant items, portfolio projects, event heroes, CMS items), generate with **Base44's built-in
|
|
122
|
-
image generation**, then attach via the vertical seed module's image-attach step —
|
|
123
|
-
module doesn't cover that entity.
|
|
125
|
+
image generation**, then attach via the vertical seed module's image-attach step —
|
|
126
|
+
`wix-base44-connector` doc discovery if the module doesn't cover that entity.
|
|
124
127
|
|
|
125
128
|
**Seed images with the FINAL url, in one call.** Seeding writes to Wix, so use the real
|
|
126
129
|
`https://media.base44.com/...` url from the **completed** `generate_image` result and pass it straight
|
|
@@ -147,6 +150,6 @@ Once the site is built and seeded:
|
|
|
147
150
|
## Later admin requests
|
|
148
151
|
|
|
149
152
|
For any later admin/management request, work as in STEP 4: your vertical's seed module first, else
|
|
150
|
-
`wix-
|
|
153
|
+
`wix-base44-connector` doc discovery — all over the connector.
|
|
151
154
|
|
|
152
155
|
version: v1338
|
|
@@ -165,6 +165,8 @@ stale render.
|
|
|
165
165
|
## Using the client from your own UI
|
|
166
166
|
The two shipped hooks are the whole flow. If you build a custom surface, drive it the same way:
|
|
167
167
|
|
|
168
|
+
> Migrating from Cart V1 / Checkout V1? These helpers are V2-only — see the [migration guide](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/migration-guide) for the before/after.
|
|
169
|
+
|
|
168
170
|
```jsx
|
|
169
171
|
// LIST — every list helper returns an OBJECT, not a bare array. Destructure it:
|
|
170
172
|
const { services, total, nextOffset } = await queryServices({ limit: 24 }); // total 0 → empty state
|
|
@@ -3,7 +3,7 @@ import { wixApiRequest } from "./wix-client.js";
|
|
|
3
3
|
// Data model reference: see INSTRUCTIONS.md
|
|
4
4
|
// Service and TimeSlot shapes: see wix-bookings-services.js
|
|
5
5
|
|
|
6
|
-
// Wix Bookings app id — required inside catalogReference
|
|
6
|
+
// Wix Bookings app id — required inside catalogReference when adding the booking to the eCom cart.
|
|
7
7
|
const BOOKINGS_APP_ID = "13d21c63-b5ec-5912-8397-c3a5ddb27a97";
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -101,27 +101,28 @@ export async function createBooking(slot, contactDetails, { totalParticipants =
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
|
-
*
|
|
104
|
+
* Add a created booking to the current eCom cart and return the hosted checkout URL.
|
|
105
|
+
* In Cart V2 the cart id IS the checkout id — add the booking line to the current cart, then create
|
|
106
|
+
* the redirect session straight from that cart's id (there is no separate checkout-creation call).
|
|
105
107
|
* Redirect the buyer there (window.location.href = ...). On return, the booking is confirmed.
|
|
106
108
|
* Throws if no redirect URL is produced.
|
|
107
|
-
* https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/
|
|
109
|
+
* https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/add-line-items-to-current-cart.md
|
|
108
110
|
* @param {string} bookingId booking.id from createBooking().
|
|
109
111
|
* @returns {Promise<string>} The hosted-checkout URL to redirect to.
|
|
110
112
|
*/
|
|
111
113
|
export async function checkoutBooking(bookingId) {
|
|
112
114
|
if (!bookingId) throw new Error("checkoutBooking requires a bookingId.");
|
|
113
115
|
|
|
114
|
-
const
|
|
116
|
+
const cartRes = await wixApiRequest("/ecom/v2/carts/current/add-line-items", {
|
|
115
117
|
method: "POST",
|
|
116
118
|
body: {
|
|
117
|
-
|
|
118
|
-
lineItems: [
|
|
119
|
+
catalogItems: [
|
|
119
120
|
{ quantity: 1, catalogReference: { appId: BOOKINGS_APP_ID, catalogItemId: bookingId } },
|
|
120
121
|
],
|
|
121
122
|
},
|
|
122
123
|
});
|
|
123
|
-
const checkoutId =
|
|
124
|
-
if (!checkoutId) throw new Error("Failed to
|
|
124
|
+
const checkoutId = cartRes?.cart?.id;
|
|
125
|
+
if (!checkoutId) throw new Error("Failed to add the booking to the cart for checkout.");
|
|
125
126
|
|
|
126
127
|
const redirect = await wixApiRequest("/headless/v1/redirect-session", {
|
|
127
128
|
method: "POST",
|
|
@@ -170,6 +170,8 @@ render.
|
|
|
170
170
|
|
|
171
171
|
## Using the client from your own UI (menu, order cart)
|
|
172
172
|
|
|
173
|
+
> Migrating from Cart V1 / Checkout V1? These helpers are V2-only — see the [migration guide](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/migration-guide) for the before/after.
|
|
174
|
+
|
|
173
175
|
```jsx
|
|
174
176
|
import { getFullMenu } from "@/rest/wix-restaurants-menu";
|
|
175
177
|
import { useOrderCart } from "@/context/OrderCartContext";
|
|
@@ -188,7 +190,8 @@ const { menus } = await getFullMenu(); // [] when no menus → show t
|
|
|
188
190
|
// Load-bearing field paths (the shipped components already do these):
|
|
189
191
|
// - item.image / section.image / label.icon are OBJECTS → render `.url`, never the object; //-urls → https:
|
|
190
192
|
// - MENU prices are plain decimal strings with NO currency symbol ("12.50") — format in the UI.
|
|
191
|
-
// The eCom cart line price (line.
|
|
193
|
+
// The eCom cart line price (line.pricing.unitPrice / line.pricing.totalPrice) is a ConvertedMoney
|
|
194
|
+
// { amount, convertedAmount } with NO symbol either — format the number yourself.
|
|
192
195
|
// - an item is priced by EITHER item.price (single) OR item.variants[] (one-of, each { name, price }).
|
|
193
196
|
// - a cart mutation uses cart.lineItems[].id (the lineItemId), NOT the menu item id.
|
|
194
197
|
```
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
// Slide-over order cart. Reads everything from useOrderCart(); mutate by lineItem.id (NOT the menu
|
|
2
|
-
// item id), check out via the context (redirect-session URL). The eCom
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// item id), check out via the context (redirect-session URL). The eCom Cart V2 line price is
|
|
3
|
+
// `pricing.totalPrice`, a ConvertedMoney { amount, convertedAmount } with NO formatted string —
|
|
4
|
+
// format it with the cart's currency (formatCartMoney below). Styled with base44 design tokens
|
|
5
|
+
// (shadcn Tailwind classes). Mount it once in the Layout.
|
|
5
6
|
import { useOrderCart } from "@/context/OrderCartContext";
|
|
6
7
|
|
|
8
|
+
// Cart V2 money is a ConvertedMoney { amount, convertedAmount } with NO formatted string — format it
|
|
9
|
+
// with the cart's currency (buyer's display currency when present, else the site currency).
|
|
10
|
+
function formatCartMoney(money, cart) {
|
|
11
|
+
const value = money?.convertedAmount ?? money?.amount;
|
|
12
|
+
const currency = cart?.customerInfo?.currencyCode ?? cart?.businessInfo?.currencyCode ?? "USD";
|
|
13
|
+
return value == null ? "" : new Intl.NumberFormat(undefined, { style: "currency", currency }).format(Number(value));
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
export default function OrderCartDrawer() {
|
|
8
17
|
const { cart, isOpen, setIsOpen, removeItem, updateQuantity, checkout, loading } = useOrderCart();
|
|
9
18
|
const lineItems = cart?.lineItems ?? [];
|
|
@@ -22,23 +31,26 @@ export default function OrderCartDrawer() {
|
|
|
22
31
|
<div className="flex-1 overflow-y-auto p-4">
|
|
23
32
|
{lineItems.length === 0 ? (
|
|
24
33
|
<p className="text-muted-foreground">Your order is empty.</p>
|
|
25
|
-
) : lineItems.map((line) =>
|
|
34
|
+
) : lineItems.map((line) => {
|
|
35
|
+
const qty = line.quantityInfo?.confirmedQuantity;
|
|
36
|
+
return (
|
|
26
37
|
<div key={line.id} className="flex gap-3 py-3 border-b border-border">
|
|
27
38
|
{/* line.id is the lineItemId for mutations — NOT the menu item id */}
|
|
28
39
|
<div className="flex-1 flex flex-col gap-1">
|
|
29
|
-
<span className="font-semibold">{line.
|
|
40
|
+
<span className="font-semibold">{line.name?.original}</span>
|
|
30
41
|
<div className="flex items-center gap-2 mt-1">
|
|
31
|
-
<QtyButton onClick={() => updateQuantity(line.id, Math.max(1,
|
|
32
|
-
<span className="min-w-[20px] text-center">{
|
|
33
|
-
<QtyButton onClick={() => updateQuantity(line.id,
|
|
42
|
+
<QtyButton onClick={() => updateQuantity(line.id, Math.max(1, qty - 1))}>−</QtyButton>
|
|
43
|
+
<span className="min-w-[20px] text-center">{qty}</span>
|
|
44
|
+
<QtyButton onClick={() => updateQuantity(line.id, qty + 1)}>+</QtyButton>
|
|
34
45
|
<button onClick={() => removeItem(line.id)}
|
|
35
46
|
className="ml-auto border-none bg-transparent cursor-pointer text-muted-foreground text-[13px] underline">Remove</button>
|
|
36
47
|
</div>
|
|
37
48
|
</div>
|
|
38
|
-
{/*
|
|
39
|
-
<span className="font-semibold">{line.
|
|
49
|
+
{/* Cart V2 has no formatted string — format the ConvertedMoney client-side */}
|
|
50
|
+
<span className="font-semibold">{formatCartMoney(line.pricing?.totalPrice, cart)}</span>
|
|
40
51
|
</div>
|
|
41
|
-
|
|
52
|
+
);
|
|
53
|
+
})}
|
|
42
54
|
</div>
|
|
43
55
|
|
|
44
56
|
{lineItems.length > 0 && (
|
|
@@ -30,7 +30,7 @@ export function OrderCartProvider({ children }) {
|
|
|
30
30
|
return () => document.removeEventListener("visibilitychange", onVisible);
|
|
31
31
|
}, [refreshCart]);
|
|
32
32
|
|
|
33
|
-
const itemCount = (cart?.lineItems ?? []).reduce((n, li) => n + (li.
|
|
33
|
+
const itemCount = (cart?.lineItems ?? []).reduce((n, li) => n + (li.quantityInfo?.confirmedQuantity || 0), 0);
|
|
34
34
|
|
|
35
35
|
// A menu item carries its menuId/sectionId from the getFullMenu tree — the caller passes both.
|
|
36
36
|
// addItemToCart throws on a missing operation/menu/section or an unavailable line; let it propagate.
|