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 |
| Home, pricing, about, contact, legal pages. Each is a stack of marketing blocks |
Posts |
| Blog posts with tags, bylines and a featured image |
Docs |
| 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 docsThe 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