GET /api/v1/page-builder/catalog returns the raw catalog JSON. The response ETag header is the catalog’s content digest — send If-None-Match: "<digest>" to get a 304 Not Modified, and cache by digest.Current catalogVersion: 0.22.1 · digest: sha256:bf03f334ebc11302490979ca4b2cf552d6cfbbb0c32c6f284f810d8f637b1aceNode shape
Every node in a page tree is the same envelope. The renderer dispatches onkind — never on type — and reads the node’s content from a top-level value, a sibling of settings:
template from the table below and a children array. Putting a node’s content in settings.value instead of value, or omitting a section’s template, is accepted by the API and then silently dropped by the renderer; an unrecognized settings.weight (a CSS keyword such as "bold") is quietly discarded rather than applied. Every node also needs an id.
See Node shape for the full contract, including the leaf-kind settings and the surface.background enum.
Templates
Node kinds
The catalog’ssettingsSchema map is the authority on what each kind accepts: 33 kind:<nodeKind> entries plus the shared background, gradient, structural, surface shapes, each listing typed properties with their enums, defaults, and per-field notes, split into core and presentational buckets matching the consumer profiles below. See Node shape for the shapes that most often cause a silent render drop.
Section types
Anon-safe — whether the section type is whitelisted on the backend’s sanitized pre-auth render (login / register / payment pages for logged-out visitors). It does not affect public-hub page visibility: anonymous visitors get the full published tree of any public page; only author-set access gates prune content there.
Settings vocabulary
settingsSchema is the per-kind:<k> settings contract for the page-builder node tree. Each kind’s schema splits into two tiers: core settings that every consumer — the web hub, native apps, any future renderer — must honor to render the node correctly, and presentational settings that native apps and other constrained consumers are free to ignore. Only keys and values the mio-hub renderer actually implements are listed below; this documents what’s real, not an aspirational spec. Recipes must not restate a setting’s default value — omitting a key defers to the hub’s built-in default for that key. The mio-hub renderer is the source of truth for this vocabulary, and it is declared directly in the catalog (MIO-2685).
shared:background
Flattened TemplateSurface Background discriminated union (src/lib/page-tree/types.ts). Validation limitation: enum applies to ‘type’; all variant fields are optional and the validator cannot enforce which fields are required per ‘type’ value. ‘thumbnail’ is excluded per the honesty policy (decision 4) — declared as a TODO in hub types, implemented nowhere, used by no recipe.
shared:gradient
Paired with shared:background when type=‘gradient’ (src/lib/page-tree/types.ts Gradient, src/lib/theme/types.ts GradientType).
shared:surface
TemplateSurface (src/lib/page-tree/types.ts). Nested under a kind’s own ‘surface’ settings key (see kind:stack, kind:content-card, and the section-root template-level surface consumed via TemplateSurface). Resolved by useNodeSurface() (src/components/primitives/node-surface.tsx).
shared:structural
NOT referenced via {type:‘object’,shape:‘structural’} from a kind descriptor like the other shared shapes. This is a validator-level ADDITIVE allowlist: every node’s settings object is validated against ‘kind:<its-kind>’ UNIONED with these three keys — tab_label/slot are read generically off ANY child node’s settings by an ANCESTOR container (tabs.tsx, accordion.tsx, find-by-slot.ts), independent of the child’s own kind, and are not part of any single kind’s own *Settings TS interface; surface is read generically off ANY node’s settings by renderer.tsx’s <TemplateSurface> wrapper, gated on that node’s ‘template’ annotation naming a templates[]/pageTemplates[] entry that itself declares a ‘surface’ property (the surface-declaring template set), independent of the node’s own kind. This is an extension beyond the design spec’s literal decision-1 text (which only names shared:surface as a referenced shape); documented here because the real catalog already uses tab_label/slot on stack/text/tabs nodes and surface on section-root container nodes (see Task A1 defaults-audit notes + MIO-2685 review round 1), and excluding any of the three would make the validator reject existing recipes. MIO-2724 addendum: ‘name’/‘role’/‘salesMeta’ (REVIEW — flagged for owner confirmation, see their own descriptions) extend this additive allowlist with catalog-authoring-only narrative-arc metadata used by the page-sales recipe’s section-root nodes — distinct from any mio-hub renderer concern, and (for ‘role’) a deliberate same-name/different-vocabulary overload against kind:field.core.role, resolved safely by this validator’s kind-first-then-structural-fallback lookup order.
kind:stack
kind:row
kind:grid
kind:carousel
kind:horizontal-scroll
kind:tabs
No settings.
The Tabs component reads NO settings of its own (PRIMITIVE_DEFAULTS explicitly documents this: “tabs — the component reads no settings at all”). Its per-child tab label comes from shared:structural’s tab_label on each CHILD’s own settings, not from a tabs-kind setting.
kind:container
No PRIMITIVE_DEFAULTS entry (container: {}) — the DS-intended maxWidth:‘content’ default has NO inline ’??’ fallback in container.tsx, deliberately undeclared per that file’s own comment (would change rendering the moment MIO-2358 wires cascade layer 1).
kind:content-card
kind:accordion
kind:video
kind:divider
kind:progress-ring
kind:headline
kind:text
kind:image
EXCLUDES ‘width’/‘height’ from ImageSettings — the hub interface comment states they are ‘presently no-ops’ (no longer forwarded to the rendered <img>, ui/thumbnail owns that element with no sizing passthrough), kept on the TS contract only for BE-served-data forward-compat parsing, not for authoring. Per the honesty policy, a key with no rendering effect does not enter the vocabulary.
kind:button
kind:icon
kind:field
kind:media-slot
kind:cta-slot
kind:file-player
kind:file-attachments
kind:search-bar
kind:quote
kind:banner
kind:countdown
kind:logo
kind:theme-toggle
No settings.
kind:plan-group
kind:plan-card
kind:plan-price
kind:doodle
kind:featured-icon
Consumer profiles
ios-min— templates:hero; settings:coreweb— templates: all templates; settings:core+presentational