@wix/agent-skills 1.31.2 → 1.33.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.
Files changed (43) hide show
  1. package/README.md +4 -12
  2. package/package.json +1 -1
  3. package/skills/wix-app/SKILL.md +39 -15
  4. package/skills/wix-app/references/BACKEND_API.md +1 -1
  5. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +47 -45
  6. package/skills/wix-app/references/SDK_MODULE_MAP.md +1 -1
  7. package/skills/wix-app/references/STORES_VERSIONING.md +24 -2
  8. package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +9 -13
  9. package/skills/wix-app/references/dashboard-page/IMAGE_RENDERING.md +61 -0
  10. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +54 -64
  11. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +25 -27
  12. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +37 -30
  13. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +43 -29
  14. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +42 -42
  15. package/skills/wix-app/references/editor-react-component/DISABLED-INVALID.md +31 -0
  16. package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +14 -1
  17. package/skills/wix-app/references/editor-react-component/PARTS.md +40 -9
  18. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +22 -2
  19. package/skills/wix-app/references/editor-react-component/SSR.md +6 -3
  20. package/skills/wix-app/scripts/scan-a11y-eslint.cjs +39 -16
  21. package/skills/wix-app/scripts/sdk-curated.json +45 -0
  22. package/skills/wix-app/scripts/sdk-lookup.cjs +1180 -0
  23. package/skills/wix-base44-connector/SKILL.md +4 -2
  24. package/skills/wix-base44-connector/scripts/utils.cjs +5 -2
  25. package/skills/wix-headless-kit/SKILL.md +4 -1
  26. package/skills/wix-headless-kit/guides/api-run.md +14 -20
  27. package/skills/wix-headless-kit/install/pins.json +1 -1
  28. package/skills/wix-manage/SKILL.md +30 -8
  29. package/skills/wix-manage/references/automations/actions.md +134 -0
  30. package/skills/wix-manage/references/automations/activation-status.md +64 -48
  31. package/skills/wix-manage/references/automations/api-catalog.md +213 -77
  32. package/skills/wix-manage/references/automations/automation-model.md +199 -0
  33. package/skills/wix-manage/references/automations/bracket-expressions.md +132 -0
  34. package/skills/wix-manage/references/automations/build-and-manage-automations.md +305 -26
  35. package/skills/wix-manage/references/automations/triggers.md +190 -0
  36. package/skills/wix-manage/references/collaborators/manage-site-collaborators.md +128 -0
  37. package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +3 -1
  38. package/skills/wix-manage/references/forms/read-forms-and-submissions.md +277 -0
  39. package/skills/wix-manage/references/forms/update-form.md +5 -0
  40. package/skills/wix-manage/references/seo/manage-url-redirects.md +33 -4
  41. package/skills/wix-manage/references/sites/create-headless-site.md +14 -5
  42. package/skills/wix-manage/references/sites/upload-static-site.md +373 -302
  43. package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +3 -3
package/README.md CHANGED
@@ -10,7 +10,7 @@ Agent skills for building Wix app extensions, managing Wix business solutions, d
10
10
 
11
11
  ### Claude Code Plugin
12
12
 
13
- In [Claude Code](https://docs.anthropic.com/en/docs/claude-code), run:
13
+ In [Claude Code](https://docs.anthropic.com/en/docs/claude-code), run:
14
14
 
15
15
  ```bash
16
16
  /plugin marketplace add wix/skills
@@ -63,7 +63,7 @@ npx skills add wix/skills -g
63
63
  | [wix-headless](skills/wix-headless/SKILL.md) | Connect Wix business services to a headless frontend (SDK + Wix CLI), and optionally build & host the site | Setting up a Wix Headless backend or adding Wix business features (Stores, Bookings, CMS, Blog, Events, Forms, Members, Restaurants, Portfolio, Pricing Plans) — install apps, seed content, and produce an SDK-integration guide; for managed projects also scaffold a new site (create) or wire an existing design (connect), then build and release. Works across managed, self-managed, and stripe project types |
64
64
  | [wix-vibe-headless](skills/wix-vibe-headless/SKILL.md) | Connect an existing front end to Wix over client-only REST | Wiring a vibe-coded / HTML / Vite app to a live Wix site (storefront, bookings, blog, events, portfolio, restaurants, CMS, pricing plans) from the browser with a public `WIX_CLIENT_ID` — no SDK, no backend |
65
65
  | [wix-docs](skills/wix-docs/SKILL.md) | Look up the Wix API/SDK docs (shared fallback) | Confirming an exact Wix endpoint, method schema, field, or enum before writing code — `curl` doc-search + the `.md`-twin trick, or the Wix MCP tools. Referenced by the other skills as their docs-lookup fallback |
66
- | [replatform](replatform/README.md) | Migrate sites from WordPress and other platforms into Wix | Migrating an exiting business from another platform into Wix. Both backend data and website. `npx skills add wix/skills/replatform` |
66
+ | [wix-replatform](wix-replatform/README.md) | Migrate sites from WordPress and other platforms into Wix | Migrating an existing business from another platform into Wix. Both backend data and website. `npx skills add wix/skills/wix-replatform` |
67
67
 
68
68
  ## Supported Agents
69
69
 
@@ -89,21 +89,13 @@ These skills work with any agent that supports the [Agent Skills specification](
89
89
 
90
90
  When a major bump is required (a breaking change in the underlying `wix-cli`), the previous major continues on a `release/<N>.x` maintenance branch and receives backports for genuine bugs only — no new features.
91
91
 
92
- ## Releasing
93
-
94
- Run the [`release-bump`](.github/workflows/release-bump.yml) workflow from the **Actions** tab and pick a `version_strategy`. The rest is automatic — the bump PR auto-merges once checks pass and [`release.yml`](.github/workflows/release.yml) publishes to npm via Trusted Publishing.
95
-
96
92
  ## Serving (`www.wix.com/skills`)
97
93
 
98
- Besides the npm package, skills are served as raw markdown / `.tgz` at `https://www.wix.com/skills/<name>` (also `dev.wix.com/skills`), directly from this repo's `main` branch with no build step. Responses are cached, so a merge to `main` reflects there within a few minutes.
94
+ Besides the npm package, skills are served as raw markdown / `.tgz` at `https://www.wix.com/skills/<name>` (also `dev.wix.com/skills`), directly from the `main` branch of `wix/skills` with no build step. Responses are cached, so a change reflects there within a few minutes of reaching that branch.
99
95
 
100
96
  ## Contributing
101
97
 
102
- See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on adding new skills.
103
-
104
- ### Eval Token Budgets
105
-
106
- Eval scenarios under `yaml/wix-manage-evals/` may define a top-level `maxTokens` value. The GitHub Actions eval gate compares that budget against the PR run's total tokens for the scenario and fails the PR check when the budget is exceeded. This gate-owned field is separate from `llm_judge.maxTokens`, which only configures the judge assertion.
98
+ To report a problem with a skill or suggest a change, [open an issue](https://github.com/wix/skills/issues/new). Pull requests are not merged in this repository; accepted changes are made by the maintainers. See [CONTRIBUTING.md](CONTRIBUTING.md) for what makes a useful report.
107
99
 
108
100
  ## License
109
101
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/agent-skills",
3
- "version": "1.31.2",
3
+ "version": "1.33.0",
4
4
  "description": "Wix Skills for AI coding agents — versioned npm distribution of the wix/skills content.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,8 +33,8 @@ Helps build extensions for Wix CLI applications. Covers all extension types: das
33
33
  - [ ] **🛑 Component Docs Gate (MANDATORY, dashboard UI only):** For each patterns symbol you are about to write, decided **from the lookup output** which single artifact answers the question you actually have — the import line, an example, or the props file — and read only that one, per [Component Selection Order](#component-selection-order)'s "the short version". State which artifact you read per symbol, and why, before the first line of JSX. Reading a doc *and* its bundle for the same symbol, or opening a page for an import line the lookup already gave you, is the failure this gate exists to prevent.
34
34
 
35
35
  For the object `useTableCollection()` returns, read [TABLE_STATE.md](references/dashboard-page/TABLE_STATE.md) — a state object you receive rather than construct, whose members are unobvious and several plausible ones absent.
36
- - [ ] **Step 3:** Checked API references; used MCP discovery only for gaps
37
- - [ ] **Dashboard page over Wix data:** located the method and verified every mapped field against the installed SDK's own declaration first — see [DATA_SOURCES.md](references/dashboard-page/DATA_SOURCES.md), and [QUERY_AND_PAGING.md](references/dashboard-page/QUERY_AND_PAGING.md) before writing `fetchData`. A field marked `@deprecated` still compiles and renders something plausible and wrong.
36
+ - [ ] **Step 3:** Checked API references; resolved every vertical entity in **one** `sdk-lookup.cjs` call ([SDK lookup](#sdk-lookup-one-call-for-every-vertical-entity)); used the docs only for what it does not print
37
+ - [ ] **Dashboard page over Wix data:** took the method from the lookup and verified every mapped field against the declaration it points to (`type … file:line`) — see [DATA_SOURCES.md](references/dashboard-page/DATA_SOURCES.md), and [QUERY_AND_PAGING.md](references/dashboard-page/QUERY_AND_PAGING.md) before writing `fetchData`. A field marked `@deprecated` still compiles and renders something plausible and wrong.
38
38
  - [ ] **Vertical SDK prerequisites — for every `@wix/*` vertical the page touches, including one added later:** confirmed the package is actually a dependency (installed it if not), and noted the Dev Center permission scope the read needs — a missing scope produces a page that builds, mounts and shows nothing. Both in [DATA_SOURCES.md](references/dashboard-page/DATA_SOURCES.md#two-things-to-settle-before-you-write-the-page); the scope goes under [Manual Steps Required](#-manual-steps-required). **A second vertical added during Step 4b needs this check too, and its failure must not take down the page** — see [A second vertical is a second scope](references/dashboard-page/DATA_SOURCES.md#a-second-vertical-is-a-second-scope).
39
39
  - [ ] **Modelled the call on the SDK, not the REST page:** namespace name, `_id` vs `id`, no `ReturnType` on overloaded methods, no `hasNext` on `PagingMetadataV2` — see [The SDK is not the REST API](references/dashboard-page/DATA_SOURCES.md#the-sdk-is-not-the-rest-api).
40
40
  - [ ] Site/editor extensions only: kept SDK calls in the extension by default, routing out only business-wide methods a visitor genuinely cannot call (see [Identity and Elevation Requirement](#identity-and-elevation-requirement))
@@ -43,6 +43,7 @@ Helps build extensions for Wix CLI applications. Covers all extension types: das
43
43
  - [ ] **Compile as you go:** ran `npx tsc --noEmit` after the first file that imports `@wix/patterns`, not only at Step 5. Patterns' state and filter APIs are the most common source of errors, and finding twenty of them in one batch after the page is written costs far more than finding two early.
44
44
  - [ ] **🛑 Component Selection Gate (MANDATORY, dashboard UI only):** For every UI element on a Dashboard Page, resolved it against `@wix/patterns` BEFORE reaching for `@wix/design-system` — and never hand-rolled a component either library already provides. See [Component Selection Order](#component-selection-order).
45
45
  - [ ] Invoked `wix-design-system` skill ONLY before editing the first `.tsx`/`.jsx` file that imports `@wix/design-system`. Skip for backend-only or data-only extensions.
46
+ - [ ] **When rendering images, for every collection source:** followed [IMAGE_RENDERING.md](references/dashboard-page/IMAGE_RENDERING.md). Keep schema image renderers and raw form values; custom WDS/native images must normalize the actual SDK image value before choosing a fallback or empty state. SDK decoding can replace REST image objects with URI strings. Verify loaded collection thumbnails and detail previews, or report browser verification as unavailable.
46
47
  - [ ] WDS: the design-system stylesheets are imported in exactly one place per app — `BusinessManagerTheme.tsx` for a dashboard surface (see the next item), or the main component entry file for a site/editor extension. Never in child, tab or helper files, and never twice.
47
48
  - [ ] **🛑 Business Manager theme (every dashboard surface — page, modal AND plugin):** wrote `BusinessManagerTheme.tsx` once (both stylesheets, including `themes/odeditor.global.css`, plus `WixDesignSystemProvider` → `WixDesignSystemIconThemeProvider` → `IconThemeProvider theme="odeditor"` → `WixDesignSystemDefaultPropsProvider`), and wrapped **each** extension's root in it — above `WixPatternsProvider` and above `CustomModalLayout`. Every extension is a separate iframe that inherits none of the redesign, so theming the page does nothing for a modal it opens or a plugin in a slot; each one needs its own wrapper. Also: every icon from `@wix/wix-ui-icons-common/lazy`, and `--wds-*` tokens or `skin`/`size` props rather than hardcoded colours, font sizes or inline `style` ([BUSINESS_MANAGER_TOKENS.md](references/BUSINESS_MANAGER_TOKENS.md) — note the theme rebases the `SP*` spacing unit from 6px to 4px). `tsc`, `wix build` and `wix preview` all pass on an unthemed surface — only looking at it catches this. See [BUSINESS_MANAGER_THEME.md](references/BUSINESS_MANAGER_THEME.md).
48
49
  - [ ] **Step 4c (dashboard page UI only):** Re-opened and read the page file(s) just written — not recalled intent — and confirmed against the actual code: no `SummaryBar` unless the request asked for one, a routed drill-in (`navigateToEntityPage`) for every row and no `SidePanel` used as one, every declared filter name also appearing inside `fetchData`, and — for every template with a router — the entry file both passes and guards `location`. See [UX Completeness Self-Audit](#step-4c-ux-completeness-self-audit).
@@ -219,6 +220,7 @@ Use a Dashboard Modal for dialogs that neither write nor display a listed record
219
220
  | Draft template — start here for any dashboard page: finding, copying and adapting the package's page templates | [DRAFT_TEMPLATE.md](references/dashboard-page/DRAFT_TEMPLATE.md) |
220
221
  | The state object `useTableCollection()` returns | [TABLE_STATE.md](references/dashboard-page/TABLE_STATE.md) |
221
222
  | Finding the SDK method and field names behind a page | [DATA_SOURCES.md](references/dashboard-page/DATA_SOURCES.md) |
223
+ | Images from any collection source — CMS, vertical SDKs, and custom data | [IMAGE_RENDERING.md](references/dashboard-page/IMAGE_RENDERING.md) |
222
224
  | Filter paths, WQL operators and cursor paging | [QUERY_AND_PAGING.md](references/dashboard-page/QUERY_AND_PAGING.md) |
223
225
 
224
226
  ---
@@ -227,7 +229,7 @@ Use a Dashboard Modal for dialogs that neither write nor display a listed record
227
229
 
228
230
  **CRITICAL:** Data owned by an existing Wix business app is read and written through that app's SDK module — NEVER modeled as a new CMS Data Collection. A custom collection for such data starts empty and stays disconnected from the real records (e.g., a "refunds dashboard" built on CMS shows an empty state while refunded orders exist in Wix eCommerce).
229
231
 
230
- Find the entity the user mentioned in the [entity → SDK module map](references/SDK_MODULE_MAP.md) and use that package. If the entity isn't listed or you're unsure, run `SearchWixSDKDocumentation` for it — **never conclude CMS with zero MCP calls**. CMS is only for data your app itself introduces (configuration, rules, app-specific records) that no Wix app manages.
232
+ Find the entity the user mentioned in the [entity → SDK module map](references/SDK_MODULE_MAP.md) and use that package; the [SDK lookup](#sdk-lookup-one-call-for-every-vertical-entity) then names the namespace and method. If the entity isn't listed and the lookup finds nothing, run `SearchWixSDKDocumentation` for it — **never conclude CMS without one of the two**. CMS is only for data your app itself introduces (configuration, rules, app-specific records) that no Wix app manages.
231
233
 
232
234
  **SDK types:** access them through the namespace you import, as `<namespace>.<TypeName>`, using any type name shown in the docs — never import a type by name from the `@wix/<pkg>` root.
233
235
 
@@ -237,6 +239,8 @@ const rows: orders.Order[] = []; // ✅
237
239
  // import type { Order } from '@wix/ecom'; // ❌ has no exported member 'Order'
238
240
  ```
239
241
 
242
+ **A map keyed by an SDK enum:** fields are typed `<Enum>WithLiterals` (the enum or its string values). `Partial<Record<bookings.BookingStatusWithLiterals, V>>` cannot be indexed by a status (TS7053). Use `Record<…WithLiterals, V>` with an entry for every value, or key a partial map by the string values: `` Partial<Record<`${bookings.BookingStatus}`, V>> ``.
243
+
240
244
  ---
241
245
 
242
246
  ## Data Collection Inference
@@ -307,14 +311,14 @@ Who the extension runs as decides everything below — the Category column in [E
307
311
 
308
312
  **Default: call the SDK directly from the extension.** Routing a call that didn't need it is not a harmless extra hop — it is how working features break. Sort by who the call acts for, never by its scope name:
309
313
 
310
- - **Acts for the current visitor or member** — their cart, checkout, booking, order, reservation, or profile: `currentCartV2.*`, `cartV2.placeOrder`, `bookings.createBooking`, `members.getMyMember`, and anything else operating on "my" or "the current" entity. These resolve the actor from the caller's session, so elevating runs them as the app and detaches the result from the person who asked — an order with no buyer, a booking with no attendee.
314
+ - **Acts for the current visitor or member** — their cart, checkout, booking, order, reservation, or profile: `currentCartV2.*`, `cartV2.placeOrder`, `bookings.createBooking`, `members.getCurrentMember` (REST *Get My Member*), and anything else operating on "my" or "the current" entity. These resolve the actor from the caller's session, so elevating runs them as the app and detaches the result from the person who asked — an order with no buyer, a booking with no attendee.
311
315
  - **The platform filters the result by caller** — an elevated call returns what the direct call withheld, so a "fix" for a sparse result becomes a leak. Wix Data `items.*` follows the collection's `dataPermissions` (scaffolded default: `itemRead: 'ANYONE'`, writes `'PRIVILEGED'` — fix writes with permissions, not routing; see [DATA_COLLECTION.md](references/DATA_COLLECTION.md)). Catalog reads return base fields to anyone, withholding `MERCHANT_DATA` and non-visible products unless the app holds `SCOPE.STORES.PRODUCT_READ_ADMIN`. `members.getMember`/`queryMembers` withhold `PRIVATE` members from visitor and member callers.
312
316
 
313
317
  **Route out only when the method acts on the business as a whole**, which a visitor or member genuinely cannot do: `archiveLocation`, `queryLocations`, catalog and inventory writes, `bookings.confirmBooking`, order management. **When the method's docs show the call elevated, route it out and elevate there** — from any host, dashboard included, because `auth.elevate` only works in backend code, so the endpoint is the only place the documented pattern can run.
314
318
 
315
- **When you're unsure, call it directly and let it fail.** A method a site extension may not call returns a permission error you see immediately; a method wrongly routed and elevated *succeeds* and silently returns the wrong data or acts for the wrong person. Some method pages carry a prose note that settles it — `get-my-member`: "This method requires visitor or member authentication." Authoritative when present, but only a minority of pages have one, so its absence decides nothing.
319
+ **When you're unsure, call it directly and let it fail.** A method a site extension may not call returns a permission error you see immediately; a method wrongly routed and elevated *succeeds* and silently returns the wrong data or acts for the wrong person. Some method pages carry a prose note that settles it — `get-my-member`: "This method requires visitor or member authentication." Authoritative when present (the SDK lookup prints it as the method's `note`), but only a minority of pages have one, so its absence decides nothing.
316
320
 
317
- Two signals never settle it: the scope name — `locations.queryLocations` is `SCOPE.DC-MULTILOCATION.READ-LOCATIONS` yet admin-only, while `currentCartV2.addLineItemsToCurrentCart` carries `SCOPE.ECOM.MANAGE-ADMIN` yet is visitor-callable and breaks if elevated — and the SDK schema line's client prefix, which varies by docs channel for the same method, so carries nothing and isn't worth re-deriving.
321
+ Two signals never settle it: the scope name — the methods whose scope name points the wrong way are rules in [sdk-curated.json](scripts/sdk-curated.json), which the [SDK lookup](#sdk-lookup-one-call-for-every-vertical-entity) prints as `note` — and the SDK schema line's client prefix, which varies by docs channel for the same method, so carries nothing and isn't worth re-deriving.
318
322
 
319
323
  Routing out means a Backend API endpoint that elevates and is reached with `httpClient.fetchWithAuth()`. Elevation bypasses Wix's permission check, so the endpoint must re-check the caller itself — see [Identity and Authorization](references/BACKEND_API.md#identity-and-authorization) for what each host can actually verify, and why an owner-only operation belongs in a dashboard extension instead.
320
324
 
@@ -344,7 +348,7 @@ Use the Extension Types Reference Table and decision content above. State extens
344
348
 
345
349
  ### Step 3: Read Extension Reference, Check API References, Then Discover (if needed)
346
350
 
347
- **Workflow: Read extension reference → Check API references → Use MCP only for gaps.**
351
+ **Workflow: Read extension reference → Check API references → SDK lookup for vertical entities → docs only for what the lookup does not print.**
348
352
 
349
353
  1. **Read the extension reference file** for the chosen extension type from the table above
350
354
  2. **Identify required APIs** from user requirements
@@ -355,23 +359,23 @@ Use the Extension Types Reference Table and decision content above. State extens
355
359
  - Service Plugin SPIs → read `references/SERVICE_PLUGIN.md` together with the matching `references/service-plugin/<NAME>.md` leaf
356
360
  - App Tools (AI assistant tools) → read `references/APP_TOOLS.md`; it links to `references/app-tools/TOOLS.md` (declaration) and `references/service-plugin/TOOLS_PROVIDER.md` (handler)
357
361
  4. **Verify the specific method/event exists** in references
358
- 5. **ONLY use MCP discovery if NOT found** in reference files
362
+ 5. **For vertical entities, run the [SDK lookup](#sdk-lookup-one-call-for-every-vertical-entity)** once, with every entity; use MCP discovery only for what neither the references nor the lookup answer
359
363
 
360
364
  **Platform APIs (never discover - in references):**
361
365
  - Wix Data, Dashboard SDK, Event SDK (common events), Service Plugin SPIs
362
366
 
363
367
  **Vertical APIs (discover if needed):**
364
- - Wix Stores (**⚠️ MUST use Stores Versioning reference** — V1/V3 catalog check required), Wix eCommerce, Wix Bookings, Wix Members, Wix Pricing Plans, third-party integrations — find the right `@wix/*` package in the [SDK-First Rule](#sdk-first-rule-existing-wix-app-data-is-never-cms) module map first, then discover methods via MCP
368
+ - Wix Stores (**⚠️ MUST use Stores Versioning reference** — V1/V3 catalog check required), Wix eCommerce, Wix Bookings, Wix Members, Wix Pricing Plans, third-party integrations — find the right `@wix/*` package in the [SDK-First Rule](#sdk-first-rule-existing-wix-app-data-is-never-cms) module map first, install it, then get the namespace and method from the [SDK lookup](#sdk-lookup-one-call-for-every-vertical-entity)
365
369
 
366
370
  **Decision table:**
367
371
 
368
372
  | User Requirement | Check References / Discovery Needed? | Reason / Reference File |
369
373
  | ------------------------------------ | ------------------------------------ | --------------------------------------------------- |
370
- | "Display store products" | ✅ YES (MCP discovery) | Wix Stores API — **include Stores Versioning reference** |
371
- | "Dashboard for orders / refunds" | ✅ YES (MCP discovery) | Wix eCommerce API (`@wix/ecom`) — **NEVER a CMS collection** |
372
- | "Show booking calendar" | ✅ YES (MCP discovery) | Wix Bookings API not in reference files |
373
- | "Send emails to users" | ✅ YES (MCP discovery) | Wix Triggered Emails not in reference files |
374
- | "Get member info" | ✅ YES (MCP discovery) | Wix Members API not in reference files |
374
+ | "Display store products" | ✅ YES (SDK lookup) | Wix Stores API — **include Stores Versioning reference** |
375
+ | "Dashboard for orders / refunds" | ✅ YES (SDK lookup) | Wix eCommerce API (`@wix/ecom`) — **NEVER a CMS collection** |
376
+ | "Show booking calendar" | ✅ YES (SDK lookup) | Wix Bookings API (`@wix/bookings`); SPI leaves cover only service plugins |
377
+ | "Send emails to users" | ✅ YES (SDK lookup, then MCP) | Wix Triggered Emails not in reference files |
378
+ | "Get member info" | ✅ YES (SDK lookup) | Wix Members API not in reference files |
375
379
  | "Listen for cart events" | Check `COMMON-EVENTS.md` | MCP discovery only if event missing in reference |
376
380
  | "Store data in collection" | WIX_DATA.md ✅ Found | ❌ Skip discovery (covered by reference) |
377
381
  | "Create CMS collections for my app" | Data Collection reference | ❌ Skip discovery (covered by dedicated reference) |
@@ -381,7 +385,27 @@ Use the Extension Types Reference Table and decision content above. State extens
381
385
  | "Settings page with form inputs" | N/A (UI only, no external API) | ❌ Skip discovery |
382
386
  | "Dashboard page with local state" | N/A (no external API) | ❌ Skip discovery |
383
387
 
384
- **MCP Tools for discovery (when needed):**
388
+ #### SDK lookup: one call for every vertical entity
389
+
390
+ ```bash
391
+ node <this-skill-dir>/scripts/sdk-lookup.cjs contacts orders --intent search # search | read | write | event | all
392
+ ```
393
+
394
+ Run it from the app directory, after the vertical packages are installed, with **every entity the feature touches in one call**. Pick the intent from the feature, once. A dashboard collection page edits its records by default ([DRAFT_TEMPLATE.md](references/dashboard-page/DRAFT_TEMPLATE.md#2-choose-then-read-the-chosen-templates-page)), so it uses `all`: that holds the `search` and `write` lines, the search methods first. Use `search` (with a search box) or `read` only for a read-only page, and `write` for a feature that only writes. Do not pipe the output through `head`. Per entity it prints:
395
+
396
+ - the namespace to use and why (a curated rule; within one package, a `search*` method for a search, then the highest API version; across packages that export the same name, the module map's package, else the package named after it), and the other namespaces — across packages, each with its entity description, so switch when the feature matches another one;
397
+ - the import line;
398
+ - `shape`: the one call to write for the intent, with its reason and, for a search, where the term goes;
399
+ - each method for the intent, with its call shape (`search`, `query-builder`, `query`, …), permission, required fields (`revision`) and its docs notes (`note`, with an update's field rules: what a missing field does, and how to clear one); `fieldsets` when an option decides which fields come back (members default to `PUBLIC`, without `loginEmail` or `contact`: ask for the set that holds every field you show); for a search, query or list method also `arg` and `returns`, the keys of its argument (`cursorPaging`, `filter`, `sort`, `search`) and of its response (`pagingMetadata.cursors.next`); a filter list only when the package declares one (otherwise the method docs page lists the fields) — not who may call it: that stays with [Identity and Elevation Requirement](#identity-and-elevation-requirement);
400
+ - the entity type as `file:line` — the declaration to verify fields against ([DATA_SOURCES.md](references/dashboard-page/DATA_SOURCES.md#confirming-a-field--the-part-that-ships-bugs));
401
+ - each method's own declaration as `decl file:line` — read the types behind `arg` and `returns` there, not by searching the typings;
402
+ - the curated rules for the entity (`note`), such as the Stores V1/V3 check.
403
+
404
+ Take the namespace, the method and the call shape from its output; do not re-derive them from the typings, and follow the lines under `shape`. When the lookup prints `site`, the choice depends on the site (Stores: call `getCatalogVersion()` and support both). `not installed` prints the install command: install, then run the lookup again. A name it does not know exits 1 with near matches.
405
+
406
+ It prints each search and query method's closed filter list (free-text fields, operators per field, sort) from the package's own declarations. It prints a method's **permission scope ID** only when the package declares it; when the output says `scope: not in the package`, get the scope from the method's docs page (the next list).
407
+
408
+ **MCP Tools for discovery (for what the lookup does not print):**
385
409
 
386
410
  - `SearchWixSDKDocumentation` - SDK methods and APIs (**Always use maxResults: 5**)
387
411
  - `ReadFullDocsMethodSchema` - Full type schema for a specific SDK method (parameters, return type, permissions)
@@ -227,7 +227,7 @@ caller before invoking an elevated method. Use `httpClient.fetchWithAuth()` to
227
227
  send caller identity; a bare `fetch` does not supply that identity. Authentication
228
228
  alone does not grant permission to perform the operation.
229
229
 
230
- Dashboard callers are Wix users. For site/editor callers, `members.getMyMember()`
230
+ Dashboard callers are Wix users. For site/editor callers, `members.getCurrentMember()`
231
231
  identifies a logged-in member but does not prove site ownership. Owner-only
232
232
  operations belong in a dashboard extension; do not expose them to site visitors
233
233
  on the assumption that member authentication proves ownership.
@@ -19,6 +19,24 @@ Keep the Wix CLI scaffold and file roles:
19
19
 
20
20
  Supplementary files are allowed; keep scaffold roles intact.
21
21
 
22
+ ## Required Reading (blocking)
23
+
24
+ Before writing code, open and read in full every reference in the matching
25
+ row. An unopened one is a failed run. Open paths directly; never skim or
26
+ grep instead.
27
+
28
+ | Scope | Required references |
29
+ | --- | --- |
30
+ | Creating a component | [`REACT-GUIDELINES.md`](editor-react-component/REACT-GUIDELINES.md), [`COMPONENT-CONTRACT.md`](editor-react-component/COMPONENT-CONTRACT.md), [`PARTS.md`](editor-react-component/PARTS.md), [`PROPS-VS-CSS.md`](editor-react-component/PROPS-VS-CSS.md), [`CSS-GUIDELINES.md`](editor-react-component/CSS-GUIDELINES.md), [`DIRECTIONALITY.md`](editor-react-component/DIRECTIONALITY.md), [`ACCESSIBILITY.md`](editor-react-component/ACCESSIBILITY.md), [`COMPONENT-PREVIEW.md`](editor-react-component/COMPONENT-PREVIEW.md), [`EDITOR-EXTENSION-CONFIGURATION.md`](editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md), [`OVERFLOW.md`](editor-react-component/OVERFLOW.md) |
31
+ | Editing React or JSX | [`REACT-GUIDELINES.md`](editor-react-component/REACT-GUIDELINES.md), [`ACCESSIBILITY.md`](editor-react-component/ACCESSIBILITY.md) |
32
+ | Changing public contract, semantic root, or named parts | [`COMPONENT-CONTRACT.md`](editor-react-component/COMPONENT-CONTRACT.md), [`PARTS.md`](editor-react-component/PARTS.md), [`PROPS-VS-CSS.md`](editor-react-component/PROPS-VS-CSS.md) |
33
+ | Changing public data props or elected root global class | [`COMPONENT-PREVIEW.md`](editor-react-component/COMPONENT-PREVIEW.md) |
34
+ | Item array where only one body is visible | [`COMPONENT-CONTRACT.md`](editor-react-component/COMPONENT-CONTRACT.md), [`PROPS-VS-CSS.md`](editor-react-component/PROPS-VS-CSS.md), [`ACCESSIBILITY.md`](editor-react-component/ACCESSIBILITY.md), [`DESIGN-STATES.md`](editor-react-component/DESIGN-STATES.md) |
35
+ | Creating or changing CSS | [`CSS-GUIDELINES.md`](editor-react-component/CSS-GUIDELINES.md) |
36
+ | Creating or changing layout/content | [`OVERFLOW.md`](editor-react-component/OVERFLOW.md) |
37
+ | Root direction contract, direction-sensitive behavior, or `ReactNode` slot | [`DIRECTIONALITY.md`](editor-react-component/DIRECTIONALITY.md) |
38
+ | Sizing, installation, or manifest overrides | [`EDITOR-EXTENSION-CONFIGURATION.md`](editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md) |
39
+
22
40
  ## Workflow
23
41
 
24
42
  1. **Scaffold only when creating.** Run in the Wix app (`wix.config.json`).
@@ -31,9 +49,9 @@ Supplementary files are allowed; keep scaffold roles intact.
31
49
  Never rerun the scaffold for an existing component.
32
50
  Write a meaningful `description` in 1-2 plain sentences (max 300 chars): what
33
51
  the user sees, when to use it, and capabilities that affect that choice.
34
- Don't repeat the component name or add implementation details.
52
+ Don't repeat the name or add implementation details.
35
53
 
36
- 2. **Run the dependency preflight.** Check required packages:
54
+ 2. **Run the dependency preflight.**
37
55
 
38
56
  ```bash
39
57
  deps=(@wix/react-component-schema @wix/react-component-utils @wix/editor-react-types)
@@ -56,15 +74,15 @@ Supplementary files are allowed; keep scaffold roles intact.
56
74
  }
57
75
  ```
58
76
 
59
- 3. **Plan.** Identify props, root, parts, and states; read routed references.
60
- Use the scaffold and references before package declarations; probe an API
61
- only when undocumented or a typecheck fails.
77
+ 3. **Plan.** Identify props, root, parts, and states; open all required references first.
78
+ Use them and the scaffold before inspecting package declarations; inspect
79
+ only for undocumented APIs or fields, or typecheck failures. Declarations
80
+ govern API shapes; retain editor rules.
62
81
 
63
82
  4. **Implement.** Keep props, logic, and styles in their scaffolded editable
64
- files. Format edited source files with the app's configured formatter before
65
- checking formatting. Never edit or format `*.generated.ts`.
83
+ files. Format edited source files with the app's formatter. Never edit or format `*.generated.ts`.
66
84
 
67
- 5. **Run the accessibility review.** Once the JSX is complete, run from the
85
+ 5. **Run the accessibility review (mandatory).** Once the JSX is complete, run from the
68
86
  same folder (`<SKILL_ROOT>` is the directory containing the active `SKILL.md`):
69
87
 
70
88
  ```bash
@@ -88,43 +106,30 @@ Supplementary files are allowed; keep scaffold roles intact.
88
106
  ```
89
107
 
90
108
  Run `npx tsc --noEmit`, relevant tests/lint, and the accessibility review.
91
- If later edits affect a check, rerun that
92
- check. Inspect the manifest when generated; never hand-repair it. Diagnose
93
- failures with
109
+ If later edits affect a check, rerun that check. Inspect the manifest when generated; never hand-repair it.
110
+ Diagnose failures with
94
111
  [`editor-react-component/MANIFEST-ERRORS.md`](editor-react-component/MANIFEST-ERRORS.md).
95
112
 
96
113
  For creation/layout changes, complete the routed overflow resize review.
97
114
 
98
- 8. **Report.** Summarize files, checks, blockers, and checks that could not run.
115
+ 8. **Report.** Summarize files, checks, blockers, unrun checks.
116
+ List required references as read/unread; read any unread one and fix first.
99
117
 
100
118
  ## Reference Policy
101
119
 
102
- Read only matched references. Preserve unrelated behavior. `SKILL.md` routes;
103
- references are leaves.
104
-
105
- ### Required References
106
-
107
- | Scope | Required references |
108
- | --- | --- |
109
- | Creating a component | [`REACT-GUIDELINES.md`](editor-react-component/REACT-GUIDELINES.md), [`COMPONENT-CONTRACT.md`](editor-react-component/COMPONENT-CONTRACT.md), [`PARTS.md`](editor-react-component/PARTS.md), [`PROPS-VS-CSS.md`](editor-react-component/PROPS-VS-CSS.md), [`CSS-GUIDELINES.md`](editor-react-component/CSS-GUIDELINES.md), [`DIRECTIONALITY.md`](editor-react-component/DIRECTIONALITY.md), [`ACCESSIBILITY.md`](editor-react-component/ACCESSIBILITY.md), [`COMPONENT-PREVIEW.md`](editor-react-component/COMPONENT-PREVIEW.md), [`EDITOR-EXTENSION-CONFIGURATION.md`](editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md) |
110
- | Editing React or JSX | [`REACT-GUIDELINES.md`](editor-react-component/REACT-GUIDELINES.md), [`ACCESSIBILITY.md`](editor-react-component/ACCESSIBILITY.md) |
111
- | Changing public contract, semantic root, or named parts | [`COMPONENT-CONTRACT.md`](editor-react-component/COMPONENT-CONTRACT.md), [`PARTS.md`](editor-react-component/PARTS.md), [`PROPS-VS-CSS.md`](editor-react-component/PROPS-VS-CSS.md) |
112
- | Changing public data props or elected root global class | [`COMPONENT-PREVIEW.md`](editor-react-component/COMPONENT-PREVIEW.md) |
113
- | Item array where only one body is visible | [`COMPONENT-CONTRACT.md`](editor-react-component/COMPONENT-CONTRACT.md), [`PROPS-VS-CSS.md`](editor-react-component/PROPS-VS-CSS.md), [`ACCESSIBILITY.md`](editor-react-component/ACCESSIBILITY.md), [`DESIGN-STATES.md`](editor-react-component/DESIGN-STATES.md) |
114
- | Creating or changing CSS | [`CSS-GUIDELINES.md`](editor-react-component/CSS-GUIDELINES.md) |
115
- | Creating or changing layout/content | [`OVERFLOW.md`](editor-react-component/OVERFLOW.md) |
116
- | Root direction contract, direction-sensitive behavior, or `ReactNode` slot | [`DIRECTIONALITY.md`](editor-react-component/DIRECTIONALITY.md) |
117
- | Sizing, installation, or manifest overrides | [`EDITOR-EXTENSION-CONFIGURATION.md`](editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md) |
120
+ Read every required reference for the matched scope, optional ones only on
121
+ trigger. Preserve unrelated behavior. References are leaves.
118
122
 
119
123
  ### Optional References
120
124
 
121
125
  | Trigger | Read |
122
126
  | --- | --- |
123
- | Interactive/selectable part, custom state, or open/collapse toggle | [`DESIGN-STATES.md`](editor-react-component/DESIGN-STATES.md) |
127
+ | Interactive/selectable part, custom state, or open/reveal toggle | [`DESIGN-STATES.md`](editor-react-component/DESIGN-STATES.md) |
128
+ | Disabled or invalid state | [`DISABLED-INVALID.md`](editor-react-component/DISABLED-INVALID.md) |
124
129
  | Creating interactive components or changing interactions/callbacks | [`FUNCTION-HANDLERS.md`](editor-react-component/FUNCTION-HANDLERS.md) |
125
130
  | Browser APIs, effects, or time-dependent output | [`SSR.md`](editor-react-component/SSR.md) |
126
131
  | Non-established CSS feature or DOM API, or user asks for one by name | [`BROWSER-SUPPORT.md`](editor-react-component/BROWSER-SUPPORT.md) |
127
- | `npx wix build` or manifest generation exits with an error | [`MANIFEST-ERRORS.md`](editor-react-component/MANIFEST-ERRORS.md) |
132
+ | `npx wix build` or manifest generation errors or warns | [`MANIFEST-ERRORS.md`](editor-react-component/MANIFEST-ERRORS.md) |
128
133
  | Animation, video, carousel, or other playable/looped/autoplaying content | [`ANIMATED-COMPONENTS.md`](editor-react-component/ANIMATED-COMPONENTS.md), [`COMPONENT-PREVIEW.md`](editor-react-component/COMPONENT-PREVIEW.md) |
129
134
  | Site/runtime/editor context hooks needed | [`SITE-CONTEXT-HOOKS.md`](editor-react-component/SITE-CONTEXT-HOOKS.md) (+ [`COMPONENT-PREVIEW.md`](editor-react-component/COMPONENT-PREVIEW.md) when design-mode behavior differs) |
130
135
  | Branded, themed, or brand-aware component requested | [`BRANDED-COMPONENTS.md`](editor-react-component/BRANDED-COMPONENTS.md) |
@@ -136,27 +141,24 @@ references are leaves.
136
141
  - Elected root: `dir={direction}`, fallback-direction class, logical CSS for
137
142
  direction-sensitive layout.
138
143
  - Deterministic render; no browser globals during render.
139
- - Explicit foreground colors need a known contrasting background; transparent
140
- roots inherit from the host.
141
- - Baseline Widely Available CSS/DOM only, or supported fallbacks.
144
+ - Baseline Widely Available CSS/DOM only, or fallbacks.
142
145
  - Accessibility per part, per [`ACCESSIBILITY.md`](editor-react-component/ACCESSIBILITY.md):
143
146
  read only `a11y.ariaLabel`, and only for a control without a visible name;
144
147
  never spread the `a11y` object or add one-off ARIA props.
145
148
  - Named parts: global class, module class, and `elementProps` (root uses
146
149
  top-level props).
147
- - Native design states: pair selectors with injected modifiers; keep non-input
148
- `:focus-visible` standalone unless editable focus is requested; toggle custom
149
- state classes from data, each with a matching `:global()` rule.
150
- - Open/collapse components: expose a props-only `isOpen: ElementState<boolean>`
151
- root state and sync internal state from it.
150
+ - Every visible text: a text prop plus a named part; no JSX text literals.
151
+ - Native design states: interactive elements only, never a non-interactive root
152
+ or part; pair selectors with injected modifiers; toggle custom state classes
153
+ from data, each with a matching `:global()` rule.
154
+ - Open/close/reveal: props-only root
155
+ `isOpen: ElementState<boolean>` synced to state; module classes, no `--open` class.
152
156
  - Single-visible-body arrays: `name` per item, `ActiveItemIndex<'prop'>`, render
153
157
  all bodies, hide inactive accessibly.
158
+ - No arrays inside array items; keep group fields flat (no object props).
154
159
  - Autoplay/loop: play/pause control, honor reduced motion, suppress autoplay in
155
160
  editor design mode.
156
- - Resizable layout: keep required content usable at 320px. Reflow visible
157
- groups inside their page and cap track minima with
158
- `minmax(min(100%, <minimum>), 1fr)`. Follow [`OVERFLOW.md`](editor-react-component/OVERFLOW.md).
159
- - Preview composition, inline or through variables:
160
- `withDefaults(withFallbackPlaceholder(PreviewOrComponent, options), defaultProps)`.
161
- Keep `withDefaults` outermost; use one crucial data field and match the root
162
- class.
161
+ - Resizable layout: keep required content usable at 320px, per
162
+ [`OVERFLOW.md`](editor-react-component/OVERFLOW.md).
163
+ - Preview: `withDefaults` outermost, one crucial data field, matching root
164
+ class, per [`COMPONENT-PREVIEW.md`](editor-react-component/COMPONENT-PREVIEW.md).
@@ -43,4 +43,4 @@ Data owned by an existing Wix business app is read and written through that app'
43
43
 
44
44
  Types from these packages are accessed as `<namespace>.<TypeName>` — see [SDK types](../SKILL.md#sdk-first-rule-existing-wix-app-data-is-never-cms).
45
45
 
46
- If the entity isn't listed or you're unsure, run `SearchWixSDKDocumentation` for it — **never conclude CMS with zero MCP calls**. CMS is only for data your app itself introduces (configuration, rules, app-specific records) that no Wix app manages.
46
+ This map names the package, never the namespace or the method: install the package, then run the [SDK lookup](../SKILL.md#sdk-lookup-one-call-for-every-vertical-entity) for the namespace and method. If the entity isn't listed and the lookup finds nothing, run `SearchWixSDKDocumentation` for it — **never conclude CMS without one of the two**. CMS is only for data your app itself introduces (configuration, rules, app-specific records) that no Wix app manages.
@@ -101,13 +101,35 @@ For the full table see the [Catalog V1 to V3 Migration Guide](https://dev.wix.co
101
101
  | `manageVariants: false` (customizations) | `modifiers[i]` |
102
102
  | `collectionIds[i]` | `directCategories[i].id` |
103
103
  | `ribbon`, `brand` (string) | `ribbon.name`, `brand.name` (managed via `ribbonsV3` / `brandsV3`) |
104
- | `media.mainMedia.image.url` (main image URL) | `media.main.image ?? media.main.url` — in V3, `ProductMedia.image` is a `string` (Wix-hosted URL), `url` is a `string` (external URL); check both |
104
+ | `media.mainMedia.image.url` (main image URL) | `media.main.image` can be a `wix:image://` URI. Use `media.main.url` only for image media; it can otherwise describe a video. See [Image rendering](dashboard-page/IMAGE_RENDERING.md) for browser URL conversion. |
105
105
  | `lastUpdated` | `updatedDate` |
106
106
 
107
107
  **Pricing model** — V1 had a `discount` object; V3 removed it. Discounts are now expressed by the relationship between two fields on the variant: `actualPrice` (required, what the customer pays) vs `compareAtPrice` (optional, original price shown struck through). With discount: V1 `price`/`discountedPrice` → V3 `compareAtPrice`/`actualPrice`. Without discount: V1 `price` → V3 `actualPrice`, leave `compareAtPrice` empty.
108
108
 
109
109
  ---
110
110
 
111
+ ## Display SDK product images
112
+
113
+ In the V3 SDK, `media.main.image` is a **string**, including Wix image URIs. The raw REST
114
+ response can show an image object instead: `media.main.image.url` from that response is not
115
+ the SDK access path. Pass the whole SDK image value to `toBrowserImageUrl` from
116
+ [IMAGE_RENDERING.md](dashboard-page/IMAGE_RENDERING.md), then choose a fallback:
117
+
118
+ ```typescript
119
+ import { productsV3 } from '@wix/stores';
120
+
121
+ export function productImageUrl(product: productsV3.V3Product): string | undefined {
122
+ const main = product.media?.main;
123
+ return toBrowserImageUrl(main?.image)
124
+ || (main?.mediaType === 'IMAGE' ? toBrowserImageUrl(main.url) : undefined)
125
+ || toBrowserImageUrl(main?.thumbnail?.url);
126
+ }
127
+ ```
128
+
129
+ Use this mapping in both views. Collection thumbnails may prefer normalized `main.thumbnail.url`.
130
+ A video's thumbnail is an image; its own `url` is not. Request
131
+ `'THUMBNAIL'` in **both** list and detail calls; it is not returned by default.
132
+
111
133
  ## Webhooks
112
134
 
113
135
  **Subscribe to BOTH V1 and V3 webhooks** so your app handles every site.
@@ -130,4 +152,4 @@ Payload changes: V1 `changedFields` → V3 `modifiedFields`. Top-level `entityId
130
152
  - [stores/INVENTORY.md](stores/INVENTORY.md) — inventory read and write operations
131
153
  - [stores/CATEGORIES.md](stores/CATEGORIES.md) — collections (V1) ↔ categories (V3)
132
154
 
133
- For methods not listed here, use `SearchWixSDKDocumentation` then `ReadFullDocsMethodSchema` (use `ReadFullDocsArticle` only for prose). Always return the required permission scopes to the user.
155
+ For methods not listed here, run the [SDK lookup](../SKILL.md#sdk-lookup-one-call-for-every-vertical-entity) for `products` (it prints both namespaces and their methods), then `ReadFullDocsMethodSchema` for its permission scope (and the filter list if the lookup printed none). Always return the required permission scopes to the user.
@@ -1,8 +1,9 @@
1
1
  # Finding the real SDK shape behind a dashboard page
2
2
 
3
3
  > **Scope.** [DRAFT_TEMPLATE.md](DRAFT_TEMPLATE.md) gives you the page; this file finds the method
4
- > and *field names* for its data. Read it before Step 3's MCP discovery. The installed package is
5
- > the version your code compiles against.
4
+ > and *field names* for its data. The [SDK lookup](../../SKILL.md#sdk-lookup-one-call-for-every-vertical-entity)
5
+ > gives the namespace, the method and the entity's `file:line`; this file checks the fields there.
6
+ > The installed package is the version your code compiles against.
6
7
 
7
8
  ## Where the types actually live
8
9
 
@@ -18,12 +19,10 @@ node_modules/@wix/auto_sdk_ecom_orders/build/es/
18
19
  ecom-v1-order-orders.universal-<hash>.d.mts # the domain entities
19
20
  ```
20
21
 
21
- Three consequences worth knowing before you start grepping:
22
+ Three consequences:
22
23
 
23
- 1. **The directory name is not the namespace name.** Namespaces are camelCase, package directories
24
- are kebab-case — `extendedBookings` lives in `auto_sdk_bookings_extended-bookings`, not
25
- `auto_sdk_bookings_extendedBookings`. Don't derive one from the other; list them:
26
- `ls node_modules/@wix | grep <vertical>`.
24
+ 1. **The directory name is not the namespace name.** `extendedBookings` lives in
25
+ `auto_sdk_bookings_extended-bookings`. Don't derive one from the other; the SDK lookup maps them.
27
26
  2. **The entity is not always in `index.typings.d.mts`.** `Order`, `Refund`, `Service` live in the
28
27
  hashed `*.universal-*.d.mts` when the package has one. The hash changes between versions, so glob
29
28
  for it, never hard-code it, and fall back to `index.typings.d.mts` when no universal file exists.
@@ -34,12 +33,8 @@ Three consequences worth knowing before you start grepping:
34
33
 
35
34
  ## Confirming a method
36
35
 
37
- ```bash
38
- E=node_modules/@wix/auto_sdk_ecom_order-transactions/build/es
39
- grep -oE "^declare function [a-zA-Z]+" $E/index.d.mts
40
- ```
41
-
42
- Prefer this to recall: `listTransactionsForMultipleOrders(orderIds: string[])` and
36
+ The SDK lookup lists every method of the namespace (`other methods:` outside the intent). Prefer
37
+ its list to recall: `listTransactionsForMultipleOrders(orderIds: string[])` and
43
38
  `listTransactionsForSingleOrder` differ by exactly the shape a collection page needs, and only one
44
39
  of them avoids an N+1 across the visible page.
45
40
 
@@ -50,6 +45,7 @@ the uncertain ones, **in one pass**. List the types and fields first, then print
50
45
  per file. A grep per question is a round trip each:
51
46
 
52
47
  ```bash
48
+ E=node_modules/@wix/auto_sdk_ecom_order-transactions/build/es
53
49
  awk '/^(interface|type) (Payment|RegularPaymentDetails)[ <{=]/,/^}/' $E/index.typings.d.mts
54
50
  ```
55
51
 
@@ -0,0 +1,61 @@
1
+ # Images in collection and detail pages
2
+
3
+ This applies to every data source: CMS, Stores, Bookings, and other SDK or custom collections.
4
+ An image value is not necessarily a browser URL. A `wix:image://` URI passed directly to WDS
5
+ `Image` or a native `<img>` produces a broken image even when the page builds and its data loads.
6
+
7
+ ## Use the field renderer when the schema supplies one
8
+
9
+ Keep the source's image field type and original value when using schema-driven Patterns
10
+ collections or entity fields. Their image renderers handle the supported URI and structured
11
+ image formats. Do not replace them with a custom WDS renderer just to show an image.
12
+
13
+ ## Custom image rendering
14
+
15
+ Read the source's image field declaration before mapping it. Select the image value, not the
16
+ whole media container: a media item can also be a video or document. Check its media type before
17
+ using a generic `url` as an image, or use its documented image thumbnail field.
18
+
19
+ Use the installed SDK's return type, not the raw REST response shape. SDK decoding can turn a
20
+ REST image object into a `wix:image://` string. Reading `.url` from that string returns
21
+ `undefined`, so the page shows its empty state without ever rendering an image. Do not copy
22
+ REST field access into an SDK mapper or hide this mismatch with a type assertion.
23
+
24
+ For custom WDS or native image rendering, extract a string from the image value and convert Wix
25
+ URIs with the documented SDK helper. Preserve ordinary HTTP(S) URLs and missing values:
26
+
27
+ ```typescript
28
+ import { media } from '@wix/sdk';
29
+
30
+ type ImageValue = string | { uri?: string; url?: string } | null | undefined;
31
+
32
+ export function toBrowserImageUrl(value: ImageValue): string | undefined {
33
+ const source = typeof value === 'string' ? value : value?.uri || value?.url;
34
+ return source?.startsWith('wix:image://')
35
+ ? media.getImageUrl(source).url
36
+ : source;
37
+ }
38
+ ```
39
+
40
+ This accepts image URI strings and structured image values with `uri` or `url`. Extract nested
41
+ image fields according to their own types before calling it. Do not stringify a media object,
42
+ hand-build a CDN URL, or send a video URI to an image renderer.
43
+
44
+ Use the derived URL in collection thumbnails, grid cards, and detail previews. Show an empty
45
+ state when it is absent. Keep it separate from the original entity and form value: saves must
46
+ retain the source's image format, alt text, dimensions, and other metadata.
47
+
48
+ Normalize the source image value before choosing a fallback or an empty state, in both the
49
+ list and the detail fetch paths. A working thumbnail does not establish that the detail query
50
+ returns the same fields. Request any fields required by the fallback too. Stores' mapping is
51
+ shown in [STORES_VERSIONING.md](../STORES_VERSIONING.md#display-sdk-product-images).
52
+
53
+ Verify a Wix-hosted image in both the collection and detail views, an external image URL, and
54
+ an item without an image. When browser access is available, open a row and check that its image
55
+ actually loads (`complete` and `naturalWidth > 0`), rather than only checking that an `<img>`
56
+ exists. If a known image shows an empty state, trace the SDK value through its mapper before
57
+ reporting completion. A successful build or a raw REST response does not verify the rendered
58
+ SDK result. If browser access is unavailable, report image rendering as unverified.
59
+
60
+ See [Work with Wix Media](https://dev.wix.com/docs/api-reference/articles/sdk-setup-and-usage/work-with-wix-media)
61
+ for the SDK URI format and conversion API.