Collections
Define field types and validation.
Your content model is the set of collections and fields your site stores. You define it in the admin panel or with the CLI, change it whenever you need to, and optionally generate TypeScript types from it. This page covers how to work with it.
A collection is a type of content (posts, products, authors). Each collection has fields you define (a title, a body, a price). Every entry also has system fields EmDash manages for you.
You create and edit collections and fields visually in the admin panel under Content Types, or with the CLI. Changes take effect immediately, and a non-developer can do it.
In addition to the fields you define, every entry has these, always present:
| Field | Purpose |
|---|---|
id | Stable unique identifier |
slug | URL-safe identifier, unique per locale |
status | draft, published, or scheduled |
author_id | The user who created the entry |
created_at / updated_at / published_at | Timestamps |
deleted_at | Set on soft delete; the row is kept |
version | Increments on each save |
Deleting an entry is a soft delete: it can be restored.
You can add, rename, remove, or retype a field on a live collection at any time, through the admin panel or the CLI. Existing content is preserved.
Type generation is optional but recommended. Generate types from your current model:
npx emdash typesThis writes .emdash/types.ts with an interface per collection and typed query overloads, so getEmDashCollection("posts") returns fully typed entries:
export interface Post { title: string; content: PortableTextBlock[]; excerpt?: string;}
declare module "emdash" { export function getEmDashCollection( type: "posts", ): Promise<{ entries: ContentEntry<Post>[]; error?: Error }>;}Re-run the command after changing the model to keep types in sync.
Both workflows change the same model.
A non-developer uses the admin panel:
A developer can use the CLI to generate types and move the model between environments:
npx emdash types # generate TypeScript typesnpx emdash export-seed > seed.json # export the model as a seed fileA seed file is a JSON description of collections, taxonomies, and menus. Templates ship one, and you can export your own for version control or to set up another environment.
{ "version": "1", "collections": [ { "slug": "posts", "label": "Blog Posts", "labelSingular": "Post", "supports": ["drafts", "revisions", "preview"], "fields": [ { "slug": "title", "type": "string", "required": true }, { "slug": "content", "type": "portableText" } ] } ], "taxonomies": [{ "name": "category", "label": "Categories", "hierarchical": true }], "menus": [{ "name": "primary", "label": "Primary Navigation" }]}Applying a seed is idempotent, so it is safe to re-run:
import { applySeed, validateSeed } from "emdash/seed";import seedData from "./.emdash/seed.json";
const { valid, errors } = validateSeed(seedData);await applySeed(db, seedData, { includeContent: true, onConflict: "skip" });See Seed file format for the full schema.
Collections
Define field types and validation.
Admin Panel
See the admin panel.
Seeding
Set up sites with seed files.