MADORIMADORI

Field Types

Madori includes 18 built-in field types for constructing content schemas via blueprints. Each field type defines how content is captured in the Control Panel and how data is stored in flat-file entries.

This reference documents every field type with its configuration options, supported validation rules, stored value format, and example YAML configuration.


Configuration Reference

All field types share a common configuration structure defined in blueprints:

- handle: field_handle
  field:
    type: <field_type>
    display: Human Label
    required: true
    default: <default_value>
    validate:
      - required
      - min:5
      - max:200
    options:
      # type-specific options
    visibility:
      field: another_field
      operator: equals
      value: show_this

Common Properties

Property Type Description
type string One of the 18 field type identifiers (required)
display string Label shown in the Control Panel. Auto-generated from handle if omitted
required boolean Whether the field must have a value. Default: false
default any Default value pre-populated on create forms
validate string[] Array of validation rule strings
options object Type-specific configuration options
visibility object Conditional visibility based on another field's value

Validation Rules

Madori supports the following validation rules. Each rule is only enforced on compatible field types — incompatible rules are silently ignored with a console warning.

Rule Syntax Compatible Types Description
required required All types Field must have a non-empty value
min min:<n> text, slug, markdown, tiptap, code, number Minimum character length (text) or minimum value (number)
max max:<n> text, slug, markdown, tiptap, code, number Maximum character length (text) or maximum value (number)
regex regex:<pattern> text, slug, markdown, tiptap, code Value must match the regular expression
url url text, slug, markdown, tiptap, code Value must be a valid URL
email email text, slug, markdown, tiptap, code Value must be a valid email address
numeric_range numeric_range:<min>,<max> number Value must be within the specified range

Visibility Conditions

Any field can be conditionally shown or hidden based on another field's value:

visibility:
  field: category
  operator: equals
  value: premium

Supported operators: equals, not_equals, contains, empty, not_empty.

When a field is hidden, its value is excluded from the submission payload.


Text

A single-line text input for short-form content such as titles, names, and labels.

Configuration Options

Option Type Default Description
placeholder string Placeholder text displayed when the field is empty

Supported Validation

required, min, max, regex, url, email

Value Format

Stored as a string.

Example

- handle: title
  field:
    type: text
    display: Page Title
    required: true
    default: Untitled
    validate:
      - required
      - min:3
      - max:120
    options:
      placeholder: Enter a page title...

Slug

An auto-formatted URL-friendly identifier. Renders with a monospace font and provides guidance to use lowercase letters, numbers, and hyphens.

Configuration Options

No type-specific options. Inherits common properties.

Supported Validation

required, min, max, regex, url, email

The built-in pattern [a-z0-9-]+ is recommended via the regex rule for strict enforcement.

Value Format

Stored as a string. Expected pattern: [a-z0-9-]+.

Example

- handle: slug
  field:
    type: slug
    display: URL Slug
    required: true
    validate:
      - required
      - regex:^[a-z0-9-]+$

Markdown

A multi-line plain-text editor for writing Markdown content. Renders as a resizable textarea.

Configuration Options

No type-specific options. Inherits common properties.

Supported Validation

required, min, max, regex, url, email

When min or max is used, it applies to character count of the raw Markdown text.

Value Format

Stored as a string containing raw Markdown.

Example

- handle: body
  field:
    type: markdown
    display: Body Content
    validate:
      - min:50

Tiptap

A full WYSIWYG rich-text editor powered by TipTap. Supports headings, lists, links, images, tables, code blocks, and text alignment. Content is stored as TipTap JSON and can be converted to/from Markdown and HTML.

Configuration Options

Option Type Default Description
placeholder string Placeholder text displayed in the empty editor

Supported Validation

required, min, max, regex, url, email

Validation applies to the text content extracted from the structured JSON.

Value Format

Stored as a TipTap JSON object (structured document tree). Accepts JSON objects, JSON strings, or legacy Markdown strings on read.

Example

- handle: content
  field:
    type: tiptap
    display: Rich Content
    required: true
    options:
      placeholder: Start writing...

Number

A numeric input field. Supports integer restriction, min/max bounds, and step increments via HTML number input attributes.

Configuration Options

Option Type Default Description
min number Minimum allowed value (HTML input constraint)
max number Maximum allowed value (HTML input constraint)
step number Step increment for the input control
integer boolean false When true, restricts to whole numbers

Supported Validation

required, min, max, numeric_range

The min and max validation rules enforce server-side/client-side minimum and maximum values. The numeric_range rule combines both into a single declaration.

Value Format

Stored as a number. Returns null when empty.

Example

- handle: price
  field:
    type: number
    display: Price
    required: true
    default: 0
    validate:
      - required
      - numeric_range:0,10000
    options:
      min: 0
      max: 10000
      step: 0.01

Toggle

A boolean on/off switch rendered as a sliding toggle button. Includes ARIA role="switch" and keyboard accessibility.

Configuration Options

No type-specific options. Inherits common properties. Typically configured with a default value.

Supported Validation

required

Value Format

Stored as a boolean (true or false).

Example

- handle: featured
  field:
    type: toggle
    display: Featured Article
    default: false

- handle: published
  field:
    type: toggle
    display: Published
    default: true

Select

A dropdown selector for choosing a single value from a predefined list of options.

Configuration Options

Option Type Default Description
options string[] [] Array of selectable option values
choices string[] [] Alias for options

Both options and choices keys are supported — use whichever reads better in context.

Supported Validation

required

Value Format

Stored as a string (the selected option value). Empty string when no selection.

Example

- handle: status
  field:
    type: select
    display: Status
    required: true
    default: draft
    validate:
      - required
    options:
      options:
        - draft
        - published
        - archived

Multiselect

A checkbox-based selector for choosing multiple values from a predefined list.

Configuration Options

Option Type Default Description
options string[] [] Array of selectable option values
choices string[] [] Alias for options

Supported Validation

required

Value Format

Stored as an array of string values (selected option values). Empty array when no selections.

Example

- handle: tags
  field:
    type: multiselect
    display: Tags
    options:
      options:
        - javascript
        - typescript
        - react
        - nextjs
        - nodejs

Date

A date picker using the browser's native date input.

Configuration Options

No type-specific options. Inherits common properties.

Supported Validation

required

Value Format

Stored as a string in YYYY-MM-DD format.

Example

- handle: published_at
  field:
    type: date
    display: Publish Date
    required: true
    validate:
      - required

Asset

A file picker that integrates with the Asset Manager. Supports single or multiple file selection, drag-and-drop upload, and the asset browser modal for file selection.

Configuration Options

Option Type Default Description
max_files number 0 Maximum number of files. 1 = single file, 0 = unlimited

Behaviour by max_files Value

Value Behaviour Stored Format
1 Single file selection with replace button string (file path)
> 1 Multiple files up to limit, shows counter string[] (array of paths)
0 (or omitted) Unlimited file selection string[] (array of paths)

Supported Validation

required

Value Format

Single: stored as a string path (e.g. /assets/images/hero.jpg). Multiple: stored as a string[] array of paths.

Example

# Single image
- handle: featured_image
  field:
    type: asset
    display: Featured Image
    required: true
    options:
      max_files: 1

# Multiple images (up to 5)
- handle: gallery
  field:
    type: asset
    display: Photo Gallery
    options:
      max_files: 5

# Unlimited attachments
- handle: attachments
  field:
    type: asset
    display: Attachments

Entries

A relationship field for referencing other collection entries by slug. Stores cross-references between entries.

Configuration Options

No type-specific options currently. A visual relationship picker is planned — the current implementation accepts comma-separated slugs.

Supported Validation

required

Value Format

Stored as an array of string slugs referencing other entries.

Example

- handle: related_posts
  field:
    type: entries
    display: Related Posts

- handle: author
  field:
    type: entries
    display: Author
    required: true

Taxonomy

A field for assigning taxonomy terms to an entry. Connects entries to taxonomy term hierarchies.

Configuration Options

No type-specific options currently. A visual term picker is planned — the current implementation accepts comma-separated term slugs.

Supported Validation

required

Value Format

Stored as an array of string term slugs.

Example

- handle: categories
  field:
    type: taxonomy
    display: Categories
    required: true
    validate:
      - required

Replicator

A flexible, repeatable block builder for composing structured page content. Each block is backed by a fieldset definition, enabling editors to build complex layouts from a library of block types.

Configuration Options

Option Type Default Description
sets string[] [] Array of fieldset handles available as block types

Fieldsets are defined at resources/fieldsets/{handle}.yaml. See the Fieldsets documentation for details.

Features

  • Add blocks from configured fieldset types
  • Collapse and expand individual blocks
  • Preview summary showing block type and primary text field
  • Reorder blocks via up/down buttons (keyboard-accessible)
  • Drag handle for mouse-based reordering
  • Duplicate and delete individual blocks
  • Supports nesting (replicator within replicator) up to 3 levels
  • Default values from fieldset field definitions are pre-populated

Supported Validation

required

Value Format

Stored as an array of objects. Each object includes a _type field identifying the fieldset, plus all field handle values:

blocks:
  - _type: hero
    title: Welcome to Madori
    subtitle: A flat-file CMS for Next.js
  - _type: features_grid
    heading: Features
    columns: 3

Example

- handle: blocks
  field:
    type: replicator
    display: Page Blocks
    options:
      sets:
        - hero
        - features_grid
        - basic_cta
        - rich_text

Grid

A structured repeatable field where every row shares the same field structure. Unlike Replicator (which supports multiple block types), Grid is designed for tabular data where each row has identical columns.

Configuration Options

The Grid field currently accepts JSON array data directly. A visual row editor with drag-and-drop reordering is planned.

Supported Validation

required

Value Format

Stored as an array of objects (JSON). Each object represents a row with consistent keys:

pricing_tiers:
  - name: Starter
    price: 9
    features: "5 projects, 1GB storage"
  - name: Pro
    price: 29
    features: "Unlimited projects, 10GB storage"

Example

- handle: pricing_tiers
  field:
    type: grid
    display: Pricing Tiers
    required: true

YAML

A raw YAML editor rendered as a monospace textarea. Allows developers to enter arbitrary structured data that doesn't fit other field types.

Configuration Options

No type-specific options. Inherits common properties.

Supported Validation

required

Note: YAML syntax validation is not currently enforced — editors are responsible for valid YAML.

Value Format

Stored as a string containing raw YAML content. Parsed at read-time by consuming applications.

Example

- handle: metadata
  field:
    type: yaml
    display: Custom Metadata
    default: "key: value"

Code

A code editor rendered as a monospace textarea with spell-check disabled. Designed for entering code snippets, embed codes, or structured text that should not be spell-checked.

Configuration Options

No type-specific options. Inherits common properties.

Supported Validation

required, min, max, regex, url, email

Value Format

Stored as a string containing the raw code content.

Example

- handle: snippet
  field:
    type: code
    display: Code Snippet
    validate:
      - max:5000

Blocks

A page-building field that automatically includes all fieldsets marked with is_block: true. Unlike Replicator, which requires you to specify available sets explicitly, Blocks auto-discovers all block fieldsets — no configuration needed.

Configuration Options

No type-specific options. Simply add a blocks field to a blueprint and all fieldsets with is_block: true become available as block types.

Features

  • Auto-discovers all fieldsets with is_block: true
  • Same editing experience as Replicator (add, reorder, collapse, delete blocks)
  • No explicit sets configuration required
  • Adding a new fieldset with is_block: true makes it immediately available

Supported Validation

required

Value Format

Stored identically to Replicator — an array of objects with _type identifying the fieldset:

blocks:
  - _type: hero
    title: Welcome to Madori
    subtitle: A flat-file CMS for Next.js
  - _type: html_embed
    html: '<iframe src="https://example.com"></iframe>'
    caption: Demo video

Example

- handle: page_blocks
  field:
    type: blocks
    display: Page Blocks

No options.sets needed — all is_block: true fieldsets are included automatically.


Hidden

A hidden field that is not displayed in the Control Panel interface. Used for internal metadata, computed values, or system-managed data that editors should not modify directly.

Configuration Options

No type-specific options. Typically used with a default value.

Supported Validation

None. Hidden fields are not validated since editors cannot interact with them.

Value Format

Stored as any type (unknown). Commonly a string.

Example

- handle: internal_id
  field:
    type: hidden
    default: auto-generated

- handle: schema_version
  field:
    type: hidden
    default: "1.0"

Common Patterns

Combining Validation Rules

Multiple validation rules can be applied to a single field:

- handle: email
  field:
    type: text
    display: Email Address
    required: true
    validate:
      - required
      - email
      - max:254

Conditional Fields with Visibility

Show a field only when another field has a specific value:

- handle: has_cta
  field:
    type: toggle
    display: Show Call to Action
    default: false

- handle: cta_text
  field:
    type: text
    display: CTA Button Text
    visibility:
      field: has_cta
      operator: equals
      value: true

- handle: cta_url
  field:
    type: text
    display: CTA Link URL
    validate:
      - url
    visibility:
      field: has_cta
      operator: equals
      value: true

SEO Fields Group

A common pattern for page-level SEO metadata:

- handle: meta_title
  field:
    type: text
    display: Meta Title
    validate:
      - max:60
    options:
      placeholder: Override page title for search engines

- handle: meta_description
  field:
    type: text
    display: Meta Description
    validate:
      - max:160
    options:
      placeholder: Brief description for search results

- handle: og_image
  field:
    type: asset
    display: Social Share Image
    options:
      max_files: 1

Blog Post Blueprint

A complete example combining multiple field types:

tabs:
  main:
    display: Content
    fields:
      - handle: title
        field:
          type: text
          display: Title
          required: true
          validate:
            - required
            - max:120
      - handle: slug
        field:
          type: slug
          required: true
      - handle: published_at
        field:
          type: date
          display: Publish Date
          required: true
      - handle: featured_image
        field:
          type: asset
          display: Featured Image
          options:
            max_files: 1
      - handle: body
        field:
          type: tiptap
          display: Body
          required: true
      - handle: categories
        field:
          type: taxonomy
          display: Categories
      - handle: featured
        field:
          type: toggle
          display: Featured
          default: false
  seo:
    display: SEO
    fields:
      - handle: meta_title
        field:
          type: text
          display: Meta Title
          validate:
            - max:60
      - handle: meta_description
        field:
          type: text
          display: Meta Description
          validate:
            - max:160

Field Type Quick Reference

Type Stores Best For
text string Titles, names, short text
slug string URL identifiers
markdown string Long-form plain Markdown
tiptap object (JSON) Rich text with formatting
number number Prices, counts, measurements
toggle boolean On/off flags
select string Single choice from options
multiselect string[] Multiple choices from options
date string (YYYY-MM-DD) Dates
asset string or string[] Files and images
entries string[] Cross-references to entries
taxonomy string[] Term assignments
replicator object[] Flexible page blocks (explicit sets)
blocks object[] Page blocks (auto-discovers is_block fieldsets)
grid object[] Tabular repeatable data
yaml string Arbitrary structured data
code string Code snippets, embeds
hidden any Internal metadata