EmDash CMS. Setting up and using EmDash CMS with your Lexington theme

Some Lexington themes are available with EmDash CMS integration. These variants ship as a single Astro project with a built-in admin at /_emdash/admin, so editors can manage content without a separate Studio deploy: while developers keep Astro performance and full control of the front end.

Local development uses Node.js and SQLite. Production deploys to Cloudflare Workers with D1 and R2.


Quick Start (Local)

The whole flow: install, seed sample content, start the site and CMS:

EmDash quick start: npm install, npm run setup, npm run dev

After downloading or forking your theme:

bash
npm install
npm run setup    # sample content + images (first time)
npm run dev

Each EmDash theme runs on its own dev port (for example, Semplice uses 4335), so it never conflicts with other Astro projects. The dev server prints the exact URLs when it starts:

  • Websitehttp://localhost:<port>
  • CMS adminhttp://localhost:<port>/_emdash/admin

Or open admin with the dev login shortcut:

bash
npm run admin

Edit content in admin, click Save, then Publish. Drafts do not appear on the site until published.


Prerequisites


Editing Content

  1. Go to /_emdash/admin (or run npm run admin locally).
  2. Open a collection: posts, podcast episodes, jobs, help articles, etc. (depends on your theme).
  3. Edit fields and upload media as needed.
  4. Click Save, then Publish.
  5. Refresh the website to see live changes.

Navigation is CMS-managed in most EmDash themes:

  1. Admin → Appearance → Menus
  2. Edit primary, company, footer, or other seeded menu keys
  3. Publish changes

EmDash themes with LiveSearch use the built-in API at /_emdash/api/search. Press ⌘K / Ctrl+K on the site to open search.

Site settings

Admin → Settings → Site Settings: set site URL, SEO defaults, and social handles. See your theme’s SEO.md for details.


Deploy to Cloudflare

The key steps on camera: store the encryption key, verify the build, deploy:

Deploying to Cloudflare: wrangler secret put, npm run check:cf, wrangler deploy

Complete this checklist before going live. The theme ships with placeholders you must replace:

What File Action
Site URL astro.config.shared.mjs Set site to your production URL
Site URL (CMS) Admin → Settings → Site Settings Set the same URL after deploy
R2 public URL astro.config.cloudflare.mjs Uncomment and set publicUrl on the r2() adapter
KV cache id wrangler.jsonc Replace REPLACE_WITH_KV_NAMESPACE_ID

Step 1: Set your domain

  1. astro.config.shared.mjs: set site (e.g. https://example.com).
  2. wrangler.jsonc: set name to your Worker name.
  3. After deploy, set the same URL in admin → Settings → Site Settings.

Step 2: Encryption key (required)

EmDash encrypts sensitive data at rest. Generate once and store a backup.

bash
npx wrangler login
npx emdash secrets generate
npx wrangler secret put EMDASH_ENCRYPTION_KEY

Paste the generated key when prompted.

KV caches menus, settings, and queries for faster pages.

bash
npx wrangler kv namespace create site-cache

Copy the returned id into wrangler.jsonckv_namespaces[0].id.

Local dev uses in-memory cache automatically.

Step 4: R2 public media URL (required for images)

CMS images are stored in R2 in production:

  1. Cloudflare dashboard → R2 → your media bucket → Settings → Public access
  2. Uncomment and set publicUrl in astro.config.cloudflare.mjs:
js
storage: r2({
  binding: "MEDIA",
  publicUrl: "https://media.yourdomain.com",
}),
  1. Redeploy: npm run deploy

See EmDash Cloudflare deployment.

Step 5: Build and deploy

bash
npm run check:cf   # optional: verify production build
npm run deploy

Step 6: Complete Setup Wizard

Open https://<your-worker>.workers.dev/_emdash/admin and complete the Setup Wizard. You’ll create a real admin login with a passkey; the local dev login shortcut doesn’t exist in production.

Seed content runs on the live Worker; your local SQLite database is not deployed.

Step 7: Custom domain

Cloudflare dashboard → Workers & Pages → your worker → Custom Domains → Add.

Update site in astro.config.shared.mjs and Site URL in admin to match.


Project Structure

plaintext
/
├── .emdash/
│   ├── seed.json       # Content model + sample entries
│   └── uploads/        # Seeded media
├── src/
│   ├── components/
│   ├── layouts/
│   ├── lib/            # CMS helpers (menus, settings, etc.)
│   ├── pages/
│   └── styles/
├── scripts/
│   ├── apply-media.mjs # Links seed images (part of setup)
│   └── clean.sh        # Distribution cleanup
├── astro.config.mjs           # Local dev (Node + SQLite)
├── astro.config.cloudflare.mjs  # Production (Workers + D1 + R2)
├── astro.config.shared.mjs    # Shared site URL and settings
└── wrangler.jsonc             # Cloudflare Worker config

Content types and routes vary by theme. Check .emdash/seed.json and src/content.config.ts in your theme for the exact schema.


Customization

Styling

Edit src/styles/global.css for global styles. Lexington EmDash themes use Tailwind CSS v4.

Content model

The CMS schema lives in .emdash/seed.json. After changing fields or collections, re-seed locally if needed:

bash
npm run setup

For production schema changes, follow EmDash documentation for migrations and deploy steps.

Portable Text

Rich text fields render through Portable Text components in your theme. Extend block types in the admin schema and matching Astro components on the front end.


Troubleshooting

“Cannot find module” errors?

bash
npm install

Empty site / no posts?

bash
npm run setup
npm run dev

Images missing after setup?

bash
node scripts/apply-media.mjs

(or run npm run setup, which includes this step)

Edits not showing on the website?

  • Click Publish in admin after Save (not just Save).
  • Hard-refresh the browser.

Admin save errors or dev server stuck?

bash
npm run stop
npm run dev

Port already in use?

bash
npm run stop
npm run dev

Images broken in production?

  • Confirm R2 public access is enabled.
  • Set publicUrl in astro.config.cloudflare.mjs and redeploy.

Slow pages in production?

  • Create a KV namespace and set its id in wrangler.jsonc.

Useful Commands

Command Description
npm install Install dependencies
npm run setup Seed content + link sample images
npm run dev Start local site + CMS (SQLite)
npm run admin Open admin with local dev login
npm run stop Stop the theme’s dev server
npm run check:cf Verify production build (no deploy)
npm run deploy Build and deploy to Cloudflare Workers
npm run clean Remove node_modules, caches, local DB before sharing

Resources