@wix/agent-skills 1.23.0 → 1.24.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 +64 -50
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +4 -3
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +28 -25
- package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +8 -2
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +12 -14
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +4 -3
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +66 -9
- package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +25 -0
- package/skills/wix-app/references/editor-react-component/OVERFLOW.md +146 -0
- package/skills/wix-app/references/editor-react-component/PARTS.md +6 -0
- package/skills/wix-app/scripts/scan-a11y-eslint.cjs +25 -1
- package/skills/{wix-headless-fast → wix-headless-kit}/SKILL.md +79 -60
- package/skills/{wix-headless-fast → wix-headless-kit}/cold-start/bootstrap.mjs +2 -2
- package/skills/{wix-headless-fast → wix-headless-kit}/cold-start/cold-start.md +26 -35
- package/skills/wix-headless-kit/guides/capabilities.md +76 -0
- package/skills/wix-headless-kit/guides/feedback.md +98 -0
- package/skills/{wix-headless-fast → wix-headless-kit}/guides/migration.md +20 -9
- package/skills/{wix-headless-fast → wix-headless-kit}/install/AGENTS.md +3 -0
- package/skills/{wix-headless-fast → wix-headless-kit}/install/attach.mjs +5 -2
- package/skills/{wix-headless-fast → wix-headless-kit}/install/check.mjs +1 -1
- package/skills/wix-headless-kit/install/context.mjs +169 -0
- package/skills/{wix-headless-fast → wix-headless-kit}/install/deploy.mjs +17 -4
- package/skills/{wix-headless-fast → wix-headless-kit}/install/setup.mjs +89 -55
- package/skills/{wix-headless-fast → wix-headless-kit}/install/templates.mjs +1 -1
- package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +2 -2
- package/skills/wix-manage/references/cms/cms-data-items-crud.md +16 -16
- package/skills/wix-manage/references/cms/cms-publishing-flow.md +15 -15
- package/skills/wix-manage/references/cms/cms-schema-management.md +6 -6
- package/skills/wix-manage/references/sites/query-sites.md +1 -8
- package/skills/wix-auth/SKILL.md +0 -12
- package/skills/wix-auth/references/device-flow.md +0 -140
- package/skills/wix-headless-fast/install/context.mjs +0 -126
- /package/skills/{wix-headless-fast → wix-headless-kit}/guides/existing-site.md +0 -0
- /package/skills/{wix-headless-fast → wix-headless-kit}/guides/reference-mode.md +0 -0
- /package/skills/{wix-headless-fast → wix-headless-kit}/install/agents-md.mjs +0 -0
- /package/skills/{wix-headless-fast → wix-headless-kit}/install/lock.mjs +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Capability map: which Wix product owns what, and what this skill ships for it
|
|
2
|
+
|
|
3
|
+
Read this when the Verticals table in SKILL.md does not settle the match: the brief names a Wix
|
|
4
|
+
product or a feature the table does not mention, two rows could fit, or the request sounds like a
|
|
5
|
+
vertical this skill does not ship. Every Wix product, its docs path (relative to
|
|
6
|
+
`https://dev.wix.com/docs/api-reference/`), the features its introduction page lists, and the
|
|
7
|
+
column that matters here: what this skill ships for it. Features come from the introduction pages;
|
|
8
|
+
when a product looks wrong or missing, re-derive from `<path>/introduction.md` through `wix-docs`.
|
|
9
|
+
|
|
10
|
+
"Shipped" means the vertical's data layer, stores, hooks, components and seed cover it; "read only"
|
|
11
|
+
means the DTO carries it but nothing acts on it; "not shipped" means the feature is built from the
|
|
12
|
+
API reference through `wix-docs` on the same project, with the same rules as every other call.
|
|
13
|
+
|
|
14
|
+
## Business solutions
|
|
15
|
+
|
|
16
|
+
| Product | Path | Features (from the introduction page) | This skill |
|
|
17
|
+
|---|---|---|---|
|
|
18
|
+
| Stores | `business-solutions/stores` | Products, categories, options and variants, inventory, brands, ribbons, info sections, customizations (modifiers), promotions, store locations, site currency, currency conversion | **storefront**: products, categories, options and variants, inventory and low stock, pre-order, ribbons, info sections, modifiers, discount names, subscriptions, back in stock, site currency (set by the seed). Not shipped: brands, store locations, currency conversion |
|
|
19
|
+
| eCommerce | `business-solutions/e-commerce` | Cart, checkout, abandoned checkout, orders, transactions, fulfillment, discount rules, recommendations, shipping rates, additional fees, payments, catalog | **storefront**, **restaurants**, **bookings**, **events**, **donations** use it for the cart line, totals (discounts, fees, taxes), coupon code, buyer note and the checkout redirect session; order read on the events and donations thank-you pages. Not shipped: abandoned checkout, fulfillment, shipping rates, recommendations |
|
|
20
|
+
| Coupons | `business-solutions/coupons` | Coupons, percentage and fixed discounts, free shipping, buy X get Y, scopes, usage limits, expiry | Applied at the cart by **storefront**; created through a `wix-manage` recipe when the brief asks (no coupon seed) |
|
|
21
|
+
| Bookings | `business-solutions/bookings` | Services, appointments, classes, courses, staff, resources, pricing, policies, time slots, bookings, waitlists, external calendar, checkout and orders | **bookings**: appointments, classes and courses, staff, time slots and sessions, rate types, deposits, policies as the call to action, locations, categories, booking to checkout or direct placement. Read only: waitlist flag on a slot, add-ons. Not shipped: non-staff resources, external calendar |
|
|
22
|
+
| Rentals | `business-solutions/rentals` | Rental services, hourly and daily durations, customer-selected length, bookable resources, resource attributes, per-hour and per-day pricing, availability, consecutive multi-day bookings | **rentals**: the catalog (Bookings services carrying the Rentals app id), hourly starts then end options, daily starts then the consecutive-day walk, the server-priced quote, the Rentals booking form, booking with the start's resource and the customer's end, checkout-or-place; the seed creates resource types, resources (bookable around the clock) and rental services one at a time. Not shipped: resource attributes and attribute filters, per-resource working hours (which split a multi-day rental into one booking per day), multi-service bookings |
|
|
23
|
+
| Meetings | `business-solutions/meetings` | Scheduling links, shareable booking page, duration and location, video or phone or in person, hosts, calendar sync, intake forms, paid meetings, rescheduling | **Not shipped.** Also Bookings underneath; a scheduling-link brief is built through `wix-docs` |
|
|
24
|
+
| Restaurants | `business-solutions/restaurants` | Menus, sections, items, variants, modifiers, labels, online orders, operations, fulfillment methods, availability exceptions, service fees, reservations, time slots, experiences | **restaurants**: menus, sections, items, variants, modifier rules, labels, ordering (operations, fulfillment methods, windows), reservations with the location's form and time slots, money from the eCommerce settings. Not shipped: service fees in the menu totals, experiences |
|
|
25
|
+
| Events | `business-solutions/events` | Events, ticket definitions, tickets, RSVP, orders and checkout, check-in, guests, guest list, schedule, policies | **events**: listing and event pages, occurrences, RSVP with the organizer's form and guest control, ticket tiers to checkout, order read on the confirmation page, categories. Not shipped: check-in, guest list, schedule |
|
|
26
|
+
| Blog | `business-solutions/blog` | Posts, draft posts, categories, tags, post stats, blog roles, paid post subscriptions | **blog**: feed, post pages, categories and tags, authors, metrics, likes, related posts, comments through Community. Seed writes draft posts and publishes them. Not shipped: paid post subscriptions, roles |
|
|
27
|
+
| CMS | `business-solutions/cms` | Data items, collections, collection permissions, aggregations, indexes, external databases, backups, background tasks | **cms**: collections and items with filters, sort, distinct values, paging, references, permissions set by the seed. Not shipped: indexes, external databases, backups |
|
|
28
|
+
| Pricing Plans | `business-solutions/pricing-plans` | Plans, orders, recurring, single payment, free plans, free trials, cancellation, credits | **pricing-plans**: plans with trials and fees, the plan gate on the member's orders, purchase through the native checkout redirect. Not shipped: cancellation, credits |
|
|
29
|
+
| Portfolio | `business-solutions/portfolio` | Projects, project items, collections, settings, gallery layouts, cover media | **portfolio**: collections, projects, galleries with images and video. Not shipped: settings |
|
|
30
|
+
| Donations | `business-solutions/donations` | Campaigns, goals, one-time and recurring, predefined and custom amounts, cover fees, progress | **donations**: all of it, through the eCommerce checkout |
|
|
31
|
+
| Gift Cards | `business-solutions/gift-cards` | Gift cards, gift card products, redemption codes, balances, denominations, expiry, transactions | Not shipped |
|
|
32
|
+
| Benefit Programs | `business-solutions/benefit-programs` | Programs, templates, tiers, credits, redemption, enrollment, balances, eligibility | Not shipped; program activation is dashboard-only |
|
|
33
|
+
| Suppliers Hub | `business-solutions/suppliers-hub` | Marketplace products, suppliers, dropshipping, wholesale tiers | Not shipped; partner-only |
|
|
34
|
+
| Forum | `business-solutions/forum` | Deprecated (discontinued March 2026) | Not shipped; do not build on it. Discussion is blog comments or Community groups |
|
|
35
|
+
|
|
36
|
+
## Site-wide products
|
|
37
|
+
|
|
38
|
+
| Product | Path | Features | This skill |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| Members & Contacts | `crm/members-contacts` | Contacts, labels, extended fields, notes, members, profiles, authentication, privacy, badges, followers | **members**: sign-up, login, verification, logout, the current member's profile, gated pages. Not shipped: contacts, labels, badges, followers, profile editing |
|
|
41
|
+
| Forms | `crm/forms` | Form schemas, submissions, templates, intake forms, interactive sessions, chat settings | **forms**: the schema rendered live, every field kind, rules, steps, submissions with files (paid plans) or through the media-upload capability. Not shipped: templates, interactive sessions, chat |
|
|
42
|
+
| FAQ | `business-management/faq-app` | Categories, question entries | **faq**: all of it |
|
|
43
|
+
| Site Search | `business-management/site-search` | Search, search schemas | the **site-search** capability: federated search and suggestions over the deployed verticals |
|
|
44
|
+
| Media Manager | `assets/media` | Files, folders, upload URLs | the **media-upload** capability (a validated Astro endpoint and a client helper); images in every seed |
|
|
45
|
+
| SEO | `business-management/seo` | Site tags, patterns, item tags, resolved tags, redirects | owner-editable item SEO on every Astro item page that has a Wix SEO item type (products, posts, services, events, categories) |
|
|
46
|
+
| Community | `crm/community` | Groups, membership, comments, reviews, moderation | Comments only, inside **blog**. Not shipped: groups, reviews |
|
|
47
|
+
| Loyalty Program | `crm/loyalty-program` | Points, earning rules, tiers, accounts, rewards, loyalty coupons | Not shipped |
|
|
48
|
+
| Online Programs | `business-management/online-programs` | Programs, sections, steps, enrollment, payment | Not shipped (a paid course a member enrolls in is pricing-plans plus gated pages, or this) |
|
|
49
|
+
| Locations | `business-management/locations` | Locations, default location, business schedule, special hours | Read by **bookings** and **restaurants** for their locations; not managed |
|
|
50
|
+
| Communication, CRM, Automations, Marketing, Payments, Get Paid, Multilingual, Notifications, Branches, Analytics, Calendar | `crm/…`, `business-management/…` | see each introduction page | Not shipped; back-office or infrastructure, driven from `wix-manage` recipes or `wix-docs` when a brief needs one |
|
|
51
|
+
|
|
52
|
+
## Where things actually live
|
|
53
|
+
|
|
54
|
+
- Meetings and Rentals ship no APIs of their own: both are Bookings with restricted field values,
|
|
55
|
+
so their contracts are the Bookings ones. A rentals site also needs the Wix Bookings app installed
|
|
56
|
+
(the rentals seed does it): with Rentals alone, availability for an hourly rental with several
|
|
57
|
+
units answers 401 "Booking app not installed".
|
|
58
|
+
- Loyalty coupons (`crm/loyalty-program/rewards/coupons`) are a different resource from eCommerce
|
|
59
|
+
Coupons (`business-solutions/coupons`).
|
|
60
|
+
- Stores categories are called Collections in Catalog V1 and Categories in Catalog V3; the shipped
|
|
61
|
+
code is V3.
|
|
62
|
+
- SEO spans two products: the tag model is `business-management/seo`; Ads.txt and keyword
|
|
63
|
+
suggestions are under `business-management/marketing/seo`.
|
|
64
|
+
- Badges and Followers live under `crm/members-contacts/members/activity/`, profiles under
|
|
65
|
+
`members/member-management/members-about-v2`, privacy under `member-management/privacy`.
|
|
66
|
+
- There is no roles API and no segments API; contact labels serve segmentation.
|
|
67
|
+
- Stores, Coupons and Suppliers Hub have no usable introduction page; start from the menu page and
|
|
68
|
+
the sub-section introductions.
|
|
69
|
+
|
|
70
|
+
## When the brief lands on "not shipped"
|
|
71
|
+
|
|
72
|
+
Say so plainly in one line, then build it on the same project and stack from the API reference
|
|
73
|
+
through `wix-docs` (search, then the method page), with every other rule unchanged: nothing from
|
|
74
|
+
memory, live data or an honest empty state, purchases through Wix. Choose the closest shipped
|
|
75
|
+
vertical as the base when one exists (a meetings brief starts from bookings, a loyalty brief from
|
|
76
|
+
members), and name the gap in the closing message.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Feedback: relay the user's building-with-Wix experience to Wix
|
|
2
|
+
|
|
3
|
+
A small, optional step: send the user's feedback about the experience of building with Wix to Wix,
|
|
4
|
+
attributed to the authenticated user. It closes the loop when this skill, the shipped code, the
|
|
5
|
+
APIs, the docs or the tooling got in the way. It is not support and not about the user's site
|
|
6
|
+
content; it is feedback about building with Wix.
|
|
7
|
+
|
|
8
|
+
## When to offer it
|
|
9
|
+
|
|
10
|
+
Sending is always the user's call. Offering is not: default to offering, in plain prose, once per
|
|
11
|
+
issue, in any of these cases, and send only after an explicit yes.
|
|
12
|
+
|
|
13
|
+
- The user asks to send feedback or report something to Wix. Confirm the wording and send.
|
|
14
|
+
- The user complains, is frustrated, or reports a Wix bug while you work. Acknowledge, then offer.
|
|
15
|
+
- The run hit friction, even once. Friction is anything that cost more turns than it should have,
|
|
16
|
+
whether or not it ended in an error: a confusing error, a doc that was wrong or missing, a seed
|
|
17
|
+
step that failed and had to be re-run, a shipped file that did not cover what the brief needed, a
|
|
18
|
+
playbook line you had to read the source to understand, a contract you had to discover by trial,
|
|
19
|
+
a slow install or a flaky call you retried, a workaround you had to invent, a platform gate the
|
|
20
|
+
brief did not anticipate (a plan restriction, a missing payment method), a step where you were
|
|
21
|
+
unsure what the skill wanted. Offer in the moment: "That tripped us up; want me to send it to Wix
|
|
22
|
+
as feedback?"
|
|
23
|
+
- At the close of every run, before the live URL and the dashboard link, run a self-check over the
|
|
24
|
+
whole session. Friction you shrugged off or silently retried past is still signal. If anything
|
|
25
|
+
qualifies, offer before you sign off. Skip the offer only when the run was clean end to end.
|
|
26
|
+
|
|
27
|
+
When you offer, invite the user to add anything in their own words; it goes into the message
|
|
28
|
+
verbatim under "In the user's words". Never send on a single transient error, never without a yes,
|
|
29
|
+
never twice for the same issue. When unsure, ask.
|
|
30
|
+
|
|
31
|
+
## Compose the message
|
|
32
|
+
|
|
33
|
+
Wix receives free text, so a bare sentence is low signal. Send a summary of the whole run in three
|
|
34
|
+
layers, so Wix can triage without chasing you.
|
|
35
|
+
|
|
36
|
+
**Provenance**, as labelled lines; drop what does not apply, add what helps:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
Agent / model: <Claude Code / Opus, Cursor, Codex, ...>
|
|
40
|
+
Skill: wix-headless-kit <version from .agents/skills/wix-headless-kit/SKILL.md or skills-lock.json> · run kind: <create | connect | attach | iterate | reference mode | migration preview>
|
|
41
|
+
Stack: <astro | react | lib | static | port> · verticals: <storefront, blog, ...> · capabilities: <media-upload, site-search, none>
|
|
42
|
+
Wix tooling used: <Wix CLI, wix-manage recipes, wix-docs, REST via curl>
|
|
43
|
+
Wix products: <Stores, Bookings, Events, Blog, Forms, ...>
|
|
44
|
+
Site: <siteId> · public clientId: <appId> · dashboard: <url> · live: <url>
|
|
45
|
+
Skill files involved: <templates/<vertical>/seed/seed-<v>.mjs, templates/<vertical>/INSTRUCTIONS.md, install/setup.mjs, ...>
|
|
46
|
+
Other ids: <product / service / form / event ids created this run, as relevant>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Narrative:**
|
|
50
|
+
|
|
51
|
+
- In the user's words: what they added when you offered, verbatim, secrets redacted. Skip when empty.
|
|
52
|
+
- User intent and run summary: what they set out to build and the arc of the session in a few
|
|
53
|
+
sentences, what worked and what fought back.
|
|
54
|
+
- Conversation and agent flow: a condensed play-by-play, the key exchanges, the scripts and calls
|
|
55
|
+
you ran, what came back, the decisions and course corrections. Distilled, not a transcript.
|
|
56
|
+
- Friction points: the heart of it. Every place something got in the way, each with the step or
|
|
57
|
+
endpoint, the status and message, the gap, the workaround and what you expected instead, with a
|
|
58
|
+
minimal repro where there is one. Include the ones you recovered from.
|
|
59
|
+
|
|
60
|
+
**Attribution**, per significant friction point, your best diagnosis tagged with one of: API
|
|
61
|
+
behavior, API schema, API reference docs, docs articles or examples, Wix harness (CLI, auth, hosting),
|
|
62
|
+
this skill's shipped code, this skill's playbook, other or unsure; and whether you confirmed it or
|
|
63
|
+
are assuming. A wrong route is worse than "unsure".
|
|
64
|
+
|
|
65
|
+
**Bottom line**: one or two sentences naming the single most important problem and its impact,
|
|
66
|
+
worst first, plainly, in a professional register.
|
|
67
|
+
|
|
68
|
+
Confirm the final wording with the user before sending. Never include secrets (no bearer tokens,
|
|
69
|
+
refresh tokens, API keys, credentials) and no personal data beyond what the feedback needs.
|
|
70
|
+
|
|
71
|
+
## Send it
|
|
72
|
+
|
|
73
|
+
The call identifies the human account, so it needs a user-scoped bearer from the bare token
|
|
74
|
+
command, not the site-scoped one the seeds use (`token --site` carries a metaSiteId and the service
|
|
75
|
+
rejects it as anonymous).
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
TOKEN=$(npx @wix/cli@latest token)
|
|
79
|
+
curl -sS -w "\nHTTP_STATUS:%{http_code}" \
|
|
80
|
+
-X POST "https://www.wixapis.com/mcp-serverless/v1/headless-feedback" \
|
|
81
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
82
|
+
-H "Content-Type: application/json" \
|
|
83
|
+
-d '{"message":"<composed feedback>"}'
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- `HTTP_STATUS:200` with `{}`: sent. Tell the user.
|
|
87
|
+
- `500` "Unable to determine target user id, anonymous messages are not allowed": the token was
|
|
88
|
+
site-scoped. Re-mint with the bare command and retry once.
|
|
89
|
+
- `401` or `403`: the CLI session expired. `npx @wix/cli@latest login` (surface the URL and code to
|
|
90
|
+
the user), re-mint, retry once. If it still fails, show the response and stop.
|
|
91
|
+
|
|
92
|
+
## Rules
|
|
93
|
+
|
|
94
|
+
- Offer whenever the run warrants it; send only after an explicit yes.
|
|
95
|
+
- One submission per issue; no retries beyond the one named above, no duplicates.
|
|
96
|
+
- Specific and factual; wording confirmed first.
|
|
97
|
+
- No tokens, secrets, credentials or unnecessary personal data in the message.
|
|
98
|
+
- Not for the user's site content and not a support channel.
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
# A migration preview: a site being moved to headless
|
|
2
2
|
|
|
3
3
|
Read when setup reports `mode: "migrate"`, or when a folder holds a `wix.config.json` and
|
|
4
|
-
`node <SKILL_ROOT>/install/context.mjs` prints `migration.active: true`. The brief
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
`node <SKILL_ROOT>/install/context.mjs` prints `migration.active: true`. The brief is the prompt
|
|
5
|
+
the Wix dashboard's Headless settings hand the owner after "Go Headless": download the project from
|
|
6
|
+
`https://manage.wix.com/download-headless-business/<siteId>/download.zip`, the names of the apps
|
|
7
|
+
the site already has, and the instruction not to probe, install or seed anything. The zip holds
|
|
8
|
+
`wix.config.json` (the deploy site and its app) beside the CLI's blank Astro starter.
|
|
9
|
+
|
|
10
|
+
**What `.env.local` says.** `wix env pull` copies the project's `prod` environment: the parent's
|
|
11
|
+
`WIX_CLIENT_ID`, and the migration's own variables, `EDITOR_MIGRATION_STATUS` (`ACTIVE` while the
|
|
12
|
+
migration is under way, `COMPLETED` once the parent serves this frontend), `EDITOR_MIGRATION_PARENT_SITE_ID`,
|
|
13
|
+
`EDITOR_MIGRATION_CHILD_SITE_ID` and `EDITOR_MIGRATION_CHILD_APP_ID`. `context.mjs` reads the first
|
|
14
|
+
two; the shape is `migration` whenever the status is active, whatever else the folder holds.
|
|
7
15
|
|
|
8
16
|
**Two sites, one project.** `wix.config.json` names a site created only to host the deployment:
|
|
9
17
|
`wix release` goes there and nowhere else. `.env.local` (what `wix env pull` writes; setup and
|
|
@@ -28,16 +36,19 @@ manages. So:
|
|
|
28
36
|
`read-site.mjs` sizes the content as in `guides/existing-site.md`; when it says not to probe,
|
|
29
37
|
design from the brief.
|
|
30
38
|
|
|
31
|
-
**The run.** `setup.mjs --vertical <vertical> [--stack <stack>]` in the folder: it
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
**The run.** `setup.mjs --vertical <vertical>[,<vertical>…] [--stack <stack>]` in the folder (every vertical the brief needs, in one call): it keeps the
|
|
40
|
+
starter the download carries and deploys the vertical's code and dependencies into it (a bare config
|
|
41
|
+
gets the composed template copied in around it), starts the install, writes the project's AGENTS.md
|
|
42
|
+
with the migration recorded, and skips the seed. Then
|
|
34
43
|
SKILL.md steps 4 and 5 as for any run. `attach.mjs` refuses a migration folder on purpose: the
|
|
35
44
|
app, hosting and credentials came with the download; nothing is provisioned or re-pointed.
|
|
36
45
|
|
|
37
46
|
**The close.** The release is a **preview** on the deploy site. Close with the preview URL (copied
|
|
38
47
|
from the `wix release` output), the parent's dashboard link, and the two facts: the original site
|
|
39
48
|
is unchanged, and completing the migration, which makes the parent serve this frontend and retires
|
|
40
|
-
the deploy site, is the user's next step
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
the deploy site, is the user's next step once they approve the preview: the dashboard hands them
|
|
50
|
+
a second prompt for it (`wix env pull`, `wix finalize-migration`, `wix build`, `wix release`, in
|
|
51
|
+
that order). That step is not part of this skill and the command may not be in the installed CLI
|
|
52
|
+
yet; do not invent one, do not run `wix release` against the parent, and do not edit
|
|
53
|
+
`wix.config.json`. On every stack the code already carries the parent's client id,
|
|
43
54
|
so completion needs no redeploy from here.
|
|
@@ -29,6 +29,9 @@ Installed at `.agents/skills/`. If missing, restore with:
|
|
|
29
29
|
site holds for it, with the documentation URL of every call it made. A code change ends with a release; the live URL shows it, the dev server does not count.
|
|
30
30
|
`node .agents/skills/{{SKILL}}/install/check.mjs` says whether the skill or its templates have a newer
|
|
31
31
|
version and prints the update commands; an update touches the skill folder or `templates/`, never `src/`.
|
|
32
|
+
When Wix gets in the way of a change here (a confusing error, a doc gap, a workaround you had to
|
|
33
|
+
invent), offer to relay it to Wix per `.agents/skills/{{SKILL}}/guides/feedback.md`; send only after
|
|
34
|
+
an explicit yes.
|
|
32
35
|
- `wix-docs` — how to discover the Wix APIs and their docs: search first, then read only the page
|
|
33
36
|
you need. Every endpoint, body, field and enum you did not get from the deployed code or a recipe
|
|
34
37
|
is confirmed there before you write it.
|
|
@@ -45,7 +45,7 @@ import { cpSync, existsSync, mkdirSync, openSync, readFileSync, writeFileSync }
|
|
|
45
45
|
import { basename, dirname, join, resolve } from "node:path";
|
|
46
46
|
import { fileURLToPath } from "node:url";
|
|
47
47
|
import { writeAgentsMd } from "./agents-md.mjs";
|
|
48
|
-
import { siteContext } from "./context.mjs";
|
|
48
|
+
import { frontendPresent, siteContext } from "./context.mjs";
|
|
49
49
|
import { listVerticals, templatesDir } from "./templates.mjs";
|
|
50
50
|
|
|
51
51
|
const SKILL_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -76,7 +76,10 @@ const subfolder = argv.includes("--subfolder");
|
|
|
76
76
|
const cwd = process.cwd();
|
|
77
77
|
const has = (p) => existsSync(join(cwd, p));
|
|
78
78
|
const cwdConfig = has("wix.config.json") ? JSON.parse(readFileSync(join(cwd, "wix.config.json"), "utf8")) : null;
|
|
79
|
-
|
|
79
|
+
// A frontend here: a package.json, an index.html at the root, or an index.html in the folder the
|
|
80
|
+
// config's site.outputDirectory names (a static site laid out for release) — install/context.mjs.
|
|
81
|
+
const fp = frontendPresent(cwd);
|
|
82
|
+
const hasProject = fp.packageJson || fp.rootIndex || fp.outputIndex;
|
|
80
83
|
// A migration preview (wix.config.json names a deploy-only site, .env.local names the site being
|
|
81
84
|
// migrated) is already provisioned: its app, hosting and credentials came with the folder. Nothing
|
|
82
85
|
// here applies — setup.mjs takes it (SKILL.md step 3).
|
|
@@ -24,7 +24,7 @@ const { repo } = installSource();
|
|
|
24
24
|
const out = { skill: {}, templates: {}, update: {} };
|
|
25
25
|
|
|
26
26
|
// ---- the repository: one clone of its history without file contents (small), read for both layers
|
|
27
|
-
const tmp = mkdtempSync(join(tmpdir(), "wix-headless-
|
|
27
|
+
const tmp = mkdtempSync(join(tmpdir(), "wix-headless-kit-check-"));
|
|
28
28
|
const clone = git(["clone", "--quiet", "--filter=blob:none", "--no-checkout", "--single-branch", repo, tmp]);
|
|
29
29
|
if (clone.status !== 0) {
|
|
30
30
|
rmSync(tmp, { recursive: true, force: true });
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// The site context of a project folder — the one place that says which site a call targets.
|
|
2
|
+
//
|
|
3
|
+
// node <SKILL_ROOT>/install/context.mjs [--refresh] [--no-pull] (prints one JSON object)
|
|
4
|
+
//
|
|
5
|
+
// Two identities live in a Wix project and are the same site almost always:
|
|
6
|
+
// deploy — `wix.config.json` (`siteId`, `appId`): where `wix release` uploads. The CLI's business.
|
|
7
|
+
// content — `.env.local` (`WIX_CLIENT_ID`, what `wix env pull` writes): the app the SDK client
|
|
8
|
+
// runs as, on every stack (the Astro integration reads WIX_CLIENT_ID from the env and
|
|
9
|
+
// never the config; the other stacks get it copied into src/wix/config.ts by deploy.mjs).
|
|
10
|
+
// They differ on a MIGRATION PREVIEW: a project whose config points at a fresh site created only to
|
|
11
|
+
// host the deployment, while `.env.local` carries the credentials of the site being migrated (the
|
|
12
|
+
// parent) and says so. Then every admin, discovery and seed call targets the parent, the SDK client
|
|
13
|
+
// is the parent's, and only the release goes to the child. Completing the migration is a CLI step
|
|
14
|
+
// that does not exist yet; this module only reads the state.
|
|
15
|
+
//
|
|
16
|
+
// `env pull` runs here when `.env.local` is missing (or --refresh): it is the source of the content
|
|
17
|
+
// identity, and the Astro build refuses to run without it. Non-interactive (CI=1); a failure is
|
|
18
|
+
// reported in `pullError` and the config's ids stand in, so a caller can still work offline.
|
|
19
|
+
import { spawnSync } from "node:child_process";
|
|
20
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
|
|
23
|
+
// The variables the editor-to-headless migration writes into the child project's `prod`
|
|
24
|
+
// environment (headless-bo, editorMigrations/environmentMetadata.ts), which `wix env pull` copies
|
|
25
|
+
// into `.env.local` unchanged. The names are the platform's and are spelled once, here.
|
|
26
|
+
export const ENV = {
|
|
27
|
+
clientId: "WIX_CLIENT_ID",
|
|
28
|
+
parentSiteId: "EDITOR_MIGRATION_PARENT_SITE_ID",
|
|
29
|
+
/** ACTIVE while the migration is under way; COMPLETED once the parent serves the child's frontend. */
|
|
30
|
+
status: "EDITOR_MIGRATION_STATUS",
|
|
31
|
+
childSiteId: "EDITOR_MIGRATION_CHILD_SITE_ID",
|
|
32
|
+
childAppId: "EDITOR_MIGRATION_CHILD_APP_ID",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** KEY=value lines of a dotenv file, quotes stripped; null when the file is absent. */
|
|
36
|
+
export function readEnvFile(file) {
|
|
37
|
+
if (!existsSync(file)) return null;
|
|
38
|
+
const out = {};
|
|
39
|
+
for (const raw of readFileSync(file, "utf8").split(/\r?\n/)) {
|
|
40
|
+
const line = raw.trim();
|
|
41
|
+
if (!line || line.startsWith("#")) continue;
|
|
42
|
+
const eq = line.indexOf("=");
|
|
43
|
+
if (eq === -1) continue;
|
|
44
|
+
const key = line.slice(0, eq).trim().replace(/^export\s+/, "");
|
|
45
|
+
let value = line.slice(eq + 1).trim();
|
|
46
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
47
|
+
value = value.slice(1, -1).replace(/\\"/g, '"');
|
|
48
|
+
}
|
|
49
|
+
out[key] = value;
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function readWixConfig(cwd) {
|
|
55
|
+
const file = join(cwd, "wix.config.json");
|
|
56
|
+
if (!existsSync(file)) return null;
|
|
57
|
+
try { return JSON.parse(readFileSync(file, "utf8")); } catch { return null; }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const ENV_PULL = ["-y", "@wix/cli@latest", "env", "pull"];
|
|
61
|
+
const runPull = (dir) => spawnSync("npx", ENV_PULL, { cwd: dir, env: { ...process.env, CI: "1" }, encoding: "utf8", timeout: 180_000 });
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* `wix env pull` into `cwd/.env.local`, in place. Every project shape gets the command since Wix CLI
|
|
65
|
+
* 1.1.253 (2026-09-29): before it, a config with `site.outputDirectory` (the static stack, a site
|
|
66
|
+
* published through the drop flow) landed in a limited command set without `env`, and this pulled
|
|
67
|
+
* through a temp copy of the config. Non-interactive; a failure comes back as `error`.
|
|
68
|
+
*/
|
|
69
|
+
export function pullEnv(cwd) {
|
|
70
|
+
const envFile = join(cwd, ".env.local");
|
|
71
|
+
const r = runPull(cwd);
|
|
72
|
+
if (r.status === 0 && existsSync(envFile)) return { ok: true, via: "in place" };
|
|
73
|
+
return { ok: false, error: (r.stderr || r.stdout || "env pull produced no .env.local — is the Wix CLI logged in? (npx @wix/cli@latest whoami)").trim().slice(-400) };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Whether a frontend exists in this folder: a `package.json` (a bundled project), an `index.html` at
|
|
78
|
+
* the root (plain pages), or an `index.html` inside the folder the config's `site.outputDirectory`
|
|
79
|
+
* names (a static site laid out for release, pages under site/). Nothing else counts — not this
|
|
80
|
+
* skill's code, not the skills folder, not AGENTS.md: those say who ran here, not what is here.
|
|
81
|
+
*/
|
|
82
|
+
export function frontendPresent(cwd = process.cwd()) {
|
|
83
|
+
const has = (p) => existsSync(join(cwd, p));
|
|
84
|
+
const outDir = (readWixConfig(cwd)?.site?.outputDirectory ?? "").replace(/^\.\//, "").replace(/\/$/, "");
|
|
85
|
+
return {
|
|
86
|
+
packageJson: has("package.json"),
|
|
87
|
+
rootIndex: has("index.html"),
|
|
88
|
+
outputIndex: !!outDir && outDir !== "." && has(join(outDir, "index.html")),
|
|
89
|
+
outputDirectory: outDir || null,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* What the folder IS, from five file facts — the one classification every script and SKILL.md
|
|
95
|
+
* step 3 share: wix.config.json, its site.outputDirectory, the migration variables in .env.local,
|
|
96
|
+
* package.json, index.html. `migrationActive` comes from siteContext (it needs `.env.local`).
|
|
97
|
+
*
|
|
98
|
+
* empty nothing that reads as a project → setup CREATE: the run makes the site, seeds the plan
|
|
99
|
+
* project a frontend, no wix.config.json → setup ADOPT: `init` gives it a new, empty site, seeds the plan
|
|
100
|
+
* config-only a config, no frontend → attach.mjs on the config's site; nothing seeded
|
|
101
|
+
* migration a config whose .env.local declares an ACTIVE editor migration, with or without the blank
|
|
102
|
+
* Astro starter the download carries → setup MIGRATE; nothing seeded. Decided before the
|
|
103
|
+
* frontend test: the starter's package.json must not read as a project to iterate on
|
|
104
|
+
* wix-project a config AND a frontend (package.json, or index.html in the output folder) → iterate:
|
|
105
|
+
* never scaffold, init or reseed; deploy.mjs adds a solution, edits, release
|
|
106
|
+
* published-static a config, index.html at the ROOT, no package.json, no laid-out output folder (a site
|
|
107
|
+
* published through the drop flow and downloaded) → setup makes site/ the upload and
|
|
108
|
+
* deploys the REST layer; the config's site, no init, nothing seeded
|
|
109
|
+
*/
|
|
110
|
+
export function folderShape(cwd = process.cwd(), { migrationActive = false } = {}) {
|
|
111
|
+
const config = existsSync(join(cwd, "wix.config.json"));
|
|
112
|
+
const f = frontendPresent(cwd);
|
|
113
|
+
const next = {
|
|
114
|
+
empty: "setup.mjs --vertical <v> --business-name <brand> [--plan]: creates the site here and seeds the plan (CREATE)",
|
|
115
|
+
project: "setup.mjs --vertical <v> --stack <stack> [--plan]: init links the folder to a new, empty site, seeds the plan and deploys (ADOPT)",
|
|
116
|
+
"config-only": "attach.mjs: the site exists and has no frontend yet; read what it holds (the vertical's read-site.mjs) — nothing is seeded; the vertical's seed module with a plan only when the brief supplies or describes content",
|
|
117
|
+
migration: "setup.mjs (MIGRATE): the shipped code into the starter the download carries (or the composed template around a bare config); the site being migrated owns its content — guides/migration.md",
|
|
118
|
+
"wix-project": "iterate: never scaffold, init or reseed. deploy.mjs <vertical…> --stack <stack> adds a solution, then ONE npm install; file edits for a change; release. Read the site (read-site.mjs) before any seed module runs",
|
|
119
|
+
"published-static": "setup.mjs --vertical <v>: the config's site, no init; site/ becomes the upload and the REST layer lands in site/js/wix/; move the pages, styles and assets into site/. Nothing is seeded: read the site, then run the vertical's seed module with a plan when the brief gives content; release keeps the URL",
|
|
120
|
+
};
|
|
121
|
+
let shape;
|
|
122
|
+
if (!config) shape = f.packageJson || f.rootIndex ? "project" : "empty";
|
|
123
|
+
else if (migrationActive) shape = "migration";
|
|
124
|
+
else if (f.packageJson || f.outputIndex) shape = "wix-project";
|
|
125
|
+
else if (f.rootIndex) shape = "published-static";
|
|
126
|
+
else shape = "config-only";
|
|
127
|
+
return { shape, next: next[shape], facts: { config, ...f } };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* `{ folder: { shape, next, tells }, deploy: { siteId, appId }, content: { siteId, clientId },
|
|
132
|
+
* migration: { active, parentSiteId }, env: { file, present, pulled }, pullError?, warnings: [] }`.
|
|
133
|
+
* `pull`: "auto" (default) pulls when `.env.local` is missing; true always; false never.
|
|
134
|
+
*/
|
|
135
|
+
export function siteContext({ cwd = process.cwd(), pull = "auto" } = {}) {
|
|
136
|
+
const config = readWixConfig(cwd) ?? {};
|
|
137
|
+
const deploy = { siteId: config.siteId ?? config.projectId ?? null, appId: config.appId ?? null };
|
|
138
|
+
const envFile = join(cwd, ".env.local");
|
|
139
|
+
let pulled = false, pullError;
|
|
140
|
+
if (deploy.siteId && (pull === true || (pull === "auto" && !existsSync(envFile)))) {
|
|
141
|
+
const r = pullEnv(cwd);
|
|
142
|
+
if (r.ok) pulled = r.via;
|
|
143
|
+
else pullError = r.error;
|
|
144
|
+
}
|
|
145
|
+
const env = readEnvFile(envFile) ?? {};
|
|
146
|
+
const parentSiteId = env[ENV.parentSiteId] || null;
|
|
147
|
+
const status = env[ENV.status];
|
|
148
|
+
// ACTIVE (or a parent id with no status yet) is a migration under way; COMPLETED means the parent
|
|
149
|
+
// already serves this frontend and the project is an ordinary one again.
|
|
150
|
+
const active = !!parentSiteId && (status === undefined || status.trim().toUpperCase() === "ACTIVE");
|
|
151
|
+
const migration = { active, parentSiteId: active ? parentSiteId : null, ...(status ? { status: status.trim().toUpperCase() } : {}) };
|
|
152
|
+
const clientId = env[ENV.clientId] || deploy.appId;
|
|
153
|
+
const content = { siteId: active ? parentSiteId : deploy.siteId, clientId };
|
|
154
|
+
const warnings = [];
|
|
155
|
+
if (env[ENV.clientId] && deploy.appId && env[ENV.clientId] !== deploy.appId && !active && migration.status !== "COMPLETED") {
|
|
156
|
+
warnings.push(`.env.local ${ENV.clientId} differs from wix.config.json appId and no migration is declared — the SDK client runs as the env's app, the release goes to the config's site`);
|
|
157
|
+
}
|
|
158
|
+
if (active && migration.parentSiteId === deploy.siteId) {
|
|
159
|
+
warnings.push("the migration's parent site is the deploy site itself — nothing is being migrated");
|
|
160
|
+
}
|
|
161
|
+
return { folder: folderShape(cwd, { migrationActive: active }), deploy, content, migration, env: { file: envFile, present: Object.keys(env).length > 0, pulled }, ...(pullError ? { pullError } : {}), warnings };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ---- CLI ----------------------------------------------------------------------------------------
|
|
165
|
+
if (process.argv[1] && /context\.mjs$/.test(process.argv[1])) {
|
|
166
|
+
const argv = process.argv.slice(2);
|
|
167
|
+
const pull = argv.includes("--no-pull") ? false : argv.includes("--refresh") ? true : "auto";
|
|
168
|
+
console.log(JSON.stringify(siteContext({ pull }), null, 2));
|
|
169
|
+
}
|
|
@@ -111,6 +111,18 @@ const VERTICAL_DEPS = {
|
|
|
111
111
|
"@wix/essentials": "^1.0.6",
|
|
112
112
|
},
|
|
113
113
|
},
|
|
114
|
+
rentals: {
|
|
115
|
+
// A rental is a Bookings service with rentals-specific values: the same SDK modules as bookings.
|
|
116
|
+
core: {
|
|
117
|
+
"@wix/bookings": "^1.0.1650",
|
|
118
|
+
"@wix/auto_sdk_ecom_cart-v-2": "^1.0.192",
|
|
119
|
+
"@wix/redirects": "^1.0.125",
|
|
120
|
+
},
|
|
121
|
+
astro: {
|
|
122
|
+
"@wix/seo": "^1.0.79",
|
|
123
|
+
"@wix/essentials": "^1.0.6",
|
|
124
|
+
},
|
|
125
|
+
},
|
|
114
126
|
blog: {
|
|
115
127
|
core: {
|
|
116
128
|
"@wix/blog": "^1.0.645",
|
|
@@ -247,7 +259,7 @@ if (siteSearch) {
|
|
|
247
259
|
}
|
|
248
260
|
// The generated file is data only; the shipped core resolves defaults (types, routes, labels) from it.
|
|
249
261
|
const siteSearchConfigSource = () =>
|
|
250
|
-
`// Generated by wix-headless-
|
|
262
|
+
`// Generated by wix-headless-kit install/deploy.mjs from plan.capabilities.siteSearch.\n` +
|
|
251
263
|
`// Edit the plan and redeploy. Defaults for anything omitted are in search-core.ts (resolveConfig).\n` +
|
|
252
264
|
`export const siteSearchPlan = ${JSON.stringify(siteSearch, null, 2)};\n`;
|
|
253
265
|
// ---- static stack: the REST layer, composed flat and stripped ------------------------------------
|
|
@@ -401,7 +413,7 @@ if (uploadPolicies.length) {
|
|
|
401
413
|
// The generated file is data only. The shipped endpoint owns validation and elevation.
|
|
402
414
|
writeFileSync(
|
|
403
415
|
configFile,
|
|
404
|
-
`// Generated by wix-headless-
|
|
416
|
+
`// Generated by wix-headless-kit install/deploy.mjs from plan.capabilities.mediaUpload.\n` +
|
|
405
417
|
`// Edit the plan and redeploy; do not add browser-controlled policy selection here.\n` +
|
|
406
418
|
`export const mediaUploadPolicies = ${JSON.stringify(uploadPolicies, null, 2)} as const;\n`,
|
|
407
419
|
);
|
|
@@ -506,8 +518,9 @@ if (!requested.length) {
|
|
|
506
518
|
}
|
|
507
519
|
|
|
508
520
|
// ---- client ids ---------------------------------------------------------------------------------
|
|
509
|
-
// The shared data client is ambient on managed Astro
|
|
510
|
-
//
|
|
521
|
+
// The shared data client is ambient on managed Astro, and so is the members flow there (the
|
|
522
|
+
// integration's built-in /api/auth routes). WIX_MEMBERS_CLIENT_ID is still filled for projects whose
|
|
523
|
+
// members code predates the shared seam; the shipped code reads WIX_CLIENT_ID only.
|
|
511
524
|
// --client-id, else the CONTENT app: .env.local's WIX_CLIENT_ID (what `wix env pull` writes — on a
|
|
512
525
|
// migration preview the parent site's app, the one the Astro integration itself runs as), else the
|
|
513
526
|
// config's appId. Never the config first: on a preview that is the deploy-only child app.
|