All skills
wix avatar

/wix-app

@dc6f1fa official
by Wix.comwix/skills33 stars
33

Build and review Wix CLI app extensions — dashboard pages, modals, plugins, menu plugins, custom element widgets, Editor React components, site plugins, embedded scripts, 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, checkout, shipping, tax, discount, SPI, CMS, schema, tracking, popup, admin panel, menu item, modal, validate, test, verify, register extension, App Market, app review, submission readiness.

Use this Skill: https://skilld.dev/gh/wix/skills/wix-app

This session only. Nothing lands on disk.

referencesdashboard-pageTABLE_STATE.md

≈1.8k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Reading the state object useTableCollection hands you

Scope. The Component Docs Gate covers component names and props, and the package's own TableState declaration is the member list. This file covers only what that declaration cannot tell you: the plausible members that are absent from it, and the behaviour behind the ones that are there.

Why guessing here always fails

useTableCollection() returns a TableState. For the members themselves, read the declaration the index names — Read <pkgRoot>/dist/dts-bundle/index.json, then its file. Reading them is not the hard part; the hard part is that several plausible members don't exist at all, and one that does means something other than its name suggests (see Four that bite in practice).

One thing not to conclude from the docs bundle. dist/dts-bundle/ publishes CollectionState as a stub:

declare class CollectionState<T = any, F = any> { [key: string]: unknown }

That is a documentation abridgement, not the declaration your code compiles against. tsc resolves dist/types/index.d.ts, which re-exports the fully typed CollectionState from @wix/bex-core — no index signature. So state.collection.… is properly typed, a wrong member is a compile error at the access, and reading state.collection.status.status to debug a stuck table is sound. See WIX_PATTERNS_DOCS.md § 5.

Prefer a typed member on TableState itself anyway — it is the object the hook hands you, and the table's own view of the collection.

Four that bite in practice

state.filters does not exist. Filter state lives on the filter objects you created with stringsArrayFilter() / dateRangeFilter() and passed into filters. Keep those in module-level consts and reference the const in both the hook config and the JSX — that is also what MultiSelectCheckboxFilter's filter prop wants.

showLoadingState is not "the query is running". It stays true when the query resolves with zero rows, so binding SummaryBar's status to it leaves the bar on skeleton pills permanently on an empty collection — which reads as a hung network rather than an empty result. Use state.showErrorState ? 'error' : 'success'.

collection.isLoading and collection.refresh() are not members. They look plausible, they compile against the index signature, and neither exists at runtime.

A fetchTotal that resolves undefined shows 0, not the rows

This is the "SummaryBar says 0 while the table under it is full" report, and it is worth tracing once because every step is silent. FetchTotalState wraps your function in a second, one-item collection whose page is literally { items: [], total: await fetchTotal(query) }. That page then goes through CollectionState.updateResult, which computes lastPage.total ?? lastPage.items.length — so a total of undefined becomes 0, because the synthetic page has no items to fall back on. And QueryResultState.total reads fetchTotal ? fetchTotal.total : this._totals.processed: the moment fetchTotal exists it wins, and the loaded-rows fallback is gone.

Two consequences worth keeping in mind:

  • A wrong fetchTotal is worse than no fetchTotal. Omit it and total degrades to the rows you have; wire it to something that resolves undefined and a page with 4,000 matching rows reports 0. Nothing throws, nothing fails tsc, and the table beside it is correct.
  • pagingMetadata.total is not a count. A cursor-paged response carries no total, and @wix/data documents the field as returned only under offset paging with returnTotalCount: true. Under the cursor paging these pages default to, expect undefined. Call something that counts — QUERY_AND_PAGING.md.

To tell the two apart in a running page, show state.collection.totalStatus next to the number: it is the totals collection's own status, so a success beside a 0 means your function resolved nothing, not that the query failed.

Reading state outside the table: it is MobX

@wix/patterns depends on mobx and mobx-react-lite, so the state object is observable and a plain React component does not track it. Anything you derive from state in your own component — a SummaryBar count, a badge total, a header figure — is computed once on first render, when the collection is still empty, and never recomputed. The table itself updates because it observes internally; your derived numbers sit at zero next to a table full of rows, which reads as a bug in the query rather than in the wiring.

useSelector from @wix/patterns subscribes:

const loadedCount = useSelector(() => state.keyedItems.length);
const rows = useMemo(() => state.keyedItems.map((k) => k.item), [loadedCount]);

Select a primitive. Returning a fresh array or object from the selector gives it a new identity on every evaluation. Select a length, a total or an id, then derive the rest once it fires.

Query and result shapes

fetchData(query) receives a ComputedQuery<F>: limit, offset, page, search, rawSearch, cursor, filters, rawFilters, sort.

Read the return type from @wix/bex-core, not from @wix/patterns. The name CursorQueryResult exists in both packages and they are different types. The one your fetchData must satisfy is the generic in node_modules/@wix/bex-core/dist/types/hooks/paginationModeConfig.d.ts:

interface DataResultRaw<T> {
  items: T[];
  total?: number | null;
  available?: number;                          // total BEFORE filters
  cursor?: string | undefined | null;
  hasNext?: boolean | null;
}
type OffsetQueryResult<T> = Omit<DataResultRaw<T>, 'cursor'>;
type CursorQueryResult<T> = Omit<DataResultRaw<T>, 'cursor'> & { cursor: string | undefined | null };

Three consequences, each of which has shipped as a bug:

In cursor mode the cursor key is required; its value may be undefined. The intersection re-declares cursor without ?, so return { items } does not compile — but { items, cursor: undefined } does. "Required" is about the key, not the value.

On the last page return undefined, never ''. An empty string is still a cursor to the collection: it requests the next page forever and appends the same rows each pass, a table that grows without end while the API is perfectly happy, rendering as a spinner under the last row that reads as "still loading". Derive it so the empty case collapses:

cursor: response.pagingMetadata?.cursors?.next || undefined,

hasNext and total exist in both modes — they are on DataResultRaw, which both aliases extend. Cursor mode also accepts a separate fetchTotal, since a cursor-paged response carries no total; build its filter exactly as the page's or the count disagrees with the rows it counts.

Look any of these up yourself with Read <pkgRoot>/dist/dts-bundle/index.json and the file path it gives; the index is the single source of truth, and it moves between versions.

Source: SKILL.md on GitHub

1 warningtoday4 checks · Risk SAFE
  • Gen Agent Trust Hubtoday

    This skill is a specialized development toolkit for building extensions on the Wix platform. It provides comprehensive instructions for creating dashboard pages, backend APIs, and site plugins using the Wix CLI and SDKs. No malicious patterns were detected; the skill's behaviors, such as dependency management, command execution for builds, and local script execution for code reviews, are entirely consistent with its purpose as a developer productivity tool for the Wix ecosystem.

  • Sockettoday

    1 alert: gptAnomaly

  • Snyktoday

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at dc6f1fa. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated yesterday
compatibility
requires `@wix/cli` >= 1.1.192.

README badge

README badge for wix/skills/wix-app

Builds dashboard pages, modals, plugins, custom widgets, Editor React components, backend APIs, events, service plugins, and data collections for Wix CLI apps. Provides decision logic, API patterns, and validation workflows; scaffolding is owned by the Wix CLI via `wix generate --params`.

Generated from the current SKILL.md.

What extension types does this skill cover?
All Wix CLI app extension types: dashboard pages, modals, plugins, menu plugins, custom element widgets, Editor React components, site plugins, embedded scripts, backend APIs, backend events, service plugins, and data collections.
Does this skill scaffold the extension files for me?
The Wix CLI owns scaffolding via `wix generate --params` for all extension types except Backend API. This skill provides decision logic, API guidance, and business-logic patterns to fill in the generated stubs. Backend API files must be created manually.
What Wix CLI version is required?
The skill requires @wix/cli >= 1.1.192.
Do I need to create a Data Collection extension for app-specific data?
Yes, if you're saving or persisting app-specific data, managing domain entities in a dashboard, or running a service plugin that reads app-configured data. The skill infers this automatically—you don't need to explicitly request it.
Does this skill cover Wix Stores API usage?
Yes. When using any Wix Stores API (products, inventory, orders), the skill requires dual V1/V3 catalog support and references the Stores Versioning guide for module selection and field mapping.

Generated from the current SKILL.md. These answers refresh after source changes.