---
title: Field Types Reference
description: Complete reference for all EmDash field types.
---

import { Aside } from "@astrojs/starlight/components";

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

## Overview

| Type           | SQLite Column | Description                |
| -------------- | ------------- | -------------------------- |
| `string`       | TEXT          | Short text input           |
| `text`         | TEXT          | Multi-line text            |
| `number`       | REAL          | Decimal number             |
| `integer`      | INTEGER       | Whole number               |
| `boolean`      | INTEGER       | True/false                 |
| `datetime`     | TEXT          | Date and time              |
| `select`       | TEXT          | Single choice from options |
| `multiSelect`  | JSON          | Multiple choices           |
| `portableText` | JSON          | Rich text content          |
| `image`        | TEXT          | Image reference            |
| `file`         | TEXT          | File reference             |
| `reference`    | TEXT          | Reference to another entry |
| `json`         | JSON          | Arbitrary JSON data        |
| `slug`         | TEXT          | URL-safe identifier        |

## Text Types

### `string`

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

```ts
{
  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

### `text`

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

```ts
{
  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)

### `slug`

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

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

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

## Number Types

### `number`

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

```ts
{
  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).

### `integer`

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

```ts
{
  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.

### `boolean`

True or false. Use for toggles and flags.

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

Stored as SQLite INTEGER (0 or 1).

## Date and Time

### `datetime`

Date and time value. Stored in ISO 8601 format.

```ts
{
  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`

## Selection Types

### `select`

Single selection from predefined options.

```ts
{
  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.

### `multiSelect`

Multiple selections from predefined options.

```ts
{
  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 Content

### `portableText`

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

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

Stored as JSON array of Portable Text blocks:

```json
[
	{
		"_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](/plugins/creating-plugins/#portable-text-block-types).

<Aside>
	Portable Text is a specification for structured rich text. See
	[portabletext.org](https://portabletext.org) for details.
</Aside>

## Media Types

### `image`

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

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

**Widget options:**

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

**Stored value:**

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

### `file`

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

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

**Stored value:**

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

## Relational Types

### `reference`

Reference to another content entry.

```ts
{
  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:**

```json
"01HXK5MZSN..."
```

**Multiple references stored value:**

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

## Flexible Types

### `json`

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

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

Stored as-is in SQLite JSON column.

<Aside type="caution">JSON fields have no validation. Use sparingly for truly dynamic data.</Aside>

## Field Properties

All fields support these common properties:

| Property       | Type        | Description                         |
| -------------- | ----------- | ----------------------------------- |
| `slug`         | `string`    | Unique identifier (required)        |
| `label`        | `string`    | Display name (required)             |
| `type`         | `FieldType` | Field type (required)               |
| `required`     | `boolean`   | Require a value (default: false)    |
| `unique`       | `boolean`   | Enforce uniqueness (default: false) |
| `defaultValue` | `unknown`   | Default value for new entries       |
| `validation`   | `object`    | Type-specific validation rules      |
| `widget`       | `string`    | Custom widget override              |
| `options`      | `object`    | Widget configuration                |
| `sortOrder`    | `number`    | Display order in admin              |

## Reserved Field Slugs

These slugs are reserved and cannot be used:

- `id`
- `slug`
- `status`
- `author_id`
- `created_at`
- `updated_at`
- `published_at`
- `deleted_at`
- `version`

## TypeScript Types

Import field types for programmatic use:

```ts
import type { FieldType, Field, CreateFieldInput } from "emdash";

const fieldTypes: FieldType[] = [
	"string",
	"text",
	"number",
	"integer",
	"boolean",
	"datetime",
	"select",
	"multiSelect",
	"portableText",
	"image",
	"file",
	"reference",
	"json",
	"slug",
];
```
