Skills
Skill 1 of 67
Build and review Wix CLI app extensions — dashboard pages, modals, plugins, menu plugins, custom element widgets, Editor React components, site plugins, embedded scripts, context…
27 minutes · 5,887 words · 28 sections
Install
npx skills add wix/skills --skill wix-appnpx skills add wix/skills/plugin marketplace add wix/skillsThe first command installs just this skill, by the name in its SKILL.md; the second installs the whole repository.
Helps build extensions for Wix CLI applications. Covers all extension types: dashboard pages, modals, plugins, menu plugins, custom element widgets, Editor React components, site plugins, embedded scripts, context providers, function libraries, backend APIs, events, service plugins, and data collections.
Scaffolding is owned by the Wix CLI. Use wix generate --params for every supported type. It generates files and, where applicable, builder boilerplate, UUIDs, and src/extensions.ts registration. HTTP endpoints are discovered from files and need no registration. This skill provides the decision logic, API guidance, configuration semantics, and business-logic patterns that fill in the generated stubs.
Before reporting completion to the user, ALL boxes MUST be checked:
Not done: Dashboard page UI: Translated the prompt into a workflow before choosing components — what the user must understand, focus on, investigate, act on, and see confirmed. See UX Success Model (opens in a new tab), and the installed package’s own Collection Toolkit.md guide for which component serves each need (The Discovery Chain (opens in a new tab)).
SummaryBar unless the request asked for one — a named total, count, or “how many / how much” figure in the prompt. Not “the page seems like it wants one”: an uninvited bar pushes the rows down and puts a number on screen nobody asked to be right about. When the request did ask, the number has to come from something that counts (QUERY_AND_PAGING.md (opens in a new tab)) and be read through useSelector, because the state is MobX (TABLE_STATE.md (opens in a new tab)).navigateToEntityPage to an EntityPage with a working form and save, for CMS and vertical SDK data alike; the three read-only cases are in DRAFT_TEMPLATE.md (opens in a new tab). Unless the prompt is explicitly a report or an export. Never a SidePanel: in Cairo that hosts a page’s own panels.filters and read inside fetchData. Filter UI that never narrows the rows is a defect that looks like a feature.A filtered table with no drill-in and no working filters is what gets built when nobody states the requirement — the most common way a generated dashboard disappoints. The aggregate is the judgment call; the drill-in and the filters are not.
Not done: 🛑 Template-First Gate (MANDATORY, dashboard UI only, comes before writing any shell/provider/router): Followed DRAFT_TEMPLATE.md (opens in a new tab): found the page templates the installed @wix/patterns ships, chose one with its Page Templates.md guide — which pages the workflow above needs, and where the rows come from (your own fetch, or a CMS collection) — read that template’s page, and copied every file --templates lists for it. Composing the page shell, provider nesting, or router wiring from scratch when a template already shows it is the failure mode this gate exists to prevent — the Patterns/Component Docs gates below are for what the template doesn’t cover, not a replacement for starting there. The reverse holds too: a template replaces composing the shell, never the discovery chain, so every symbol it doesn’t show still goes through the next gate.
Not done: 🛑 Patterns Docs Gate (MANDATORY for any dashboard page UI): Read WIX_PATTERNS_DOCS.md (opens in a new tab) before the first command that touches node_modules/@wix/patterns — its discovery chain (pkg-root.cjs, the index, Composition and Providers.md once, Collection Toolkit.md for which component serves a need) lives only in that file, and this line is a summary of its step 1, not a substitute for opening it. Then resolve every patterns name you plan to write in one node <pkgRoot>/bin/patterns-lookup.cjs <name…> call: per name, it prints the import, the examples and the one props file. Upgrade @wix/patterns if dist/docs/index.json is missing. Patterns API facts come only from the published dist/docs/ (pages), dist/examples/ (worked calls), dist/dts-bundle/ (types) and dist/templates/ (whole pages) trees — never from src/, dist/esm/, dist/types/, or any other path inside the package. A prop a bundle has stubbed is in the file its stub names (Reading the Doc Indices.md).
Not done: 🛑 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. Procedure: COMPONENT_SELECTION.md (opens in a new tab). Resolve every patterns name in one node <pkgRoot>/bin/patterns-lookup.cjs <name…> call, not one probe per name. 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.
For the object useTableCollection() returns, read TABLE_STATE.md (opens in a new tab) — a state object you receive rather than construct, whose members are unobvious and several plausible ones absent.
sdk-lookup.cjs call (SDK lookup); used the docs only for what it does not print
type … file:line) — see DATA_SOURCES.md (opens in a new tab), and QUERY_AND_PAGING.md (opens in a new tab) before writing fetchData. A field marked @deprecated still compiles and renders something plausible and wrong.@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 (opens in a new tab); the scope goes under 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 (opens in a new tab)._id vs id, no ReturnType on overloaded methods, no hasNext on PagingMetadataV2 — see The SDK is not the REST API (opens in a new tab).wix generate --paramsname and aiContext each scaffolded builder declares — see EXTENSION_METADATA.md (opens in a new tab).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.@wix/patterns BEFORE reaching for @wix/design-system — and never hand-rolled a component either library already provides. See Component Selection Order.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.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.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. Any extension that renders WixPatternsProvider also gets BusinessManagerPatternsTheme.tsx, written once per app, nested directly inside the theme wrapper and above WixPatternsProvider. Patterns switches its own Harmony layout on the bmHarmonyTheme experiment, which never reaches the iframe. Without the second wrapper, the toolbar keeps an outlined Filter button and a pill search on an otherwise themed page (BUSINESS_MANAGER_PATTERNS.md (opens in a new tab)). 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 (opens in a new tab) — 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 (opens in a new tab).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.🛑 STOP: If any box is unchecked, do NOT proceed to the next step.
What are you trying to build?
Who will see it?
Where will it appear?
@wix/patterns + @wix/design-system (see Component Selection Order). Cannot use <Modal /> — use a separate Dashboard Modal extension and dashboard.openModal() instead.APP_TOOLS declaration + TOOLS_PROVIDER_CONFIG handler — see APP_TOOLS.md (opens in a new tab))Dashboard UI comes from two libraries, resolved in this order. Read COMPONENT_SELECTION.md (opens in a new tab) before choosing any component.
@wix/patterns: the page shell and everything collection-shaped (tables, filters, search, row and bulk actions, overlays, the page for one item). Look it up with patterns-lookup.cjs (WIX_PATTERNS_DOCS.md (opens in a new tab)); never assemble it from WDS parts.@wix/design-system: leaf-level UI patterns does not own (inputs, buttons, form fields, text, layout, cards, badges, tooltips, toasts, icons). Use the wix-design-system skill; only if it is missing, read the installed package’s types and name the file.Never skip a step, and never decide a component is missing from memory: check. Skipping to step 2 because a lookup was inconvenient is the most common way a dashboard page ends up all-WDS.
Overlaps: in a patterns page, patterns’ header and container win over WDS’s. PickerModal, usePickerModal and bulkActionModal are patterns overlays, not WDS modals. Dashboard Plugins render outside a patterns shell, so WDS is the default there; patterns collection components still apply if the surface displays a data collection.
Opening a listed record, and any create or edit form for one (even a single field), is an editable EntityPage, not a Dashboard Modal or SidePanel; “I built the list without @wix/patterns“ is no exception. A page that lists nothing (settings, config) has no EntityPage obligation. A Dashboard Modal is only for dialogs that neither write nor display a listed record. On the create route, omit entity and read the Create route section of <pkgRoot>/dist/docs/useEntityPage.md. Full flow: COMPONENT_SELECTION.md (opens in a new tab).
| Extension Type | Category | extensionType (for wix generate --params) | Reference File |
|---|---|---|---|
| Dashboard Page | Dashboard | DASHBOARD_PAGE | DASHBOARD_PAGE.md (opens in a new tab) |
| Dashboard Modal | Dashboard | DASHBOARD_MODAL | DASHBOARD_MODAL.md (opens in a new tab) |
| Dashboard Plugin | Dashboard | DASHBOARD_PLUGIN | DASHBOARD_PLUGIN.md (opens in a new tab) |
| Dashboard Menu Plugin | Dashboard | DASHBOARD_MENU_PLUGIN | DASHBOARD_MENU_PLUGIN.md (opens in a new tab) |
| Service Plugin | Backend | SERVICE_PLUGIN | SERVICE_PLUGIN.md (opens in a new tab) |
| App Tools (AI assistant tools) | Backend | APP_TOOLS, then SERVICE_PLUGIN with pluginType: TOOLS_PROVIDER_CONFIG | APP_TOOLS.md (opens in a new tab) |
| Backend Event Extension | Backend | EVENT | BACKEND_EVENT.md (opens in a new tab) |
| Backend API (HTTP endpoint) | Backend | HTTP_ENDPOINT | BACKEND_API.md (opens in a new tab) |
| Data Collection | Backend | DATA_COLLECTION | DATA_COLLECTION.md (opens in a new tab) |
| Editor React component | Site | EDITOR_REACT_COMPONENT | EDITOR_REACT_COMPONENT.md (opens in a new tab) |
| Custom element widget | Site | CUSTOM_ELEMENT | CUSTOM_ELEMENT_WIDGET.md (opens in a new tab) |
| Site Plugin | Site | SITE_PLUGIN | SITE_PLUGIN.md (opens in a new tab) |
| Embedded Script | Site | EMBEDDED_SCRIPT | EMBEDDED_SCRIPT.md (opens in a new tab) |
| Context Provider | Site | CONTEXT_PROVIDER | CONTEXT_PROVIDER.md (opens in a new tab) |
| Function Library | Site | FUNCTION_LIBRARY | FUNCTION_LIBRARY.md (opens in a new tab) |
| Page onLoad (a context provider with no API) | Site | CONTEXT_PROVIDER, named Page On Load <Task Name> | PAGE_ON_LOAD.md (opens in a new tab) |
| Lightbox (popup) open, close and data | Site | rules added to the extension that renders on the site | LIGHTBOX.md (opens in a new tab) |
Key constraints:
<Modal />; use a separate Dashboard Modal and dashboard.openModal().HTTP endpoints: use
extensionType: "HTTP_ENDPOINT"(notBACKEND_API); directories, handler types and frontend URLs are in BACKEND_API.md (opens in a new tab).
| Topic | Reference |
|---|---|
| Code Quality Requirements (applies to all generated code) | CODE_QUALITY.md (opens in a new tab) |
| Extension Registration | EXTENSION_REGISTRATION.md (opens in a new tab) |
Extension metadata — the name and aiContext to add to each scaffolded builder | EXTENSION_METADATA.md (opens in a new tab) |
| App Validation | APP_VALIDATION.md (opens in a new tab) |
| App Market Review | APP_MARKET_REVIEW.md (opens in a new tab) |
| App Identifiers (Namespace, Code ID) | APP_IDENTIFIERS.md (opens in a new tab) |
| Wix Stores Versioning (V1/V3), including product media writes | STORES_VERSIONING.md (opens in a new tab) |
| Official Documentation Links | DOCUMENTATION.md (opens in a new tab) |
| Wix Patterns Dashboard Pages | WIX_PATTERNS_DOCS.md (opens in a new tab) |
| Business Manager theme — the wrapper every dashboard page, modal and plugin needs | BUSINESS_MANAGER_THEME.md (opens in a new tab) |
Business Manager tokens — --wds-* replacements, the rebased spacing unit, per-component adjustments | BUSINESS_MANAGER_TOKENS.md (opens in a new tab) |
Business Manager theme for @wix/patterns — the second wrapper that turns on the patterns shell’s Harmony layout | BUSINESS_MANAGER_PATTERNS.md (opens in a new tab) |
| Dashboard UX Success Model (what a good dashboard contains) | UX_SUCCESS_MODEL.md (opens in a new tab) |
| Draft template — start here for any dashboard page: finding, copying and adapting the package’s page templates | DRAFT_TEMPLATE.md (opens in a new tab) |
The state object useTableCollection() returns | TABLE_STATE.md (opens in a new tab) |
| Finding the SDK method and field names behind a page | DATA_SOURCES.md (opens in a new tab) |
| Display images from CMS, vertical SDKs, and custom collections | IMAGE_RENDERING.md (opens in a new tab) |
| Edit entity images with Media Manager; draft, Save/Cancel, and picker verification | IMAGE_EDITING.md (opens in a new tab) |
| Filter paths, WQL operators and cursor paging | QUERY_AND_PAGING.md (opens in a new tab) |
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).
Find the entity the user mentioned in the entity → SDK module map (opens in a new tab) and use that package; the SDK lookup 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.
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.
import { orders } from '@wix/ecom';
const rows: orders.Order[] = []; // ✅
// import type { Order } from '@wix/ecom'; // ❌ has no exported member 'Order'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>>.
CRITICAL: Data collections are often needed implicitly — don’t wait for the user to explicitly say “create a CMS collection.” Infer the need automatically.
⚠️ Apply the SDK-First Rule first — the indicators below only apply to data your app itself owns, not to entities a Wix app already manages.
Skip this section if the user provides a collection ID directly (e.g., an existing site-level collection). In that case, use the provided ID as-is — no Data Collection extension or namespace scoping needed.
Always include a Data Collection extension when ANY of these are true:
| Indicator | Example |
|---|---|
| User mentions saving/storing/persisting app-specific data | “save the fee amount”, “store product recommendations” |
| A dashboard page will manage (CRUD) domain entities | “dashboard to manage fees”, “admin page to edit rules” |
| A service plugin reads app-configured data at runtime | “fetch fee rules at checkout”, “look up shipping rates” |
| User mentions “dedicated database/collection” | “save in a dedicated database collection” |
| Multiple extensions reference the same custom data | Dashboard manages fees + service plugin reads fees |
Why this matters: Without the Data Collection extension, the collection won’t be created when the app is installed, the Wix Data APIs may not work (code editor not enabled), and collection IDs won’t be properly scoped to the app namespace.
If data collection is inferred, follow the App Namespace Requirement to obtain the namespace before proceeding.
When creating a Data Collection, you MUST ask the user for their app namespace from Wix Dev Center. This is a required parameter that must be obtained from the user’s Dev Center dashboard and cannot be recommended or guessed.
If the user hasn’t provided their app namespace, read APP_IDENTIFIERS.md (opens in a new tab) and give the user the instructions to obtain it.
Applies ONLY when a Data Collection extension is being created. If the user provides a collection ID directly, use it as-is — no namespace scoping, no Data Collection extension needed.
When a Data Collection is created alongside other extensions that reference the same collections:
idSuffix for each collection (the Data Collection reference documents the full ID format)<app-namespace>/<idSuffix>) in all extensions that reference the collection via Wix Data API callsApplies when ANY Wix Stores API is used (products, inventory, orders, etc.):
getCatalogVersion()productsV3 (V3) vs products (V1)This is non-negotiable — V1 and V3 are NOT backwards compatible.
Applies whenever an extension calls a Wix SDK method. Decide where the call runs before writing it.
Who the extension runs as decides everything below — the Category column in Extension Types Reference Table tells you which one you have:
auth.elevate works only in backend code. In a site, editor, or dashboard extension it doesn’t work at all.
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:
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.items.* follows the collection’s dataPermissions (scaffolded default: itemRead: 'ANYONE', writes 'PRIVILEGED' — fix writes with permissions, not routing; see DATA_COLLECTION.md (opens in a new tab)). 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.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.
When you’re unsure in a site, editor, or dashboard extension, 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.
Two signals never settle it: the scope name — the methods whose scope name points the wrong way are rules in sdk-curated.json (opens in a new tab), which the SDK lookup 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.
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 (opens in a new tab) for what each host can actually verify, and why an owner-only operation belongs in a dashboard extension instead.
Some extensions or SDK calls require a permission scope that wix generate doesn’t add automatically. Adding one is a Dev Center account change, not something the agent does — tell the user which scope to add: open their app at https://manage.wix.com/apps/<appId>/home, select Develop > Permissions in the left menu, then Add Permissions, then report it under Manual Steps Required. If the app is already installed on a site, the owner must also re-approve it via the install/update flow — revisit that same app page’s “Test App” flow (or the release output’s install links) and accept “Agree & Update” — before the scope takes effect there.
Applies when a user wants to submit their app to the Wix App Market, list it publicly, prepare for App Market review, audit decline risk, or fix App Market review feedback. Not needed for private apps or routine version releases.
Read APP_MARKET_REVIEW.md (opens in a new tab) — it contains the full technical checklist, implementation notes with Wix doc links, and the review taxonomy IDs for traceability.
Only ask for configuration values when absolutely necessary for the implementation to proceed. If a value can be configured later or added as a manual step, don’t block on it.
If unclear on approach (placement, visibility, configuration, integration), ask clarifying questions. If the answer could change the extension type, wait for the response before proceeding. Otherwise, proceed with the best-fit extension type.
Use the Extension Types Reference Table and decision content above. State extension type and brief reasoning (placement, functionality, integration).
Workflow: Read extension reference → Check API references → SDK lookup for vertical entities → docs only for what the lookup does not print.
references/backend-event/COMMON-EVENTS.mdreferences/data-collection/WIX_DATA.mdreferences/dashboard-page/DASHBOARD_API.md; Media Manager → references/dashboard-page/DASHBOARD_API_MEDIA_AND_PLUGINS.mdreferences/SERVICE_PLUGIN.md, then the SPI file its References table linksreferences/APP_TOOLS.md; it links to references/app-tools/TOOLS.md (declaration) and references/service-plugin/TOOLS_PROVIDER.md (handler)Platform APIs (never discover - in references):
Vertical APIs (discover if needed):
@wix/* package in the SDK-First Rule module map first, install it, then get the namespace and method from the SDK lookupDecision table:
| User Requirement | Check References / Discovery Needed? | Reason / Reference File |
|---|---|---|
| “Display store products” | ✅ YES (SDK lookup) | Wix Stores API — include Stores Versioning reference |
| “Dashboard for orders / refunds” | ✅ YES (SDK lookup) | Wix eCommerce API (@wix/ecom) — NEVER a CMS collection |
| “Show booking calendar” | ✅ YES (SDK lookup) | Wix Bookings API (@wix/bookings); SPI leaves cover only service plugins |
| “Send emails to users” | ✅ YES (SDK lookup, then MCP) | Wix Triggered Emails not in reference files |
| “Get member info” | ✅ YES (SDK lookup) | Wix Members API not in reference files |
| “Listen for cart events” | Check COMMON-EVENTS.md | MCP discovery only if event missing in reference |
| “Store data in collection” | WIX_DATA.md ✅ Found | ❌ Skip discovery (covered by reference) |
| “Create CMS collections for my app” | Data Collection reference | ❌ Skip discovery (covered by dedicated reference) |
| “Show dashboard toast” | DASHBOARD_API.md ✅ Found | ❌ Skip discovery |
| “Show toast / navigate” | DASHBOARD_API.md ✅ Found | ❌ Skip discovery |
| “UI only (forms, inputs)” | N/A (no external API) | ❌ Skip discovery |
| “Settings page with form inputs” | N/A (UI only, no external API) | ❌ Skip discovery |
| “Dashboard page with local state” | N/A (no external API) | ❌ Skip discovery |
node <this-skill-dir>/scripts/sdk-lookup.cjs contacts orders --intent search # search | read | write | event | allRun 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 (opens in a new tab)), 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:
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;shape: the one call to write for the intent, with its reason and, for a search, where the term goes;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); limits, the size and range caps its request declares (orderIds 1–100 items, limit() ≤1000): keep a page limit within the cap of a batch method it feeds; 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;file:line — the declaration to verify fields against (DATA_SOURCES.md (opens in a new tab));decl file:line — read the types behind arg and returns there, not by searching the typings;note), such as the Stores V1/V3 check.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.
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).
MCP Tools for discovery (for what the lookup does not print):
SearchWixSDKDocumentation - SDK methods and APIs (Always use maxResults: 5)ReadFullDocsMethodSchema - Full type schema for a specific SDK method (parameters, return type, permissions)ReadFullDocsArticle - Prose guides and conceptual articles only (not for SDK method signatures)For each supported type, including HTTP endpoints, run npx wix generate --params '<json>'. The command returns {"success":true,"extensionType":"...","newFiles":[...]} on success.
If the command fails because of unknown or invalid params, run npx wix schema generate --type <extensionType> to print the JSON Schema for that extension type, fix the --params payload, and retry. Do not fall back to manual scaffolding. The one exception is HTTP_ENDPOINT on a CLI older than 1.1.243, which predates the generator but still supports the extension: create the endpoint file by hand as described in BACKEND_API.md (opens in a new tab).
What the CLI does automatically:
src/extensions.ts with the import and .use() callsrc/extensions.tsHTTP endpoints: Run npx wix generate --params '{"extensionType":"HTTP_ENDPOINT","name":"hello"}', then implement the handler in the returned file. Follow BACKEND_API.md (opens in a new tab); if the route does not respond, its troubleshooting hint shows how to confirm discovery from the build output.
Open every path returned in newFiles and replace stubbed handler bodies / UI / queries with the user’s actual logic, guided by the extension reference file’s API and configuration sections.
wix-design-system skill before editing your first .tsx/.jsx file that imports @wix/design-system. Do NOT invoke it preemptively for backend-only or data-only jobs — it adds large content to context that you won’t use.*.extension.ts with the name and aiContext its builder declares, per EXTENSION_METADATA.md (opens in a new tab).idSuffix (case-sensitive). If idSuffix is "product-recommendations", use <app-namespace>/product-recommendations NOT productRecommendations.Dashboard page UI only. tsc, wix build, and wix preview all check that the code compiles and runs — none of them check that it’s the dashboard the UX Success Model (opens in a new tab) describes. A page with a bare, un-summarized, un-openable table compiles cleanly and still fails the requirement — that gap is exactly how a generated dashboard passes every technical check and still disappoints. Measured runs confirm it: a page can compile clean and still ship with none of the three items below, because the earlier checklist entries were a stated intention rather than something re-checked against the code that actually landed.
Before moving to Step 5, re-open every page file you just wrote and check the actual code — not what you intended to include:
Not done: The page has a SummaryBar only if the request asked for one. Grep for it: an uninvited bar is a defect, not a bonus, and deleting it is the fix. If the request did ask, every metric earns its place and the headline counts what matches the filters (state.collection.total, fed by fetchTotal), not what has been paged in — any metric derived from keyedItems is labelled as such.
Not done: If a SummaryBar number is fed by fetchTotal, follow that function to the call it makes and confirm the call counts. A fetchTotal that resolves undefined — the usual cause being pagingMetadata.total, which a cursor-paged response does not carry — makes the bar report 0 beside a table full of rows, and it compiles, runs and passes every other check on this list. It must resolve a number from a count endpoint (items.query(id)…count(), a vertical’s own count, or offset paging with returnTotalCount: true); if the API has none, delete fetchTotal and label the metric as loaded rows. See TABLE_STATE.md (opens in a new tab).
Not done: Every row opens an editable entity page by default: onRowClick calls navigateToEntityPage, and the destination has an EntityPage, a working form, and a real save operation. A read-only route is justified by one of the three cases in DRAFT_TEMPLATE.md (opens in a new tab), and the final response names which one; report-only/export-only requests need no drill-in. The save calls the source’s real update method and lets a failed call throw, so the page shows its error — no no-op, local-state-only save, or catch that swallows the failure. If Preview is available, change one field, reload to confirm it saved, and change it back; otherwise report the save as unverified. A SidePanel in a collection page file is the defect this replaces. grep -n "<SidePanel" <page files> should return nothing — match the JSX tag, not the bare word, or the templates’ own “never a SidePanel” comments fail the check and invite someone to “fix” correct code.
Not done: Every filter name declared in the toolbar also appears inside fetchData‘s query construction — grep for the name in both places if unsure.
Not done: The table wires errorState — without it a failed query is indistinguishable from a slow one, and the page you just shipped cannot tell you which it is.
Not done: Routed templates only (all but the settings one) — the entry file both passes and guards location. PatternsReactRouter throws at open when location is missing or still undefined on the first render, and tsc, wix build and even a green build all pass regardless. Both halves are required — the location={location} prop and the location ? … : null guard around it, since observeState has not fired yet on the first render. Grep the entry file rather than trusting recall:
grep -n "observeState\|location={location}\|location ?" src/extensions/dashboard/pages/<page>/<page>.tsx # the file the builder's `component` points atThree hits is correct. A missing guard is the failure mode that has actually shipped: a measured run produced a page whose plumbing looked present and still crashed on open, while a re-run of the same prompt produced a working one — so this is intermittent, and re-running is not a check.
Not done: Every @wix/* vertical imported by the page’s api module is a declared dependency, and each one’s scope is listed under Manual Steps. Any call to a secondary vertical (an enrichment lookup, a filter’s options, a search term resolved to ids) is wrapped so its failure degrades that feature instead of failing the page.
If a box fails and no exception applies, add the missing piece now. Do not let “it compiles” stand in for “it satisfies the checklist” — Step 5 checks the former, this step checks the latter, and they are independent.
Run the four steps in Validation below. Do NOT report completion to the user until validation passes — if it fails, fix the errors and re-validate until it does.
Only after validation passes, provide a concise summary section at the top of your response:
## ✅ Implementation Complete
[1-2 sentence description of what was built]
**Extensions Created:**
- [Extension 1 Name] - [Brief purpose]
- [Extension 2 Name] - [Brief purpose]
**Build Status:**
- ✅ Dependencies: [Installed / status message]
- ✅ TypeScript: [No compilation errors / status]
- ✅ Build: [Completed successfully / status]
- ✅/⚠️ Preview: [Created — Dashboard URL / Failed - reason]
**⚠️ IMPORTANT: [X] manual step(s) required to complete setup** (see "Manual Steps Required" section below)Present any manual steps the user must perform (e.g., configuring settings in the Wix dashboard, enabling permissions, setting up external services).
Format:
## 🔧 Manual Steps Required
The following actions need to be done manually by you:
### 1. [Action Category/Title]
[Detailed description with specific instructions]
### 2. [Action Category/Title]
[Detailed description]wix generate --params updates src/extensions.ts automatically for registered extensions. HTTP endpoints require no import or .use() call; the runtime discovers their files. For background, troubleshooting, and the manual recovery pattern when src/extensions.ts drifts, see EXTENSION_REGISTRATION.md (opens in a new tab).
Execute these steps sequentially after all implementation is complete. See APP_VALIDATION.md (opens in a new tab) for the complete guide. Dashboard page UI: run Step 4c’s UX Completeness Self-Audit first — the checks below verify the code runs, not that it’s the dashboard the prompt asked for.
npx tsc --noEmit -p .npx wix buildnpx wix preview, in the foreground and unpiped: it uploads, prints the preview URLs and exits on its own, so no timeout, backgrounding, sleep or | tail. If your shell moves it to the background anyway, it stalled: read what it printed and .wix/debug.log once, then report that the preview did not complete. Don’t poll, and don’t promise a URLStop and report errors if any step fails. Check .wix/debug.log on failures.
For links to official Wix CLI documentation for all extension types, see DOCUMENTATION.md (opens in a new tab).
Build and review Wix CLI app extensions — dashboard pages, modals, plugins, menu plugins, custom element widgets, Editor React components, site plugins, embedded scripts, context providers, function libraries, lightbox (popup) behavior, page onLoad contexts, backend APIs, backend events, service plugins, data collections, and App Market readiness. Use when building ANY feature or extension for a Wix CLI app or preparing a Wix app for App Market review. Triggers on: add, build, create, implement, help me, dashboard, widget, plugin, backend, API, event, collection, embedded script, service plugin, Editor React component, context provider, function library, onLoad, on page load, checkout, shipping, tax, discount, SPI, CMS, schema, tracking, popup, lightbox, admin panel, menu item, modal, validate, test, verify, register extension, App Market, app review, submission readiness.
The verbatim description from this skill’s front matter — the string an agent matches on to decide whether to load it.
skills/wix-app/SKILL.mdmain, last pushed 8 November 2026.SKILL.md, not by matching a directory convention. 5 distinct layouts observed: skills/*/SKILL.md, skills/wix-headless-replatform/resources/*/SKILL.md, skills/wix-replatform/resources/*/SKILL.md, */SKILL.md, wix-replatform/resources/*/SKILL.md.h1 and no skipped levels:.claude-plugin/marketplace.json by Wix, declaring 1 plugin. It is read for editorial metadata only — never as the skill index, which is always the repository tree./wix/skills.md, and each skill at its own .md URL.205 files · 1.3 MB
Everything this skill ships beside its prose. All of it is set here, as subchapters of skill 1.
Documentation the agent loads on demand, rather than up front.
references/30 files · 206 KBreferences/app-tools/1 file · 4 KB
references/backend-event/1 file · 5 KB
references/context-provider/14 files · 91 KBreferences/context-provider/vertical-contexts/blog/9 files · 45 KBreferences/context-provider/vertical-contexts/bookings/13 files · 66 KBreferences/context-provider/vertical-contexts/events/22 files · 108 KBreferences/context-provider/vertical-contexts/stores/21 files · 100 KBreferences/custom-element-widget/1 file · 2 KB
references/dashboard-menu-plugin/7 files · 8 KBreferences/dashboard-page/17 files · 113 KBreferences/dashboard-plugin/1 file · 9 KB
references/data-collection/4 files · 25 KB
references/editor-react-component/24 files · 151 KBreferences/function-library/5 files · 28 KB
references/lightbox/2 files · 13 KB
references/page-on-load/2 files · 11 KB
references/service-plugin/13 files · 59 KBreferences/site-plugin/2 files · 19 KB
Executable code the skill can run.