Common Field Options
The options shared by every field type, explained with examples.
These options work on every field helper (textField, photoField, selectField, ...). Type-specific options are documented on each field's page.
| Option | Type | Default |
|---|---|---|
name | string | required |
label | string | Record<locale, string> | generated from name |
required | boolean | false |
defaultValue | depends on the field | none |
order | number | none |
conditionalRules | [rule] | and(...) | or(...) | none |
adminGenerated | true | false | 'readonly' | true |
localized | boolean | false |
name
The column name, and the key used in form submissions and hook values.
textField({ name: 'first_name' })- Must be unique within the section (case-insensitive), including across field groups.
idis reserved unless the field is the section'sdb.identifier.localeis reserved.- Renaming a field renames the column:
update-sectionsdetects the change and asks whether it's a rename (data kept) or a new field.
dateRangeField is the exception: it has startName and endName instead of name.
label
Text shown above the input. When omitted, it's generated from name: underscores become spaces, camelCase is split, and words are capitalized.
name | Generated label |
|---|---|
title | Title |
published_at | Published At |
metaDescription | Meta Description |
Translate it for the admin UI with an object keyed by language code:
textField({
name: 'title',
label: { en: 'Title', ar: 'العنوان', fr: 'Titre' },
})The admin shows the label for the editor's UI language, falling back to i18n.fallbackLanguage.
required
textField({ name: 'title', required: true })- The form refuses empty values, and the server checks again on submit.
- The column is created
NOT NULL, unless the field hasconditionalRules(a hidden field has no value, so it must be nullable). - For file fields, "required" means a file must be uploaded on create; on edit, the existing file satisfies it.
checkboxFieldignoresrequired: unchecked is a valid value.
defaultValue
Pre-fills the form on the create page and becomes the column's SQL DEFAULT:
numberField({ name: 'stock', defaultValue: 0 })
checkboxField({ name: 'is_active', defaultValue: true })
selectField({ name: 'status', options: [/* ... */], defaultValue: 'draft' })
colorField({ name: 'accent', defaultValue: '#0070f3' })The type depends on the field (a string for text fields, a number for numbers, and so on). Each field page lists what it accepts.
Combined with adminGenerated: false, a default value lets you store a value editors never see. See below.
order
Sorts fields inside the form (or inside their field group), lowest first. Fields without order come after all ordered fields, in array order.
fields: [
textField({ name: 'subtitle', order: 2 }),
textField({ name: 'notes' }), // no order: rendered last
textField({ name: 'title', order: 1 }),
]
// Form: Title, Subtitle, NotesIn practice, leave order out everywhere and let the array order decide. Reach for it when fields are assembled from shared helpers. Field groups accept order too, with the same rule.
conditionalRules
Show a field only when other fields have certain values. A hidden field is not validated and not saved, so required means "required when visible".
import { and, or } from 'nextjs-cms/core/fields'
// One rule: pass a one-element array
conditionalRules: [{ field: type, condition: 'equals', value: 'external' }]
// Several rules: combine them explicitly
conditionalRules: and(
{ field: type, condition: 'equals', value: 'external' },
{ field: price, condition: 'greaterThan', value: 0 },
)
conditionalRules: or(
{ field: status, condition: 'equals', value: 'scheduled' },
{ field: status, condition: 'equals', value: 'published' },
)Conditions: equals, notEquals, contains, notContains, greaterThan, lessThan, greaterThanOrEquals, lessThanOrEquals.
The full guide, with semantics and patterns, is Conditional Fields.
adminGenerated
Controls whether editors fill in the field:
| Value | Create/edit form | Saved from the form |
|---|---|---|
true (default) | Editable input | Yes |
'readonly' | Shown as read-only text | No |
false | Hidden | No (the column's default applies) |
'readonly': show a value that something else maintains
// A counter your website updates; editors can see it but not change it.
numberField({ name: 'view_count', label: 'Views', adminGenerated: 'readonly' })false: a column editors never see
// Filled by your website or an import job, invisible in the admin.
textField({ name: 'external_ref', adminGenerated: false })
// Stored on create with a fixed value, editors never see it.
textField({ name: 'source', adminGenerated: false, defaultValue: 'cms' })For textField and slugField, a field with adminGenerated: false and a defaultValue is still written with that default on create.
Auto-increment number fields are always adminGenerated: false. The database assigns the value.
localized
Mark a field as translatable. Requires localization in cms.config.ts.
textField({ name: 'title', required: true, localized: true })
richTextField({ name: 'body', localized: true })
photoField({ name: 'banner', localized: true }) // a different banner per language- The default locale's value is stored in the section's table; other locales in
{table}_locales. - Non-localized fields are shared: editing them in any locale changes them everywhere.
- The section identifier can't be localized.
Read the Localization guide for the storage model and how to query translations.