Change it anytime
Add, rename, remove, or retype collections and fields whenever you need to. Changes take effect immediately.
EmDash is an Astro integration. You add it to astro.config.mjs, choose a database and storage, and define content collections. This page covers the model you need to build a site. For internals (table layouts, the request path, code generation), see Architecture (internals).
┌──────────────────────────────────────────────┐│ Your Astro site ││ ││ Pages and components you write ││ │ ││ │ getEmDashCollection() / getEmDashEntry()│ ▼ ││ ┌───────────────┐ ┌────────────────┐ ││ │ Content │ │ Admin panel │ ││ │ (your data) │◄────►│ /_emdash/admin │ ││ └───────────────┘ └────────────────┘ ││ │ ││ Database (SQLite / libSQL / D1 / Postgres) ││ Media storage (local / R2 / S3) │└──────────────────────────────────────────────┘You write pages and components as normal. EmDash provides the content, an admin panel for editing it, and the database and storage behind it. Editors work in the admin panel; your pages read the same content through query functions.
You define collections and fields — in the admin panel or with the CLI — and EmDash stores content against them.
Change it anytime
Add, rename, remove, or retype collections and fields whenever you need to. Changes take effect immediately.
Editor-designed
A content editor can design the whole model through the admin UI.
Typed
Generate TypeScript types from the current model for autocomplete from query to template.
Portable
Export the model as a JSON seed file for version control, and apply it in another environment.
See the content model for how to define, change, type, and seed it.
EmDash serves content through Astro’s Live Collections at runtime, so changes an editor makes are visible immediately. You read content with two functions:
import { getEmDashCollection, getEmDashEntry } from "emdash";
const { entries: posts } = await getEmDashCollection("posts");const { entry: post } = await getEmDashEntry("posts", "my-post-slug");See Querying content for filtering, pagination, and drafts.
You pass a database and a storage backend to the integration. Everything else has a default.
import { defineConfig } from "astro/config";import emdash, { local } from "emdash/astro";import { sqlite } from "emdash/db";
export default defineConfig({ integrations: [ emdash({ database: sqlite({ url: "file:./data.db" }), storage: local({ directory: "./uploads" }), }), ],});Plugins react to content and media lifecycle events and can add admin pages, dashboard widgets, and settings. There are two formats:
See the plugin overview to choose and install plugins, or create a plugin.
Collections
Content Model
Understand the content model.
Admin Panel
See what the admin panel offers editors and admins.