Schema reference

Field types

Every field type the schema can declare, with its knobs, defaults, and the YAML it produces on disk.

Not verified yet

The CMS supports 15 field types. Every field has the same set of common keys (FieldBase) plus type-specific extras. This page is exhaustive — use the table of contents on the right to jump to the type you need.

Common to every field

- key: heading # frontmatter key — where the value lands
  type: text # discriminator — selects the field implementation
  label: Heading # author-facing label, shown above the input
  description:  # optional helper text, shown under the field
  required: true # validator enforces non-empty
  hidden: true # never rendered (value seeded from `default`)
  default: 'Welcome' # initial value for new entries
  visibleIf: # show only when the condition is true
    field: tier
    op: eq
    value: pro
  whenHidden: keep # keep | drop — what to do with stored value
  customValidators: [] # plugin validators, see Validation
  computed: # auto-derived value, see Computed fields
    from: title
    transform: slug
    mode: auto
KeyEffect
keyThe frontmatter key the value lands at. Must be unique inside its group.
typeType discriminator. The remaining knobs are type-specific.
labelAuthor-facing label. Required on every field (no fallback to key).
descriptionHelper text rendered under the input.
requiredReject save when empty. See Validation → required.
hiddenNever rendered. Value still seeded from default so saves don't strip it.
defaultInitial value (literals only; no expressions).
visibleIfHide unless the condition evaluates true. See Conditional rendering.
whenHiddenkeep (default) preserves the stored value when hidden; drop purges on save.
customValidatorsPlugin validators applied in addition to the built-ins.
computedAuto-fill the value from another field. See Computed fields.

text

Single-line text input.

- key: title
  type: text
  label: Title
  default: ''
  minLength: 5
  maxLength: 80
  recommendedLength: { min: 30, max: 60 }
  regex: '^[A-Z]'
  regexMessage: 'Start with a capital.'
  minLengthMessage: 'Make it at least 5 characters.'
KnobEffect
minLengthHard lower bound (chars). Violations surface in the Errors panel.
maxLengthHard upper bound.
recommendedLengthSoft sweet-spot range. The counter turns green inside, amber outside.
regexJavaScript-flavoured regex source (no surrounding slashes).
regexMessageCustom error text for regex.
*Message variantsOverride the default error text for required / minLength / maxLength.

Use text for short single-line values (titles, slugs, IDs). For multi-line plain text use paragraph. For rich formatting use richtext.

paragraph

Multi-line plain-text input. Same length / regex knobs as text.

- key: description
  type: paragraph
  label: Description
  rows: 3
  recommendedLength: { min: 50, max: 160 }
KnobEffect
rowsInitial visible row count (auto-grows).

Use paragraph for SEO descriptions, summaries, social-card copy — anywhere the content is plain text but multi-line.

richtext

Tiptap-based rich-text editor. Toolbar buttons are opt-in.

- key: body
  type: richtext
  label: Body
  format: markdown
  toolbar:
    - bold
    - italic
    - heading2
    - heading3
    - link
    - bulletList
    - orderedList
    - code
    - codeBlock
    - blockquote
KnobValuesEffect
formatmarkdown (default), htmlStorage format the value round-trips through.
toolbararray of button namesWhich buttons render. Omit for the default set.

format: markdown writes the value as Markdown — typically the .md file's body. format: html writes HTML. Pick markdown when your build pipeline already runs the file through a Markdown processor; pick html when you want the CMS to do the rendering and you're storing pre-rendered output.

number

Numeric input. Integer when step: 1, decimals otherwise.

- key: seats
  type: number
  label: Seats
  min: 1
  max: 100
  step: 1
  default: 1
KnobEffect
minReject save when below.
maxReject save when above.
stepIncrement (also drives integer vs decimal).

For a sliding-control UI prefer range. For a set of allowed values use select.

boolean

Toggle. The simplest field type.

- key: featured
  type: boolean
  label: Featured
  default: false

No type-specific knobs beyond default.

date

Date picker. Stores as ISO-8601 yyyy-mm-dd.

- key: publishedAt
  type: date
  label: Published at
  default: ''

No time component. Use a text field with a regex if you need ISO datetimes or other formats.

color

Colour picker.

- key: accent
  type: color
  label: Accent colour
  format: hex
  default: '#3b33c7'
KnobValuesEffect
formathex (default), oklchhex writes #rrggbb; oklch writes oklch(...) — useful when your theme runs through Tailwind v4 / OKLch.

range

Slider with min / max / step.

- key: spacing
  type: range
  label: Spacing
  min: 0
  max: 100
  step: 5
  default: 50

Same min / max / step semantics as number but renders as a slider control. Good fit for opacity, spacing scale, or any value the author tweaks visually.

multichoice

Multi-select with min / max constraints. Value is string[].

- key: tags
  type: multichoice
  label: Tags
  options:
    - travel
    - food
    - sport
  min: 1
  max: 3
KnobEffect
optionsThe allowed values. Strings or {value, label, description} objects.
minReject save when fewer than this many are selected.
maxReject save when more than this many are selected.

Multichoice arrays diff as + added, − removed pills in the Version history — the schema-aware renderer recognises the set semantics.

URL field. Same regex semantics as text.

- key: ctaUrl
  type: link
  label: CTA URL
  regex: '^https?://'

Use this over text when the intent is "this is a hyperlink" — UX hints + validators tune to URLs. The author can still paste anything; the regex enforces the actual shape.

image

Picker + drag-drop upload. With storage: set, the picker scopes to that storage and the upload routes through it.

- key: hero
  type: image
  label: Hero image
  storage: uploads
  accept: image/png, image/jpeg
  maxSize: 5242880
KnobEffect
storageNamed storage from config.yml#storages. See Media library.
acceptComma-separated MIME glob list. Overrides the storage's accept.
maxSizeBytes. Overrides the storage's max_size.

The editor renders the value as an inline thumbnail. For non-images use file.

file

Same as image but for non-image attachments (PDFs, videos, audio).

- key: attachment
  type: file
  label: Attachment
  storage: uploads
  accept: application/pdf
  maxSize: 10485760

The editor renders the value as a file row (name + icon + type + size) rather than a thumbnail.

select

Single-select with an explicit option list.

- key: tier
  type: select
  label: Tier
  options:
    - free
    - pro
    - enterprise
  default: free
  widget: dropdown
KnobValuesEffect
optionsarray of strings or {value, label, description}The allowed values.
defaultone of the option valuesInitial value.
widgetdropdown (default), radio, buttons, comboboxControls the input UI.

dropdown is the universal default. radio for short lists where every option should be visible. buttons for visual toggles. combobox for long lists where the author needs to type-to-search.

group

Object field — a nested set of fields under a single key.

- key: hero
  type: group
  label: Hero
  fields:
    - key: heading
      type: text
      label: Heading
    - key: subheading
      type: paragraph
      label: Subheading
  preview:
    title: heading
KnobEffect
fieldsOrdered list of child fields. Recursive — groups can contain groups.
previewDrives the "drill-in card" rendering when the parent surfaces this group.

The value is {heading, subheading} in YAML; the editor renders the inner fields inline at the parent level (no separate drill-in card unless you mount the group as an array item).

array

The richest field type. Each items[] entry is one allowed item shape — a group, a $ref to a block, or a primitive ({type: text} for arrays of strings).

- key: blocks
  type: array
  label: Content blocks
  items:
    - $ref: hero-compact
    - $ref: media-text
  idKey: _type
  minItems: 1
  maxItems: 10
  uniqueOn: slug
  uniqueOnMessage: 'Each block needs a unique slug.'
KnobEffect
itemsOne entry per allowed item shape. Single-entry = uniform array; multi-entry = multi-shape.
idKeyMulti-shape discriminator key on items. Defaults to _type. Override for content that uses kind:, block:, etc.
minItemsReject save when below this count.
maxItemsReject save when above this count; "Add item" disables at the cap.
uniqueOnRelative path within an item; rejects duplicates.
*MessageCustom messages for any of the above.

Single-shape

items:
  - type: text
    key: tag
    label: Tag

Every item is the same shape. No discriminator key on items.

Multi-shape

items:
  - $ref: hero-compact
  - $ref: media-text
  - $ref: stats-row

Each item carries a discriminator key (_type: by default) matching one entry's $ref target. The CMS reads + writes through this key. Changing idKey: after content exists requires a one-shot migration to rename the key on each item.

Primitive

items:
  - type: text
    key: tag

Arrays of strings, numbers, etc. No discriminator needed (the JS type is the discriminator). The editor renders a compact list with inline controls.

On this page