Modeling content
A space's schema is its types, each a list of fields. Build them under Types in the admin, push them from code with the CLI, or let an assistant do it over MCP.
Kinds of types
| Content type | Entries in the page tree: pages, blog posts, products. Can be managed as a collection (a table with CSV import and export). |
| Block type | Nestable building blocks used in blocks fields and inside rich text: heroes, grids, FAQ items. |
| Global | Exactly one entry, outside the tree: site settings, footer, SEO defaults. |
Start from a preset under New type → From a preset: blog (with authors and quotes), products, events, job openings, locations, a company directory, team members, a landing page, site settings, and FAQ, testimonial, pricing, logo cloud and call-to-action blocks. A preset brings the block types it uses; ones that already exist with the same fields are reused.
Type settings: a title field (a single-line text field; content types name their entries after it, and an entry's URL follows it until it's first published; blocks show it in outlines), an icon, a color, a group (a section in the block picker) and, for blocks, a preview image.
Field types
One field type per kind of value; settings decide the shape:
| Type | Value | Settings |
|---|---|---|
text | "…" | multiline, minLength, maxLength, format (email, url, phone, slug), pattern + patternMessage, placeholder |
richText | ProseMirror JSON | marks, nodes (allow-lists), images, blocks (embeddable block types), maxLength |
markdown | "…" | maxLength |
number | 12.5 | min, max, integer, step, prefix/suffix, appearance: "slider" |
boolean | true | appearance: "switch" |
date | "2026-05-01", or ISO with time | time, min/max (a date or today), after (another date field: end after start) |
select | "a", or ["a", "b"] with multiple | options or a shared list, multiple, creatable (free values: tags), min/max, appearance |
color | "#1a2b3c" | |
asset | { "asset": "ast_…" }, or a list with multiple | multiple, accept, aspectRatios, min/max |
link | { "kind": "url", "url": "…" } (or entry, email, asset) | allow |
reference | "ent_…", or a list with multiple | multiple, types, under (a folder), min/max |
blocks | A list of blocks | types, min/max, initial (blocks new entries start with) |
table, json | Rows and columns; anything | |
geo, video, seo, form | Location; video embed; SEO settings; a form placed on the page | video: providers |
Every field has key, label, a stable id (assigned by the server), and optionally description, required, translatable, tab, group (a collapsible section), width: "half", defaultValue (for text, number, boolean, date, select and color fields), readOnly and hidden (for values set by integrations; not permissions). Root fields of content types can be indexed (fast Delivery API filters, up to 20 per space) and unique (not translatable).
Conditional fields
showIf shows a field only for some values of the fields above it in the same block:
{ "key": "url", "label": "URL", "type": "text", "required": true,
"showIf": { "match": "all", "rules": [{ "field": "linkType", "op": "equals", "value": "external" }] } }
Operators: equals, notEquals, in, notIn, filled, empty, greaterThan, lessThan. A hidden field isn't required and isn't published; its value stays in the draft in case the editor switches back. Conditions look at default-language values.
Changing a schema
Content follows schema changes, in drafts, every language, published content and history:
- Renaming a field (same
id, newkey) moves its values. - Converting (type,
multiple,time,multiline) changes values' shape: text ↔ markdown ↔ rich text, one ↔ many, date ↔ date and time, number ↔ text, reference → link, anything → JSON. Some conversions lose something (formatting, extra items, the time of day); values that can't be converted are removed. - Removing a field deletes its values (entry history keeps them).
- Renaming a type key updates entries, documents, folder settings and other types. Update your site code too.
The admin shows what a save will do first (POST /v1/spaces/<id>/types/<key>/preview): entries touched, values converted, lost or removed, and published entries that would no longer pass validation. Open editors are told and their unsaved edits follow. Every save is a version under History, where you can revert. A single change can touch up to 2,000 entries; use a migration script for more.
Generated types (blokcms types generate) follow the same model: multiple fields are arrays, conditional fields are optional, and rich text with embeds documents its image and block nodes.