Skip to content

Section schema reference

Every built-in section is defined with defineSection({ type, schema, ... }). The type string is the discriminator stored in each section’s JSON file; the Zod schema is the source of truth for content shape.

Each block on disk has this outer envelope:

{
id: string; // unique within the site
type: string; // section type key (see below)
content: { ... }; // type-specific content
options?: { ... }; // type-specific display options
layout?: {
colSpan?: number; // only meaningful inside a container
};
}

Source: packages/primitives/src/components/sections/LinkHeading/index.tsx

A top-level section heading. Generates a navigation anchor.

FieldTypeRequiredNotes
content.headingstringYesHeading text

Source: packages/primitives/src/components/sections/SubHeading/index.tsx

A second-level heading. Excluded from the top-level nav by default.

FieldTypeRequiredNotes
content.headingstringYesHeading text
content.excludeFromNavbooleanNoWhen true, omits this heading from nav generation

Source: packages/primitives/src/components/sections/SubSubHeading/index.tsx

A third-level heading. Never appears in top-level nav.

FieldTypeRequiredNotes
content.headingstringYesHeading text
content.excludeFromNavbooleanNoWhen true, omits this heading from nav generation

Source: packages/primitives/src/components/sections/Prose/index.tsx

A rich-text body block. Content is stored as sanitized HTML.

FieldTypeRequiredNotes
content.bodystringYesHTML string; listed in richTextFields and sanitized on save

Source: packages/primitives/src/components/sections/Media/index.tsx

A single image or video block.

FieldTypeRequiredNotes
content.refSingleMediaReferenceYesImage or video reference (see below)
content.linkLinkValueNoOptional link wrapping the media
FieldTypeRequiredNotes
type"image"YesDiscriminator
imageIdstringYesMedia manifest ID; defaults to ""
captionstring | string[]NoCaption text
backgroundstringNoBackground color hint
invertFromstringNoTheme at which to invert the image
borderbooleanNoRender a border
objectFit"cover" | "contain"NoCSS object-fit

Inherits all "image" fields, plus:

FieldTypeRequiredNotes
type"video"YesDiscriminator
posterstringNoPoster image URL
autoplaybooleanNoAuto-play on load
loopbooleanNoLoop playback
mutedbooleanNoMuted by default
FieldTypeRequiredNotes
options.squarebooleanNoForce square aspect ratio
options.showCaptionbooleanNoRender the caption below the media
options.borderbooleanNoRender a border
options.objectFit"cover" | "contain"NoCSS object-fit; defaults to "contain"

Source: packages/primitives/src/components/sections/Button/index.tsx

A call-to-action button.

FieldTypeRequiredNotes
content.textstringYesButton label
content.linkLinkValueNoDestination; see LinkValue below
content.downloadbooleanNoAdds download attribute to the rendered anchor

Source: packages/primitives/src/components/sections/Container/index.tsx

A layout wrapper that holds child blocks in a CSS grid. Nesting is capped at depth 2 (a container may hold leaves, not other containers).

FieldTypeRequiredNotes
content.columnsnumber (int, 1–6)YesNumber of grid columns; defaults to 1
content.flow"row" | "column"YesGrid auto-flow direction; defaults to "row"
content.childrenSection[]YesChild blocks (any section type, each with an id and optional layout.colSpan); defaults to []
content.childDefaultsRecord<string, unknown>NoDefault options applied to children added via the editor

Child blocks may carry layout.colSpan (int ≥ 1). If colSpan exceeds columns, it is clamped to columns on the next parse.


Source: packages/primitives/src/components/sections/Spacer/index.tsx

An empty vertical gap. No content fields.

FieldTypeRequiredNotes
content{}Always an empty object

Source: packages/primitives/src/components/sections/Colors/index.tsx, schema.ts

A brand color palette display.

FieldTypeRequiredNotes
content.colorsColorItem[]YesOne entry per color
FieldTypeRequiredNotes
namestringNoDisplay name for the color
spacesColorSpace[] (min 1)YesOne or more color space representations

At least one field must be present.

FieldTypeRequiredNotes
hexstringNo6-digit hex (#rrggbb)
rgbstringNoFree-form RGB string
cmykstringNoFree-form CMYK string
pantonestringNoPantone name or code
FieldTypeRequiredNotes
options.labelstringNoSection label text
options.columnsnumber (int, 2–4)NoDisplay columns
options.collapsingbooleanNoEnable collapsing layout
options.showLabelbooleanNoRender the label; defaults to true in settings

Source: packages/primitives/src/components/sections/IconList/index.tsx

A list of labelled items, each with optional icon and do/don’t marker.

FieldTypeRequiredNotes
content.itemsIconListItem[]YesOne entry per list item
FieldTypeRequiredNotes
labelstringYesShort label
textstringYesBody text
iconstringNoIcon identifier
dodont"do" | "dont"NoDo/Don’t marker
FieldTypeRequiredNotes
options.iconstring | nullNoDefault icon for all items
options.showLabelbooleanNoRender item labels
options.stackTextbooleanNoStack label + text vertically

Source: packages/primitives/src/components/sections/DoDontMedia/index.tsx

A media block with an explicit Do / Don’t annotation. Designed to be used inside a container alongside other dodont_media blocks.

FieldTypeRequiredNotes
content.refSingleMediaReferenceYesImage or video reference; same shape as media
content.dodont"do" | "dont"YesAnnotation shown on the block
content.linkLinkValueNoOptional link wrapping the media
FieldTypeRequiredNotes
options.squarebooleanNoForce square aspect ratio
options.showCaptionbooleanNoRender the caption below the media
options.borderbooleanNoRender a border
options.objectFit"cover" | "contain"NoCSS object-fit; defaults to "contain"

Defined in packages/primitives/src/schemas/link.ts. A discriminated union on kind.

External link (kind: "external"):

FieldTypeNotes
kind"external"
hrefstringMust be empty, relative, http(s)://, or mailto:; dangerous schemes (javascript:, data:) are rejected
target"_self" | "_blank"

Internal link (kind: "internal"):

FieldTypeNotes
kind"internal"
pageIdstringID of the target page
anchorSectionIdstring | null | undefinedOptional in-page anchor
target"_self" | "_blank"