Skip to content

Fields

FieldStorageAdmin Component
texttextInput or Textarea (with rows)
slugtextAuto-generated from source field
emailtextEmail input
numberinteger / realNumber input
booleaninteger (0/1)Toggle switch
datetext (ISO 8601)Date picker
selecttextSelect dropdown
richTexttext (JSON AST)Tiptap editor
imagetextImage picker with upload/browse
relationtext (reference ID)Combobox with search
arraytext (JSON)Comma-separated input
jsontext (JSON)Textarea or custom component
blockstext (JSON)Drag-and-drop block editor

All fields accept these options:

OptionTypeDescription
requiredbooleanValidate as non-empty on save
labelstringCustom label (defaults to humanized field name)
descriptionstringText shown below the label
defaultValuevariesInitial value for new documents
translatablebooleanStore per-locale in translations table
indexedbooleanAdd database index
uniquebooleanEnforce unique values
condition{ field, value }Show/hide based on another field
admin.placeholderstringInput placeholder text
admin.rowsnumberTextarea height (text fields)
admin.helpstringHelp text below the input
admin.position"sidebar"Place field in sidebar instead of content area
admin.hiddenbooleanHide from admin UI
admin.componentstringCustom admin component
fields.blocks({
types: {
hero: {
heading: fields.text({ required: true }),
body: fields.text(),
ctaLabel: fields.text(),
ctaHref: fields.text(),
},
text: {
heading: fields.text(),
content: fields.richText(),
},
faq: {
heading: fields.text(),
items: fields.json({
defaultValue: [],
admin: { component: "repeater" },
}),
},
},
});

Block sub-fields support: text, number, boolean, select, richText, image, relation, array.

The repeater component renders JSON arrays as grouped add/remove item cards.

Show/hide fields based on a select or boolean field’s value:

postType: fields.select({
options: ["article", "video", "podcast"],
}),
videoUrl: fields.text({
condition: { field: "postType", value: "video" },
}),

The value can be a string, boolean, or array of strings (matches any).

role: fields.select({
options: ["admin", "editor", "viewer"],
access: {
update: ({ user }) => user?.role === "admin",
},
}),

Fields the user can’t update are silently stripped on save.