← Files WixARCHIVED FILE
skills/wix-headless-templates/cms/seed/SEED.md
6.82 KB · Oct 8, 2026 · 12:02 UTC
# CMS — seeding
Seed by **running `seed-cms.mjs` with a plan file** — don't hand-write the REST calls.
The script mints its own site token via the Wix CLI (logged-in session + `wix.config.json`
required), installs the Wix Data (CMS) app if needed, resolves every IMAGE value into Wix
Media in one parallel wave, and creates everything in order: per collection — create
(schema + permissions) → bulk-insert items → wire multi-references → verify persistence.
```bash
# from the project root (where wix.config.json lives):
node <SKILL_ROOT>/templates/cms/seed/seed-cms.mjs plan.json
```
`plan.json` is plain data — **it IS the site's content model**: the collections, their field
schemas, and the items the pages will render. Write it from the brief. Default to **one or
two content collections with ~3–6 items each** (the seed shows the shape; the owner adds the
rest in the dashboard). Give any collection that gets a detail page a `slug` TEXT field, and
every content item an image on an IMAGE field (a content site without images looks broken).
```json
{
"collections": [
{
"id": "categories", "displayName": "Categories",
"fields": [{ "key": "name", "type": "TEXT" }],
"items": [{ "name": "Cakes" }, { "name": "Breads" }]
},
{
"id": "recipes", "displayName": "Recipes",
"fields": [
{ "key": "title", "type": "TEXT" },
{ "key": "slug", "type": "TEXT" },
{ "key": "summary", "type": "TEXT" },
{ "key": "body", "type": "RICH_TEXT" },
{ "key": "photo", "type": "IMAGE" },
{ "key": "publishDate", "type": "DATE" },
{ "key": "categories", "type": "MULTI_REFERENCE", "referencedCollectionId": "categories" }
],
"items": [
{ "title": "Chocolate Layer Cake", "slug": "chocolate-layer-cake",
"summary": "Three layers, one ganache.", "body": "<p>Cream the butter…</p>",
"photo": "https://…", "publishDate": "2026-08-01", "categories": [0] },
{ "title": "Country Sourdough", "slug": "country-sourdough",
"summary": "A 24-hour loaf.", "body": "<p>Feed the starter…</p>",
"photo": "https://…", "publishDate": "2026-08-10", "categories": [1] },
{ "title": "Pavlova", "slug": "pavlova",
"summary": "Crisp shell, soft heart.", "body": "<p>Whip the whites…</p>",
"photo": "https://…", "publishDate": "2026-08-20", "categories": [0] }
]
}
]
}
```
- `id` — the collection id the frontend binds to, verbatim (no namespace; Wix doesn't rename
it). Item keys must match the field `key`s exactly — the script fails loud on a key the
schema doesn't have (the API would silently drop it).
- Field `type` — `TEXT`, `NUMBER`, `BOOLEAN`, `DATE`, `DATETIME`, `TIME` (a `"hh:mm:ss.SSS"`
string, stored as text), `URL`, `EMAIL`, `IMAGE`, `RICH_TEXT` (an HTML string, stored verbatim),
`ARRAY_STRING` (tags: an array of strings), `REFERENCE`, `MULTI_REFERENCE`.
- `IMAGE` values — the default is `{ "prompt": "..." }` (AI-generated, ~1 Wix AI credit per
image, account-billed): brand-contextual — subject, aesthetic/mood, palette, lighting —
always ending "no text, no watermarks". At least one image in the set shows the real subject of the business — the actual product/space/service, not abstract decoration. For an asset the user actually supplied use
`{ "path": "..." }` (a file on this machine — uploaded to Wix Media) or an https URL string
(their own hosted URL; verify it with `curl -sI` → 200) — never a stock-photo or guessed URL. Images
resolve in parallel and never block the seed; a failed image leaves that field unset (the
item stays text-only).
- `DATE`/`DATETIME` values are ISO strings — the script wraps both as `{ "$date": iso }` (the
form the app's reads and date filters are proven against; a `"YYYY-MM-DD"` string would be
stored as text). A `TIME` value stays a string.
- References: **order collections so targets come first.** A `REFERENCE` value is the target
item's index in its collection's `items` array; `MULTI_REFERENCE` is an array of indices
(set at insert it would be silently dropped — the script wires these via
`POST /wix-data/v2/bulk/items/insert-references`; at runtime the app does the same through
`linkItems` / `unlinkItems` in `wix/cms/items.ts`).
- `permissions` — omit for the **public-read** default
(`read: ANYONE`, writes `ADMIN`). Other shapes (per action: `ANYONE` › `SITE_MEMBER` ›
`SITE_MEMBER_AUTHOR` › `ADMIN`):
| preset | `read` / `insert` / `update` / `remove` | use |
|---|---|---|
| public-read (default) | `ANYONE` / `ADMIN` / `ADMIN` / `ADMIN` | admin content, anyone reads |
| collaborative | `ANYONE` / `ANYONE` / `ANYONE` / `ANYONE` | visitor-written shared board (anonymous, unscoped) |
| member-private | `SITE_MEMBER_AUTHOR` / `SITE_MEMBER` / `SITE_MEMBER_AUTHOR` / `SITE_MEMBER_AUTHOR` | per-user "my…" rows — **seed it EMPTY** (rows seeded here would be owned by the admin, invisible to members) |
| member-shared-read-only | `SITE_MEMBER` / `ADMIN` / `ADMIN` / `ADMIN` | gated: any member reads, seed/admin writes |
| public-wall | `ANYONE` / `SITE_MEMBER` / `SITE_MEMBER_AUTHOR` / `SITE_MEMBER_AUTHOR` | members post, everyone reads |
`read` is the privacy decision — a public collection's `read` MUST be `ANYONE` or the
visitor frontend reads **zero items with no error**.
**Seeding is additive — never delete or overwrite existing content** (an existing collection
is left as-is; its items are appended); ask first if a cleanup seems needed.
## Supplied content
The general rules are in `templates/shared/SUPPLIED-CONTENT.md`. For the CMS the user's data
defines the schema: each distinct table, sheet or file becomes a collection, its columns become
`fields` with a type read from the values (`TEXT`, `NUMBER`, `DATE`, `IMAGE` for image URLs,
`RICH_TEXT` for HTML), and its rows become `items`. Keep the user's column names as field keys. A
column whose values point at rows of another table becomes a `MULTI_REFERENCE`. When a column's
type is ambiguous, ask.
## Escape hatch — individual functions
`setupCms` composes exported steps — `installDataApp`, `createCollection`, `importImage`,
`bulkInsertItems`, `insertReferences`, `verifyItems`, plus `makeCtx()` — import them only
for a partial re-seed.
## Reference
Unexpected shape or an uncovered operation → read the live Wix API reference; every call the script
makes carries a `docs:` line with its reference page.
Endpoints used: `POST /wix-data/v2/collections` (Create Data Collection),
`POST /wix-data/v2/bulk/items/insert` (Bulk Insert Data Items),
`POST /wix-data/v2/bulk/items/insert-references` (Bulk Insert Data Item References),
`POST /wix-data/v2/items/query` (Query Data Items — the verify step),
`POST /site-media/v1/files/import` (Import File),
`POST /apps-installer-service/v1/app-instance/install` (Install App).
SHA-256: 80d5c4a5e02bf0723bca4817091a5b54038f7200465889cfb939dc11ab7a643e