Skip to content
Browse documentation
On this page

The CMS

Manage the marketing site, blog and docs in EmDash, and keep the seed in step.

The public site is content in EmDash. Editors work at /_emdash/admin; the pages, posts and docs render through Astro routes in src/pages/.

What EmDash manages

Collection

Renders at

Contains

Pages

/ and /<slug>

Home, pricing, about, contact, legal pages. Each is a stack of marketing blocks

Posts

/blog, /blog/<slug>

Blog posts with tags, bylines and a featured image

Docs

/docs, /docs/<slug>

These docs, grouped into sections

EmDash also holds the site title, tagline, logo, menus and SEO settings, and media uploads in the MEDIA R2 bucket.

Where it runs

EmDash uses its own D1 database (CMS_DB), separate from the app's (DB). It applies its own migrations on the first request after an upgrade. Don't query CMS_DB from Drizzle; use EmDash's query functions such as getEmDashCollection and getEmDashEntry.

The seed file

seed/seed.json defines the collections, fields, block types, taxonomies, menus, settings and starter content. EmDash applies it to an empty database, so it's what a fresh install starts with. Changing it doesn't change a site that's already running.

Editing from the command line

The EmDash CLI edits content through the site's API:

export EMDASH_URL=https://yourdomain.com
bunx emdash login
bunx emdash content get pages about --raw --json > about.json
bunx emdash content update pages about --file about-new.json --rev <rev from get>

--rev stops you overwriting changes you haven't seen. Updates publish unless you pass --draft.

Docs content

These docs are written as Markdown in seed/docs/. Each file has title, summary, section and an optional order in its frontmatter. Two containers turn into doc blocks:

:::steps
### First step
What to do.
:::

:::tip Optional title
Body text.
:::

:::note, :::caution and :::danger work like :::tip. Text inside a container is shown as typed, without Markdown.

node scripts/sync-docs.mjs --seed                              # write the docs into seed/seed.json
node scripts/sync-docs.mjs                                     # load them into the local CMS
node scripts/sync-docs.mjs --url https://yourdomain.com        # load them into the live site
node scripts/sync-docs.mjs --url https://yourdomain.com --update  # also overwrite existing docs

The live sync uses the token from emdash login. Without --update, docs that already exist are left alone so edits made in the admin are kept.

Upgrading EmDash

Run npx upgrade-emdash@latest, then work through the .emdash/UPGRADE.md it writes. Check for pending migrations before you deploy:

bunx emdash migrate --status --d1 <your-cms-database> --wrangler-config wrangler.jsonc