Products#
Shop › Products lists the catalogue. A product has one General tab (price, SKU, supply, images, variants — the same on every locale) and one tab per project locale for the localized copy (name, description, SEO). Products follow the built-in product schema; a project can extend it with its own fields under Schemas.
Variants#
A product can have children (variants) that inherit or override its pricing and carry their own stock. The Variants card lists them; the Properties card maps variant attributes (size, colour, …) to the children so the storefront can build a picker.
Additions#
An addition is a product offered with another one — gift packaging, insurance, engraving, an extended warranty. It is an ordinary product of the project, usually a service (no stock) with its own price, that the host product's Additions card references. Add an existing product or create a new service from the card; the storefront renders the add-on chooser from the product page's additions (each entry carries the addition's own price for that market) and adds a picked addition to the cart under its own SKU. One addition can be offered by many products, and a change to it (name, price) reaches every host automatically. Variants without additions of their own show the parent's.
Tags & categories#
A product carries keys — tags: ["sale", "new"] and categories: ["recipe:summer:tomato"] — never display text. The labels per language live on two pages:
- Data › Tags — a flat registry: one row per key, one label column per locale, inline editing (Save writes the changed languages). Rename a key and every product carrying it is rewritten; delete strips it from the products.
- Data › Categories — a tree. A category is a path of segments joined by
:(recipe:summer:tomato); each row labels its own segment. Add a child, rename a segment, move a node under another one or delete a subtree — the products carrying any node of the subtree are rewritten first, then the registry. A product projects the node you chose, not its ancestors.
Both pages offer Scan products: it reads every product once and lists the values that are not registry keys yet (free-text tags typed before the registry existed), each with a proposed key and the raw value as the default-language label — Register creates the entry and rewrites those products. The rewrite is capped at 500 products per action; bigger migrations are a script job.
On a product's General tab the Tags & categories card is a search-as-you-type picker over both registries; typing something new offers Create «…», which opens the same dialog the pages use. A value that is not in the registry shows amber until you replace or register it.
The labels are ordinary project translations under the reserved groups tag and category (hidden from Data › Wording): a template prints them with {{t "tag" this}} inside {{#each tags}}, or {{t "category" this}} — a missing translation falls back to the default language's label, then to the key. Listing by tag is a reference query ({"tags": {"array-contains": "sale"}}); a parent category lists its subtree with array-contains-any over the node and its descendants.
Stock#
Shop › Stock is the supply ledger per SKU. Each entry belongs to the project that owns it; the API's stock routes enforce that ownership. Supply shown on a product is read from here.
Access#
The commerce capability, write to edit.