Skip to content

EmDash CMS edition

Some themes are sold in two editions. The static edition is the theme as it ships: content lives in src/config/site.ts and in Markdown, and every change is a commit and a rebuild. The EmDash CMS edition is the same design with a content system behind it: an admin panel at /_emdash/admin where an editor changes copy, images, pricing, projects, services, posts and menus without touching the repository, plus click-to-edit on the live site.

It runs on Cloudflare Workers, with D1 for content and R2 for uploads. You deploy it once, hand over the login, and your client edits from then on.

Terminal window
npm install
cp .env.example .env
npx emdash secrets generate
npm run setup
npm run dev

pnpm and yarn work the same way: pnpm install then pnpm run setup, or yarn then yarn setup. Whatever you pick, use run setup, not a bare pnpm setup, which is a pnpm built-in.

  • npx emdash secrets generate prints a key on its first line. Paste it into .env as EMDASH_ENCRYPTION_KEY=<that key> before npm run setup, or the first run has nothing to encrypt with.
  • npm run setup creates the local SQLite database, applies the schema, and seeds the theme’s demo content, so the panel opens with the same pages you saw in the preview.
  • The site runs on the usual dev URL. The panel is at /_emdash/admin.

The first visit to /_emdash/admin opens a setup wizard: you create the owner account and register a passkey. There is no password to store. Keep that passkey, or add a second one for the client before you hand the site over.

SectionWhat lives there
PagesHome, Studio, Contact, Work, Services, Journal, Privacy, Terms
JournalArticles, with cover image, category, date and body
ServicesService entries, their deliverables, process steps and detail copy
WorkProjects, their images, metadata and long-form case-study body
MediaEvery uploaded image, stored in R2 and reusable across entries
MenusNavigation and footer links, order included
General settingsSite name, contact details, social links, SEO defaults, theme color

Pages is one collection: each route is an entry, and its sections are fields inside that entry. So the homepage hero, the pricing cards and the closing call to action are edited on the Home entry rather than scattered across the panel.

  1. Sign in at /_emdash/admin.
  2. Choose View Site in the panel.
  3. Flip the Edit toggle in the toolbar that appears on the site.

Editable text becomes clickable in place. Change it where it sits, and the panel saves it to the same entry you would have opened by hand. It is the fastest path for copy fixes, and the one to show a client first.

The CMS edition follows the same i18n model as the static edition:

  1. Register the locale in src/i18n/config.ts.
  2. Restart the dev server so the new routes are generated.
  3. Open any entry in the panel and use Translate to write that locale’s version.

Translations are stored per entry, not as one big file, so an untranslated entry falls back to the source language instead of blanking the page. The full checklist is on Add a language.

When you pull a theme update that changes the content schema, apply it without wiping the content:

Terminal window
npm run setup:update

When you want a clean slate instead - a new project from the same theme, or a local database you have edited into a corner - delete the local database and run the full setup again:

Terminal window
rm -rf data.db data.db-shm data.db-wal uploads
npm run setup

That command is local only. Never point it at a production database.

Terminal window
wrangler d1 create <your-db-name>
wrangler r2 bucket create <your-bucket-name>

Both commands print an id. Put them into wrangler.jsonc, in the d1_databases and r2_buckets blocks, then set the production encryption key and deploy:

Terminal window
wrangler secret put EMDASH_ENCRYPTION_KEY
npm run deploy:cloudflare

The deploy applies the schema to the remote database and seeds it on first run. Open https://<your-site>/_emdash/admin and complete the setup wizard again there: the local owner account is not copied to production.

A site of this size stays inside Cloudflare’s free tier for Workers, D1 and R2. You need a Cloudflare account and the wrangler CLI, nothing else.

  • EmDash is on a 0.x version and the theme pins the exact version it was built against. Upgrade deliberately, one version at a time, and run npm run setup:update after.
  • The Bylines and Comments sections exist in the panel but the theme does not render them. Leave them empty.
  • The related-projects field on a project is a multi-select over a fixed list. When you add a new project, extend that list in the admin schema, or the new project cannot be selected as related from another one.