@wix/agent-skills 1.15.0 → 1.15.1
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/README.md +8 -0
- package/package.json +1 -1
- package/skills/wix-app/references/DATA_COLLECTION.md +5 -3
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +2 -0
- package/skills/wix-app/references/STORES_VERSIONING.md +9 -211
- package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +5 -0
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +151 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +57 -0
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +6 -0
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +3 -1
- package/skills/wix-app/references/stores/CATEGORIES.md +22 -0
- package/skills/wix-app/references/stores/GET_PRODUCT.md +99 -0
- package/skills/wix-app/references/stores/INVENTORY.md +37 -0
- package/skills/wix-app/references/stores/QUERY.md +87 -0
- package/skills/wix-app/references/stores/WRITE.md +55 -0
- package/skills/wix-headless/SKILL.md +6 -1
- package/skills/wix-headless/entry/bootstrap.mjs +2 -2
- package/skills/wix-headless/entry/skill.md +0 -2
- package/skills/wix-headless/references/CAPABILITIES.md +6 -4
- package/skills/wix-headless/references/DISCOVERY.md +1 -1
- package/skills/wix-headless/references/FEEDBACK.md +16 -5
- package/skills/wix-headless/references/SDK_HANDOFF.md +2 -0
- package/skills/wix-headless/references/SEED.md +3 -1
- package/skills/wix-headless/references/SETUP.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +42 -2
- package/skills/wix-headless/references/inline-recipes/setup-bookings.md +5 -1
- package/skills/wix-headless/references/inline-recipes/setup-forms.md +1 -1
- package/skills/wix-headless/references/inline-recipes/setup-online-store.md +21 -5
- package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +3 -1
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +73 -0
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +38 -2
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +20 -1
- package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +1 -1
- package/skills/wix-headless/references/managed/CONNECT.md +1 -1
- package/skills/wix-headless/references/managed/CREATE.md +1 -1
- package/skills/wix-headless/references/managed/DEPLOYMENT.md +22 -0
- package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +8 -0
- package/skills/wix-headless/references/stripe/DEPLOYMENT.md +8 -0
- package/skills/wix-manage/SKILL.md +8 -5
- package/skills/wix-manage/references/analytics/query-site-analytics.md +66 -9
- package/skills/wix-manage/references/app-installation/install-wix-apps.md +3 -0
- package/skills/wix-manage/references/bookings/create-booking-service-from-prompt.md +6 -5
- package/skills/wix-manage/references/bookings/create-course-service.md +30 -5
- package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +76 -42
- package/skills/wix-manage/references/cms/cms-schema-management.md +6 -0
- package/skills/wix-manage/references/get-paid/how-to-setup-wix-payments.md +30 -7
- package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +225 -144
- package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +19 -10
- package/skills/wix-manage/references/sites/site-import.md +270 -0
- package/skills/wix-manage/references/stores/create-product-from-image.md +8 -6
- package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +16 -10
- package/skills/wix-vibe-headless/SKILL.md +6 -0
- package/skills/wix-vibe-headless/platforms/README.md +22 -0
- package/skills/wix-vibe-headless/platforms/base44.md +142 -0
- package/skills/wix-vibe-headless/platforms/generic.md +87 -0
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +5 -1
- package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +3 -1
- package/skills/wix-vibe-headless/references/events/wix-events-browse.js +2 -1
- package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +84 -55
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +11 -2
- package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +5 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Wix Managed Headless — build instructions
|
|
2
|
+
|
|
3
|
+
You are building a **Wix Managed** headless site. The business to build, and your Wix client id
|
|
4
|
+
and metasite id, are given in your initial prompt. Follow the steps below.
|
|
5
|
+
|
|
6
|
+
## STEP 0 — Install the Wix skills locally
|
|
7
|
+
|
|
8
|
+
Install three skills — they land under `.agents/skills/` as:
|
|
9
|
+
- **`wix-vibe-headless`** — the client build guide: how to build the frontend against the Wix
|
|
10
|
+
APIs. This is your main source of truth (STEP 1).
|
|
11
|
+
- **`wix-headless`** — a broad skill for building full Wix apps with the Wix SDK packages, **most
|
|
12
|
+
of which does not apply to how you build here**. Use it **only** as a seeding/admin recipe
|
|
13
|
+
reference — its `references/SEED.md` and `references/inline-recipes/`, for STEP 2. **Ignore
|
|
14
|
+
everything else in it** — in particular do **not** follow its authentication / `@wix/cli` /
|
|
15
|
+
"managed project" setup (e.g. anything under `references/managed/`, such as `AUTHENTICATION.md`).
|
|
16
|
+
That is **not** how auth works here — auth is handled per STEP 2 below.
|
|
17
|
+
- **`wix-docs`** — a **fallback**: how to search and read the Wix API reference docs, for anything
|
|
18
|
+
the seeding recipes above don't cover.
|
|
19
|
+
|
|
20
|
+
Install them so you can read them from files as you go (fetching skill docs over the web
|
|
21
|
+
truncates or summarises large files).
|
|
22
|
+
|
|
23
|
+
**Run the Skills CLI** — this is the install path to use:
|
|
24
|
+
```bash
|
|
25
|
+
CI=1 npx skills@latest add wix/skills/skills/wix-headless --yes
|
|
26
|
+
CI=1 npx skills@latest add wix/skills/skills/wix-vibe-headless --yes
|
|
27
|
+
CI=1 npx skills@latest add wix/skills/skills/wix-docs --yes
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Only if the CLI above actually errors** (not on a guess), fall back to curl + gzip — download
|
|
31
|
+
each bundle and extract it into `.agents/skills/wix-<name>/`:
|
|
32
|
+
```bash
|
|
33
|
+
for s in headless vibe-headless docs; do
|
|
34
|
+
mkdir -p ".agents/skills/wix-$s"
|
|
35
|
+
curl -s "https://www.wix.com/skills/$s.tgz" | tar xz -C ".agents/skills/wix-$s" --strip-components=1
|
|
36
|
+
done
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## STEP 1 — Build the client
|
|
40
|
+
|
|
41
|
+
Read `.agents/skills/wix-vibe-headless/SKILL.md` and follow it **exactly** — it is the single
|
|
42
|
+
source of truth for how the client app is built against the Wix APIs (over the public
|
|
43
|
+
`WIX_CLIENT_ID`, which is a buyer/visitor-facing credential, safe in the frontend). To save time,
|
|
44
|
+
prefer copying the ready-made files the `wix-vibe-headless` skill provides (e.g. the Wix client
|
|
45
|
+
setup) and adapting them over re-generating them from scratch.
|
|
46
|
+
|
|
47
|
+
## STEP 2 — Seed and manage the business
|
|
48
|
+
|
|
49
|
+
Seed the site with real content by following the `wix-headless` skill's `references/SEED.md`
|
|
50
|
+
(`.agents/skills/wix-headless/references/SEED.md`). Where its seed recipes don't cover what you
|
|
51
|
+
need, fall back to the `wix-docs` skill to search and read the relevant Wix API docs.
|
|
52
|
+
|
|
53
|
+
**Seeding is additive.** You may clean up the app install's **obvious default sample/mock data**
|
|
54
|
+
right after a fresh install, but the site may already hold **real content** (a prior run, or
|
|
55
|
+
owner-added) — if what's there isn't obviously install sample data, or you're unsure, **do not
|
|
56
|
+
delete or overwrite it without the user's explicit ask or approval** (ask first).
|
|
57
|
+
|
|
58
|
+
These management/admin calls need **elevated Wix credentials** — the public client id is not
|
|
59
|
+
enough. If you don't already have a way to authenticate them, either **connect your platform's
|
|
60
|
+
Wix connector** (if it has one) or **ask the user for a Wix API key / token** and store it in your
|
|
61
|
+
platform's built-in **connector / secrets (env) manager** — never hardcode or commit it. **Once
|
|
62
|
+
the connector is connected (or the API key is in place), you can make Wix REST admin calls
|
|
63
|
+
directly** — authenticate each call with that credential (the `wix-docs` skill covers Wix API-key
|
|
64
|
+
auth). Or, if the user prefers, tell them they can add this content themselves in the Wix
|
|
65
|
+
dashboard instead.
|
|
66
|
+
|
|
67
|
+
Authenticate admin calls with **only** that connector/API key. Do **not** install or run the Wix
|
|
68
|
+
CLI (`@wix/cli`), do a device-login, or follow `wix-headless`'s `references/managed/AUTHENTICATION.md`
|
|
69
|
+
— that managed-project auth flow does not apply here.
|
|
70
|
+
|
|
71
|
+
Management/admin operations (seeding, `wix-headless`, `wix-docs`) are **separate from the
|
|
72
|
+
client** — the client is built solely per the `wix-vibe-headless` skill.
|
|
73
|
+
|
|
74
|
+
If possible, run STEP 1 and STEP 2 in parallel — building the client and seeding the business
|
|
75
|
+
are independent. Within each, also parallelize independent work (API calls, seeding multiple
|
|
76
|
+
entities) to finish faster.
|
|
77
|
+
|
|
78
|
+
## Later admin requests
|
|
79
|
+
|
|
80
|
+
For any later admin/management request, work the same way as STEP 2: check the `wix-headless`
|
|
81
|
+
skill's inline recipes first (`.agents/skills/wix-headless/references/inline-recipes/`) and fall
|
|
82
|
+
back to the `wix-docs` skill where the operation isn't documented there.
|
|
83
|
+
|
|
84
|
+
## When done
|
|
85
|
+
|
|
86
|
+
After the site is built and seeded, ask the user to open this URL to complete the setup in Wix
|
|
87
|
+
(substitute the metasite id you were given): `https://manage.wix.com/dashboard/{metaSiteId}`
|
|
@@ -58,7 +58,11 @@ the full API reference for anything not shown.
|
|
|
58
58
|
## How to wire it (UI is the project's choice)
|
|
59
59
|
- **Service list** — `queryServices()` for the listing (visitor-visible services only). Render
|
|
60
60
|
`name`, `tagLine`, the image via `mediaUrl(service.media?.items?.[0]?.image)`, and the price
|
|
61
|
-
from `payment.fixed.price
|
|
61
|
+
from `payment.fixed.price`. `value` + `currency` are always present; `formattedValue` is
|
|
62
|
+
**optional** (it may be missing), so don't depend on it — build the price from `value`+`currency`
|
|
63
|
+
and use `formattedValue` only when present. e.g. `new Intl.NumberFormat(undefined, { style:
|
|
64
|
+
'currency', currency }).format(Number(value))`. (Rendering `formattedValue` alone leaves the price
|
|
65
|
+
blank — or your "Varies" fallback — whenever it's absent.) Pass the returned
|
|
62
66
|
`nextOffset` back as `offset` to load the next page. Books **APPOINTMENT and CLASS** services
|
|
63
67
|
(see the slot picker below); COURSE is whole-course enrollment and out of scope.
|
|
64
68
|
- **Service detail** — `getService(serviceId)` keyed off the URL/route; returns null on miss —
|
|
@@ -12,7 +12,9 @@ import { wixApiRequest } from "./wix-client.js";
|
|
|
12
12
|
* media.items {array} — [{ image: { id, url, width, height, altText } }]
|
|
13
13
|
* (url may be a bare Wix media handle — pass through mediaUrl() before rendering),
|
|
14
14
|
* payment.rateType "FIXED"|"CUSTOM"|"VARIED"|"NO_FEE"|"SUBSCRIPTION",
|
|
15
|
-
* payment.fixed.price { value, currency, formattedValue }
|
|
15
|
+
* payment.fixed.price { value, currency, formattedValue } — value + currency are always
|
|
16
|
+
* present; formattedValue is optional (may be missing), so format the price from
|
|
17
|
+
* value+currency and use formattedValue only when present,
|
|
16
18
|
* payment.options { online, inPerson, deposit, pricingPlan },
|
|
17
19
|
* schedule.id {string}, onlineBooking.enabled {boolean},
|
|
18
20
|
* category { id, name }, staffMemberIds {string[]}, locations {array},
|
|
@@ -24,7 +24,8 @@ import { wixApiRequest } from "./wix-client.js";
|
|
|
24
24
|
* type {string} — "RSVP"|"TICKETING"|"EXTERNAL"|"NONE",
|
|
25
25
|
* status {string} — only OPEN_* statuses accept new registrations,
|
|
26
26
|
* rsvp.responseType — "YES_AND_NO" allows a "NO" reply,
|
|
27
|
-
* tickets.
|
|
27
|
+
* tickets.lowestPrice {object} — money { value, currency, formattedValue }; render
|
|
28
|
+
* formattedValue, not the object (see "Money/price fields" in SKILL.md). tickets.soldOut {boolean},
|
|
28
29
|
* external.url — link out when type === "EXTERNAL",
|
|
29
30
|
* eventPageUrl {object} — { base, path } (URLS fieldset) — needed for getTicketCheckoutUrl,
|
|
30
31
|
* form {object} — registration form controls (FORM fieldset),
|
|
@@ -36,23 +36,31 @@ const PROJECTS_QUERY_URL = "/portfolio/v1/projects/query";
|
|
|
36
36
|
* @returns {Promise<{ collections: object[], nextCursor: string|null }>}
|
|
37
37
|
*/
|
|
38
38
|
export async function queryCollections({ limit = 100, cursor } = {}) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
39
|
+
try {
|
|
40
|
+
const res = await wixApiRequest(COLLECTIONS_QUERY_URL, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
body: {
|
|
43
|
+
includePageUrl: true,
|
|
44
|
+
query: cursor
|
|
45
|
+
? { cursorPaging: { limit, cursor } }
|
|
46
|
+
: {
|
|
47
|
+
filter: { hidden: false },
|
|
48
|
+
sort: [{ fieldName: "sortOrder", order: "ASC" }],
|
|
49
|
+
cursorPaging: { limit },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
collections: res?.collections ?? [],
|
|
55
|
+
nextCursor: res?.metadata?.cursors?.next ?? null,
|
|
56
|
+
};
|
|
57
|
+
} catch (err) {
|
|
58
|
+
// Degrade to an empty page instead of rethrowing: an uncaught read would leave a
|
|
59
|
+
// component's `loading` flag stuck true and hang the gallery on a spinner. Empty
|
|
60
|
+
// renders the same empty state as a genuinely empty backend.
|
|
61
|
+
console.error("queryCollections failed:", err);
|
|
62
|
+
return { collections: [], nextCursor: null };
|
|
63
|
+
}
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
/**
|
|
@@ -79,11 +87,18 @@ export async function getCollectionBySlug(slug) {
|
|
|
79
87
|
* @returns {Promise<number>}
|
|
80
88
|
*/
|
|
81
89
|
export async function countCollections() {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
try {
|
|
91
|
+
const res = await wixApiRequest(COLLECTIONS_QUERY_URL, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
body: { query: { filter: { hidden: false }, cursorPaging: { limit: 100 } } },
|
|
94
|
+
});
|
|
95
|
+
return res?.metadata?.total ?? (res?.collections?.length ?? 0);
|
|
96
|
+
} catch (err) {
|
|
97
|
+
// On failure treat as empty (0) rather than rethrowing — a thrown count would hang
|
|
98
|
+
// the empty-state check; 0 falls through to the "add collections" prompt.
|
|
99
|
+
console.error("countCollections failed:", err);
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
87
102
|
}
|
|
88
103
|
|
|
89
104
|
/**
|
|
@@ -93,23 +108,30 @@ export async function countCollections() {
|
|
|
93
108
|
* @returns {Promise<{ projects: object[], nextCursor: string|null }>}
|
|
94
109
|
*/
|
|
95
110
|
export async function queryProjects({ limit = 100, cursor } = {}) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
try {
|
|
112
|
+
const res = await wixApiRequest(PROJECTS_QUERY_URL, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
body: {
|
|
115
|
+
includePageUrl: true,
|
|
116
|
+
query: cursor
|
|
117
|
+
? { cursorPaging: { limit, cursor } }
|
|
118
|
+
: {
|
|
119
|
+
filter: { hidden: false },
|
|
120
|
+
sort: [{ fieldName: "createdDate", order: "DESC" }],
|
|
121
|
+
cursorPaging: { limit },
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
projects: res?.projects ?? [],
|
|
127
|
+
nextCursor: res?.metadata?.cursors?.next ?? null,
|
|
128
|
+
};
|
|
129
|
+
} catch (err) {
|
|
130
|
+
// Degrade to an empty page instead of rethrowing (see queryCollections) — an uncaught
|
|
131
|
+
// read hangs the gallery on an infinite spinner; empty renders the empty state instead.
|
|
132
|
+
console.error("queryProjects failed:", err);
|
|
133
|
+
return { projects: [], nextCursor: null };
|
|
134
|
+
}
|
|
113
135
|
}
|
|
114
136
|
|
|
115
137
|
/**
|
|
@@ -121,22 +143,29 @@ export async function queryProjects({ limit = 100, cursor } = {}) {
|
|
|
121
143
|
* @returns {Promise<{ projects: object[], nextCursor: string|null }>}
|
|
122
144
|
*/
|
|
123
145
|
export async function queryProjectsByCollection(collectionId, { limit = 100, cursor } = {}) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
146
|
+
try {
|
|
147
|
+
const res = await wixApiRequest(PROJECTS_QUERY_URL, {
|
|
148
|
+
method: "POST",
|
|
149
|
+
body: {
|
|
150
|
+
includePageUrl: true,
|
|
151
|
+
query: cursor
|
|
152
|
+
? { cursorPaging: { limit, cursor } }
|
|
153
|
+
: {
|
|
154
|
+
filter: { hidden: false, collectionIds: { $hasSome: [collectionId] } },
|
|
155
|
+
cursorPaging: { limit },
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
return {
|
|
160
|
+
projects: res?.projects ?? [],
|
|
161
|
+
nextCursor: res?.metadata?.cursors?.next ?? null,
|
|
162
|
+
};
|
|
163
|
+
} catch (err) {
|
|
164
|
+
// Degrade to an empty page instead of rethrowing (see queryCollections) — an uncaught
|
|
165
|
+
// read hangs the collection page on an infinite spinner; empty renders the empty state.
|
|
166
|
+
console.error("queryProjectsByCollection failed:", err);
|
|
167
|
+
return { projects: [], nextCursor: null };
|
|
168
|
+
}
|
|
140
169
|
}
|
|
141
170
|
|
|
142
171
|
/**
|
|
@@ -50,8 +50,9 @@ reference for anything not shown.
|
|
|
50
50
|
|
|
51
51
|
## How to wire it (UI is the project's choice)
|
|
52
52
|
- **Product grid** — `queryProducts()` for the listing (visible products only); pass
|
|
53
|
-
`nextCursor` back as `cursor` to load the next page. Render fields directly from the Wix
|
|
54
|
-
product object (see the `Product` typedef in `wix-store.js` for key fields)
|
|
53
|
+
`nextCursor` back as `cursor` to load the next page. Render most fields directly from the Wix
|
|
54
|
+
product object (see the `Product` typedef in `wix-store-catalog.js` for key fields) — the one
|
|
55
|
+
exception is `plainDescription`, which is HTML (see PDP below). For price, use
|
|
55
56
|
`actualPriceRange.minValue.formattedAmount` (already includes the currency symbol) — no
|
|
56
57
|
manual formatting needed.
|
|
57
58
|
- **PDP** — `getProductBySlug(slug)` keyed off the URL slug; returns null on miss — show
|
|
@@ -65,6 +66,10 @@ reference for anything not shown.
|
|
|
65
66
|
**mandatory** modifier (e.g. "gift wrap?") whose control isn't rendered can never be added: the
|
|
66
67
|
buyer can't satisfy the requirement, so `add-to-cart` returns 200 with an **empty** `lineItems`
|
|
67
68
|
and the add silently no-ops.
|
|
69
|
+
Render `product.plainDescription` as **HTML** — despite the name it contains markup (`<p>`,
|
|
70
|
+
`<br>`, `<strong>`), so `dangerouslySetInnerHTML={{ __html: product.plainDescription }}` (React)
|
|
71
|
+
or `el.innerHTML = product.plainDescription`, never as a plain text node (that shows raw `<p>`
|
|
72
|
+
tags). Strip tags only for plain-text contexts (SEO/meta description, a truncated card teaser).
|
|
68
73
|
- **Gate the Add-to-cart button** — disable it only until the requirements the product *actually
|
|
69
74
|
has* are met, computed from the product object (never assume every product has options or
|
|
70
75
|
modifiers): if `product.options` is non-empty, a variant must resolve from the selections; every
|
|
@@ -86,6 +91,10 @@ reference for anything not shown.
|
|
|
86
91
|
- **Categories** — `queryCategories()` for a category menu; `getCategoryBySlug(slug)` for
|
|
87
92
|
a category landing page. Pass `category.id` to `queryProductsByCategory(categoryId, { limit?, cursor? })`
|
|
88
93
|
to list only the products in that category; paginate exactly like `queryProducts`.
|
|
94
|
+
`queryCategories()` includes Wix's auto-created **"All Products" system category** (`slug:
|
|
95
|
+
"all-products"`) — it mirrors the full catalog, so drop it from the category menu
|
|
96
|
+
(`categories.filter(c => c.slug !== "all-products")`). Filter by that slug, not by name (renames/
|
|
97
|
+
localizes) or `visible` (it's `visible: true` like any other).
|
|
89
98
|
- **Cart** — `addToCart(catalogItemId, variantId?, qty?, { modifierChoices?, customTextFields? }?)`,
|
|
90
99
|
`updateCartItemQuantity(lineItemId, qty)`, `removeFromCart(lineItemId)`.
|
|
91
100
|
- `variantId` (`variantsInfo.variants[].id` from `getProductBySlug`) — required for products with
|
|
@@ -20,7 +20,9 @@ import { wixApiRequest } from "./wix-client.js";
|
|
|
20
20
|
* modifiers {array} — non-variant customizations (engraving, gift wrap):
|
|
21
21
|
* [{ id, name, mandatory, modifierRenderType "TEXT_CHOICES"|"FREE_TEXT",
|
|
22
22
|
* key, choicesSettings.choices, freeTextSettings.key }],
|
|
23
|
-
* plainDescription {string} — HTML
|
|
23
|
+
* plainDescription {string} — product description as an HTML string (contains <p>, <br>,
|
|
24
|
+
* <strong>…) despite the "plain" name — NOT plain text. Render with innerHTML /
|
|
25
|
+
* dangerouslySetInnerHTML; strip tags only for plain-text contexts (meta description, teaser),
|
|
24
26
|
* variantsInfo.variants {array} — returned only by getProductBySlug:
|
|
25
27
|
* [{ id, visible, choices [{ optionChoiceIds: { optionId, choiceId } }],
|
|
26
28
|
* price: { actualPrice, compareAtPrice }, media, inventoryStatus: { inStock } }]
|
|
@@ -28,6 +30,8 @@ import { wixApiRequest } from "./wix-client.js";
|
|
|
28
30
|
* match all selected { optionId, choiceId } pairs, then pass variant.id to addToCart.
|
|
29
31
|
*
|
|
30
32
|
* Category: { id, name, slug, visible, description, image, itemCounter, parentCategory.id }
|
|
33
|
+
* NB: queryCategories includes the auto-created system category { slug: "all-products" } —
|
|
34
|
+
* filter it out of a category menu (see INSTRUCTIONS.md). `visible` does not flag it.
|
|
31
35
|
* Full model: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/categories
|
|
32
36
|
*/
|
|
33
37
|
|