Skip to content

Field Types Reference

EmDash supports 15 field types for defining content schemas. Each type maps to a SQLite column type and provides appropriate admin UI.

TypeSQLite ColumnDescription
stringTEXTShort text input
textTEXTMulti-line text
numberREALDecimal number
integerINTEGERWhole number
booleanINTEGERTrue/false
datetimeTEXTDate and time
selectTEXTSingle choice from options
multiSelectJSONMultiple choices
portableTextJSONRich text content
imageTEXTImage reference
fileTEXTFile reference
referenceTEXTReference to another entry
jsonJSONArbitrary JSON data
slugTEXTURL-safe identifier

Short, single-line text. Use for titles, names, and short values.

{
slug: "title",
label: "Title",
type: "string",
required: true,
validation: {
minLength: 1,
maxLength: 200,
},
}

Validation options:

  • minLength — Minimum character count
  • maxLength — Maximum character count
  • pattern — Regex pattern to match

Widget options:

  • None specific

Multi-line plain text. Use for descriptions, excerpts, and longer plain text.

{
slug: "excerpt",
label: "Excerpt",
type: "text",
options: {
rows: 3,
},
}

Validation options:

  • minLength — Minimum character count
  • maxLength — Maximum character count

Widget options:

  • rows — Number of rows in textarea (default: 3)

URL-safe identifier. Automatically generated from another field or manually entered.

{
slug: "slug",
label: "URL Slug",
type: "slug",
required: true,
unique: true,
}

Slugs are automatically sanitized: lowercased, spaces replaced with hyphens, special characters removed.

Decimal number. Use for prices, ratings, and measurements.

{
slug: "price",
label: "Price",
type: "number",
required: true,
validation: {
min: 0,
max: 999999.99,
},
}

Validation options:

  • min — Minimum value
  • max — Maximum value

Stored as SQLite REAL (64-bit floating point).

Whole number. Use for quantities, counts, and order values.

{
slug: "quantity",
label: "Quantity",
type: "integer",
defaultValue: 1,
validation: {
min: 0,
max: 1000,
},
}

Validation options:

  • min — Minimum value
  • max — Maximum value

Stored as SQLite INTEGER.

True or false. Use for toggles and flags.

{
slug: "featured",
label: "Featured",
type: "boolean",
defaultValue: false,
}

Stored as SQLite INTEGER (0 or 1).

Date and time value. Stored in ISO 8601 format.

{
slug: "publishedAt",
label: "Published At",
type: "datetime",
}

Validation options:

  • min — Minimum date (ISO string)
  • max — Maximum date (ISO string)

Storage format: 2025-01-24T12:00:00.000Z

Single selection from predefined options.

{
slug: "status",
label: "Status",
type: "select",
required: true,
defaultValue: "draft",
validation: {
options: ["draft", "published", "archived"],
},
}

Validation options:

  • options — Array of allowed values (required)

Stored as TEXT containing the selected value.

Multiple selections from predefined options.

{
slug: "tags",
label: "Tags",
type: "multiSelect",
validation: {
options: ["news", "tutorial", "review", "opinion"],
},
}

Validation options:

  • options — Array of allowed values (required)

Stored as JSON array: ["news", "tutorial"]

Rich text content using Portable Text format. Supports headings, lists, links, images, and custom blocks.

{
slug: "content",
label: "Content",
type: "portableText",
required: true,
}

Stored as JSON array of Portable Text blocks:

[
{
"_type": "block",
"style": "normal",
"children": [{ "_type": "span", "text": "Hello world" }]
}
]

Plugins can add custom block types (embeds, widgets, etc.) to the editor. These appear in the slash command menu and are automatically rendered on the site. See Creating Plugins — Portable Text Block Types.

Reference to an uploaded image. Includes metadata like dimensions and alt text.

{
slug: "featuredImage",
label: "Featured Image",
type: "image",
options: {
showPreview: true,
},
}

Widget options:

  • showPreview — Show image preview in admin (default: true)

Stored value:

{
"id": "01HXK5MZSN...",
"url": "https://cdn.example.com/image.jpg",
"alt": "Description",
"width": 1920,
"height": 1080
}

Reference to an uploaded file (documents, PDFs, etc.).

{
slug: "document",
label: "Document",
type: "file",
}

Stored value:

{
"id": "01HXK5MZSN...",
"url": "https://cdn.example.com/doc.pdf",
"filename": "report.pdf",
"mimeType": "application/pdf",
"size": 102400
}

Reference to another content entry.

{
slug: "author",
label: "Author",
type: "reference",
required: true,
options: {
collection: "authors",
},
}

Widget options:

  • collection — Target collection slug (required)
  • allowMultiple — Allow multiple references (default: false)

Single reference stored value:

"01HXK5MZSN..."

Multiple references stored value:

["01HXK5MZSN...", "01HXK6NATS..."]

Arbitrary JSON data. Use for complex nested structures, third-party integrations, or data without a fixed schema.

{
slug: "metadata",
label: "Metadata",
type: "json",
}

Stored as-is in SQLite JSON column.

All fields support these common properties:

PropertyTypeDescription
slugstringUnique identifier (required)
labelstringDisplay name (required)
typeFieldTypeField type (required)
requiredbooleanRequire a value (default: false)
uniquebooleanEnforce uniqueness (default: false)
defaultValueunknownDefault value for new entries
validationobjectType-specific validation rules
widgetstringCustom widget override
optionsobjectWidget configuration
sortOrdernumberDisplay order in admin

These slugs are reserved and cannot be used:

  • id
  • slug
  • status
  • author_id
  • created_at
  • updated_at
  • published_at
  • deleted_at
  • version

Import field types for programmatic use:

import type { FieldType, Field, CreateFieldInput } from "emdash";
const fieldTypes: FieldType[] = [
"string",
"text",
"number",
"integer",
"boolean",
"datetime",
"select",
"multiSelect",
"portableText",
"image",
"file",
"reference",
"json",
"slug",
];