@wix/agent-skills 1.18.2 → 1.19.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/SKILL.md +9 -9
- package/skills/wix-app/references/BACKEND_API.md +151 -152
- package/skills/wix-app/references/EXTENSION_REGISTRATION.md +12 -8
- package/skills/wix-manage/SKILL.md +1 -1
- package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +59 -33
- package/skills/wix-manage/references/bookings/bookings-staff-setup.md +45 -22
- package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +70 -12
- package/skills/wix-manage/references/calendar/configure-default-business-hours.md +53 -17
- package/skills/wix-manage/references/stores/create-product-catalog-v3.md +17 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +9 -8
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +9 -8
- package/skills/wix-vibe-headless/platforms/base44.md +11 -3
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +4 -0
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +5 -4
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.cjs +33 -5
|
@@ -24,7 +24,8 @@ No installation, deployment, or AGENTS.md update is needed.
|
|
|
24
24
|
The deployed implementation and configuration files do not need to be read; use the build and seed
|
|
25
25
|
guides below for their contracts and usage. Continue with STEP 1.
|
|
26
26
|
|
|
27
|
-
Follow STEPs 1–3 below exactly
|
|
27
|
+
Follow STEPs 1–3 below exactly. Fire product image generations first, then build the client
|
|
28
|
+
(STEP 1), and seed (STEP 2) **after** the client is built — generation finishes while you build.
|
|
28
29
|
|
|
29
30
|
## STEP 1 — Build the client
|
|
30
31
|
|
|
@@ -74,13 +75,13 @@ Inline via exec_tool, `base44` is already declared — use it directly; do **not
|
|
|
74
75
|
`@base44/sdk`, re-declare it, or call `createClient()` (that's for standalone `.js` files only;
|
|
75
76
|
inline it throws *"Identifier 'base44' has already been declared."*).
|
|
76
77
|
|
|
77
|
-
**Product images.**
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
from the
|
|
82
|
-
call
|
|
83
|
-
|
|
78
|
+
**Product images.** Fire every `generate_image` **before you build the client**, and seed **after**
|
|
79
|
+
it — generation finishes while you build, so by the time you write the seed call your images are
|
|
80
|
+
ready: each finished result now reads `status: "completed"` with its final
|
|
81
|
+
`https://media.base44.com/...` url. Read every `imageUrl` from the results **as they read at that
|
|
82
|
+
moment** — not from what they said when you called the tool — and pass them in the single
|
|
83
|
+
`setupStore` call. A result without a final url by then (still running, or failed) → seed that
|
|
84
|
+
product **without** `imageUrl` and attach it afterwards with `attachProductImages`.
|
|
84
85
|
|
|
85
86
|
## STEP 3 — Wrap up
|
|
86
87
|
|
|
@@ -11,7 +11,8 @@ only), safe in the frontend; use it directly for the Wix client setup.
|
|
|
11
11
|
**Banner enabled for this entry flow:** mount `<WixManageBanner/>` once in the Layout, above
|
|
12
12
|
the header in the fixed top region, per the vertical instructions. It is preview-only.
|
|
13
13
|
|
|
14
|
-
Follow STEPs 1–5 below exactly (run STEP 4 in parallel with STEP 3 — **except `forms`**, see
|
|
14
|
+
Follow STEPs 1–5 below exactly (run STEP 4 in parallel with STEP 3 — **except `forms`**, see
|
|
15
|
+
STEP 3, and **except a seed that attaches entity images**, which runs after the build; see STEP 4).
|
|
15
16
|
|
|
16
17
|
## STEP 1 — Install the Wix skills locally
|
|
17
18
|
|
|
@@ -98,8 +99,15 @@ rejects the write. Wire routes/imports in with `find_replace`, leave the rest as
|
|
|
98
99
|
|
|
99
100
|
Seed by calling your vertical's ready-made seed module — read
|
|
100
101
|
`.agents/skills/wix-vibe-headless/references/<vertical>/seed/SEED.md` and follow it (the loader
|
|
101
|
-
snippet, admin connector token,
|
|
102
|
-
|
|
102
|
+
snippet, admin connector token, and every field shape are there). Gaps or an unexpected shape → the
|
|
103
|
+
documentation skill available in your environment.
|
|
104
|
+
|
|
105
|
+
**Entity images:** fire every image generation **before you build the client**, and run an
|
|
106
|
+
image-carrying seed **after** the build — generation finishes while you build, and each finished
|
|
107
|
+
result then reads `status: "completed"` with its final `https://media.base44.com/...` url. Read
|
|
108
|
+
every image url from the results **as they read at that moment**, not from what they said when you
|
|
109
|
+
called the tool. No final url by then (still running, or failed) → seed without that image and
|
|
110
|
+
attach it afterwards per the vertical's `SEED.md`.
|
|
103
111
|
Seeding is **admin-only** — not part of the client, which is built solely per the `wix-vibe-headless` skill.
|
|
104
112
|
|
|
105
113
|
- **Additive only:** never delete or overwrite the user's content, even apparent sample data; ask first if a cleanup truly seems needed.
|
|
@@ -336,6 +336,10 @@ wire these exactly as shown below.
|
|
|
336
336
|
When adding storefront routes and providers to `src/App.jsx`, preserve the existing platform
|
|
337
337
|
authentication setup, including `AuthProvider`, `useAuth`, and their `@/lib/AuthContext` imports.
|
|
338
338
|
Do not remove or replace that authentication logic.
|
|
339
|
+
The shipped commerce flow needs no login: shoppers browse, cart, and check out on the Wix visitor
|
|
340
|
+
session, which is separate from platform user auth. Whether the storefront is public or members-only
|
|
341
|
+
is the brief's call — default to public, and gate routes behind platform auth only when the brief
|
|
342
|
+
asks for it. Neither choice affects the commerce flow.
|
|
339
343
|
- Wrap the routed tree in `<CartProvider>` (from `@/context/CartContext`).
|
|
340
344
|
- Put your **header + footer in a `Layout`** that renders `<Outlet/>` between them, and nest every
|
|
341
345
|
route under one pathless `<Route element={<Layout/>}>`. Your brand chrome then wraps **every** page
|
|
@@ -19,9 +19,7 @@ const ctx = { token: accessToken };
|
|
|
19
19
|
// ONE call: install (+ wait for V3) → create products → categories → attach images, ids kept
|
|
20
20
|
// in memory (no hand-threading). Categories map name -> product NAMES. Pass an imageUrl per product
|
|
21
21
|
// to attach its image; omit it to skip images.
|
|
22
|
-
// imageUrl
|
|
23
|
-
// result — not a still-generating /__generating__/<id>.png placeholder (Wix can't fetch that).
|
|
24
|
-
// generate_image runs in the background while you build, so the urls are ready by seed time.
|
|
22
|
+
// imageUrl: a public, fetchable https:// url — Wix copies the image bytes at attach time.
|
|
25
23
|
const result = await seed.setupStore(ctx, {
|
|
26
24
|
currency: "EUR", // Pass only if the user asked for a currency or it's obvious for the store; else omit this line.
|
|
27
25
|
products: [
|
|
@@ -38,6 +36,8 @@ const result = await seed.setupStore(ctx, {
|
|
|
38
36
|
categories: { "Legends": ["The Glam Rocker"], "Rising Stars": [] }, // omit if the brief names none
|
|
39
37
|
});
|
|
40
38
|
// result: { products:[{id,slug,revision,name}], categories:[{id,name}], imagesAttached,
|
|
39
|
+
// imagesSkipped (product names whose imageUrl was not an absolute https:// url — attach those afterwards),
|
|
40
|
+
// productsWithoutImages (product names seeded with no imageUrl — attach afterwards once urls exist),
|
|
41
41
|
// currency: { requested, actual, status, warnings } }
|
|
42
42
|
```
|
|
43
43
|
|
|
@@ -112,6 +112,8 @@ enrolls in — is **Pricing Plans**, not a Stores product, so it isn't seeded he
|
|
|
112
112
|
download — uploaded and created with both the file and stock, which is what the cart requires
|
|
113
113
|
(`quantity` is ignored). It's also the only way in: a file-less digital product is created
|
|
114
114
|
successfully, reads back healthy, and is then rejected at add-to-cart as `ITEM_NOT_FOUND_IN_CATALOG`.
|
|
115
|
+
No real, fetchable file in hand → seed the product as **physical** with `inStock: true` and tell the
|
|
116
|
+
user; swap it to a digital download once a real file exists.
|
|
115
117
|
|
|
116
118
|
Two things this module does **not** seed, so don't try:
|
|
117
119
|
|
|
@@ -138,7 +140,6 @@ const products = await seed.bulkCreateProducts(ctx, [ // → [{i
|
|
|
138
140
|
]);
|
|
139
141
|
const cats = await seed.createCategories(ctx, ["Legends"]); // sequential → [{id,name}]
|
|
140
142
|
await seed.addProductsToCategories(ctx, { [cats[0].id]: [products[0].id] });
|
|
141
|
-
// images: use the FINAL https://media.base44.com/... url only (never a /__generating__/ placeholder)
|
|
142
143
|
await seed.attachProductImages(ctx, products.map((p, i) => ({ id: p.id, url: imageUrls[i], altText: p.slug })));
|
|
143
144
|
```
|
|
144
145
|
|
|
@@ -257,7 +257,8 @@ async function uploadDigitalFile(ctx, url, fileName) {
|
|
|
257
257
|
if (!mimeType) throw new Error(`digitalFileName needs one of these extensions (${Object.keys(FILE_MIME).join(", ")}): ${fileName}`);
|
|
258
258
|
const { uploadUrl } = await req(ctx, "/site-media/v1/files/generate-upload-url", { body: { mimeType, fileName } });
|
|
259
259
|
const src = await fetch(url);
|
|
260
|
-
if (!src.ok) throw new Error(`digitalFileUrl ${url} -> ${src.status}`
|
|
260
|
+
if (!src.ok) throw new Error(`digitalFileUrl ${url} -> ${src.status}. A digital product needs a real, ` +
|
|
261
|
+
`fetchable file — with none at hand, seed this product as physical with inStock: true and tell the user.`);
|
|
261
262
|
const res = await fetch(uploadUrl, {
|
|
262
263
|
method: "PUT", headers: { "Content-Type": mimeType }, body: Buffer.from(await src.arrayBuffer()),
|
|
263
264
|
});
|
|
@@ -416,9 +417,17 @@ async function addProductsToCategories(ctx, mapping) {
|
|
|
416
417
|
// caller never manages a revision token — attach any number of times, in any pass. Wix re-hosts the
|
|
417
418
|
// image from the url server-side; the re-hosted media can take a little while to appear on read-back
|
|
418
419
|
// (propagation) — that's normal, not a failure, so we don't block on it.
|
|
420
|
+
// Wix imports the image bytes server-side, so an attach needs an absolute, publicly fetchable url.
|
|
421
|
+
const isFetchableImageUrl = (url) => typeof url === "string" && /^https:\/\//.test(url);
|
|
422
|
+
|
|
419
423
|
async function attachProductImages(ctx, items) {
|
|
420
424
|
if (!items?.length) return;
|
|
421
425
|
if (items.some((it) => !it.id)) throw new Error("Image attachment requires a product ID for every item; no image request was sent.");
|
|
426
|
+
const unfetchable = items.filter((it) => !isFetchableImageUrl(it.url));
|
|
427
|
+
if (unfetchable.length) throw new Error(
|
|
428
|
+
`Image url(s) for [${unfetchable.map((it) => it.altText || it.id).join(", ")}] are not absolute ` +
|
|
429
|
+
`https:// urls, and Wix copies the image bytes at attach time. Re-call attachProductImages once each ` +
|
|
430
|
+
`image has its final url. No image request was sent; products are unaffected.`);
|
|
422
431
|
const ids = items.map((it) => it.id);
|
|
423
432
|
const q = await req(ctx, "/stores/v3/products/query", { body: { query: { filter: { id: { $in: ids } }, paging: { limit: ids.length } } } });
|
|
424
433
|
const revById = new Map((q.products ?? []).map((p) => [p.id, p.revision]));
|
|
@@ -475,7 +484,8 @@ async function configureCurrency(ctx, requested) {
|
|
|
475
484
|
* digitalFileUrl?, digitalFileName? }],
|
|
476
485
|
* categories?: { [categoryName]: string[] }, // map of category name -> product NAMES in it
|
|
477
486
|
* }}
|
|
478
|
-
* @returns { products: [{id,slug,revision,name}], categories: [{id,name}], imagesAttached: number,
|
|
487
|
+
* @returns { products: [{id,slug,revision,name}], categories: [{id,name}], imagesAttached: number,
|
|
488
|
+
* imagesSkipped?: string[], note?: string, currency: {requested,actual,status,warnings} }
|
|
479
489
|
*/
|
|
480
490
|
async function setupStore(ctx, { products = [], categories = {}, currency } = {}) {
|
|
481
491
|
validateProducts(products);
|
|
@@ -498,11 +508,29 @@ async function setupStore(ctx, { products = [], categories = {}, currency } = {}
|
|
|
498
508
|
}
|
|
499
509
|
|
|
500
510
|
const imageItems = withNames
|
|
501
|
-
.map((p, i) => ({ id: p.id, url: products[i]?.imageUrl, altText: products[i]?.altText ?? p.slug }))
|
|
511
|
+
.map((p, i) => ({ id: p.id, url: products[i]?.imageUrl, altText: products[i]?.altText ?? p.slug, name: p.name }))
|
|
502
512
|
.filter((it) => it.url);
|
|
503
|
-
|
|
513
|
+
// A url Wix cannot fetch would fail the attach: seed the product imageless and report it,
|
|
514
|
+
// so the caller attaches once the final url exists.
|
|
515
|
+
const readyItems = imageItems.filter((it) => isFetchableImageUrl(it.url));
|
|
516
|
+
const skipped = imageItems.filter((it) => !isFetchableImageUrl(it.url)).map((it) => it.name);
|
|
517
|
+
if (readyItems.length) await attachProductImages(ctx, readyItems);
|
|
504
518
|
|
|
505
|
-
|
|
519
|
+
const withoutImages = withNames.filter((p, i) => !products[i]?.imageUrl).map((p) => p.name);
|
|
520
|
+
return {
|
|
521
|
+
products: withNames, categories: cats, imagesAttached: readyItems.length,
|
|
522
|
+
...(skipped.length && {
|
|
523
|
+
imagesSkipped: skipped,
|
|
524
|
+
note: "these products' image urls were not absolute https:// urls — attach them with " +
|
|
525
|
+
"attachProductImages once each image has its final url",
|
|
526
|
+
}),
|
|
527
|
+
...(withoutImages.length && !skipped.length && {
|
|
528
|
+
productsWithoutImages: withoutImages,
|
|
529
|
+
note: "these products were seeded without an image — once their images have final urls, " +
|
|
530
|
+
"attach them with attachProductImages",
|
|
531
|
+
}),
|
|
532
|
+
currency: currencyResult,
|
|
533
|
+
};
|
|
506
534
|
}
|
|
507
535
|
|
|
508
536
|
module.exports = {
|