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).

Fields support read and update access rules:

import { hasRole } from "../core/define";
summary: fields.text({
access: {
read: hasRole("admin"), // hidden from non-admins
},
}),
seoDescription: fields.text({
access: {
update: hasRole("admin"), // read-only for non-admins
},
}),
RuleEffect in admin UIEffect on save
readField is completely hiddenField excluded from response
updateField is rendered as read-only (disabled)Field value silently preserved (changes stripped)

Both rules receive the same context as collection-level access rules: { user, doc, operation, collection }.

The admin includes optional AI features powered by the Vercel AI SDK. Add AI_PROVIDER, AI_API_KEY, and AI_MODEL to your .env to enable them. When configured, AI buttons appear automatically for:

  • Alt text generation on asset detail pages
  • SEO descriptions on post/page edit forms
  • Translation with per-field “Translate from EN” buttons that handle both plain text and rich text (preserving JSON AST structure)

Without the AI env vars, all AI buttons are hidden and no AI dependencies are loaded.