bitdoze·emdash
←→ navigateG slidesF fullscreen
bitdoze.com · review + tutorial walkthrough

EM—DASH

Cloudflare's WordPress successor.
1.0 is out.

Shipped Apr 1, 2026 → 1.0 late Sep MIT · TypeScript Astro-native $0 to try · no cloud account

Two articles, one story: what EmDash is after six months — and your first site in 30 minutes.

01 · What is EmDash

One deployment.
Everything inside.

CMS + site
Astro site, admin at /_emdash/admin, REST API, media library — one app, one deploy
Portable Text
Structured JSON, not HTML blobs. TipTap editor. WordPress Gutenberg converter included
Your DB
Kysely adapters: D1 · SQLite · libSQL · Postgres. Media on R2, any S3, or local disk

Plus an MCP server in every install (~60 agent tools) and passkey-first auth. Not a page builder — Astro components own the HTML.

02 · The architecture question

Where does content live?
In the database. Queried live.

File-based collections
EmDash Live Collections
Markdown in your repo, resolved at build time
Content in DB, queried at request time
Editor publishes → rebuild (minutes)
Editor publishes → live on next request
Site is static output
Site is server-rendered — the WordPress model, on Astro
0 rebuilds on edit output: "server" is what makes it work Prerendered pages stay frozen until rebuild
03 · Six-month health check · Sep 2026

The 0.x beta is gone.
This is a real project now.

0
GitHub stars · 1.2k forks
0
npm downloads / month
0
contributors · 800+ on Discord
0 signed releases · npm provenance · SLSA 25 UI languages
04 · Production proof

The Cloudflare Blog runs on it.
Since August 12.

0 RPS
steady state · spikes above 5,000 RPS
0 RPS
DDoS absorbed at the edge — not by EmDash
~0
cache hit rate · 99.5% of static files
0
pageviews · 28 posts in 9 days (Agents Week)

Honest caveat: their stack adds KV object cache + Workers Cache + Hyperdrive. Your blog will not need that.

05 · The genuinely novel part

96% of WordPress security issues
start in plugins. EmDash's answer:

1Capability manifests — capabilities: ["content:read", "email:send"] · you approve at install, like an app store
2Sandboxed runtime — workerd child process · 128 MB · 30 s wall time · no network to undeclared hosts
3Signed decentralized registry — built on AT Protocol · same protocol as Bluesky · no one can silently rewrite a plugin's history
4Physical enforcement — not honor-system · hook timeout? logged, request continues without the plugin
06 · The honest cons

What April's critics got right.

Ecosystem catch-22registry is real but the catalog is tinyvs 60k+ WordPress plugins · still the core risk
You own the databasebackups, upgrades, media storage — the docs say so in plain wordsthe ops burden is the product
Astro-onlycontent-in-git users are explicitly not the targethard requirement
Admin UX is youngCloudflare's own migration logged editor bugs in publicbetter than v0.1, still maturing
07 · Two deploy roads

Cloudflare all-in, or a €4 VPS.

$0
Workers Free
site + admin + D1 + R2 free allowances
no sandboxed plugins
~$5/mo
Workers Paid
Worker Loader → sandboxed plugins + registry installs
most platform coupling
€4–5/mo
Your VPS
Node 22 + SQLite + Docker + S3 backups
full control, boring ownership

Official Dockerfile + compose ship in the docs — drops straight into Dokploy/Coolify. Verify pricing before it goes in a client proposal.

08 · Ops footguns · straight from the docs

Six things that will bite you.

Forget react() in configthe admin is a React app — packages alone aren't enoughadmin hangs on "Loading EmDash…"
workerd crash loopsandboxed plugins on Node5 crashes / 60 s → sandbox gives up, site keeps serving
Restore DB without the keyEMDASH_ENCRYPTION_KEY lives outside backups, on purposeplugin secrets unreadable
Migrations auto-applydefault mode runs them on first request after deployrun npx emdash migrate --check in CI first
Scheduled publishingdid not work at all until v0.19.0CF found it mid-migration — "1.0 ≠ mature"
A green /healthproves Astro serves requests — nothing morenot a deploy gate
02

Build your first site.

15–30 minutes $0 — no cloud account Node.js ≥ 22.16 SQLite on your laptop

Blank terminal → published post → your first getEmDashCollection("posts") query.

09 · Scaffold

Five prompts. That's the whole setup.

my-emdash-site — zsh
$ npm create emdash@latest
◇ Project name?        my-emdash-site
◇ Where will you deploy?  Node.js   ← SQLite + local uploads (Cloudflare = Part 3)
◇ Which template?      Blog   ← seeds Posts, Pages, sample content
◇ Package manager?    npm
◇ Install dependencies?  Yes   · 750 packages · wrote EMDASH_ENCRYPTION_KEY to .env

— E M D A S H —  v1.0.1
› Admin UI    http://127.0.0.1:4321/_emdash/admin
› MCP server  http://127.0.0.1:4321/_emdash/api/mcp
curl localhost:4321 → 200 .env is generated + gitignored — never commit it
10 · The admin panel

Setup wizard: three screens.

1Site info · title + tagline · keep "include sample content" checked
2Your account · first user is always Admin · roles: Subscriber → Contributor → Author → Editor
3Register a passkey · Touch ID / Windows Hello / security key · up to 10 per user
Content · Manage · Admin — three sidebar groups Save = private draft · Publish changes = live Passkeys are domain-bound — register a backup
11 · The demo moment

Edit → publish → live. No rebuild.

1Open the sample Welcome post
2Rename it Hello from EmDash → Save (now a draft)
3Publish changes
4Reload localhost:4321 → it's there · dev server never restarted · astro build never ran
src/pages/index.astro
---
import { getEmDashCollection } from "emdash";
const { entries: posts, error } = await getEmDashCollection("posts", { limit: 7 });
// queried at request time → next page load sees the next version
---
12 · The mental model

Four files explain the whole project.

astro.config.mjsoutput: "server" · react() · emdash({ database, storage })react() is mandatory — classic footgun
src/live.config.tssix lines: defineLiveCollection({ loader: emdashLoader() })the wire between DB and Astro
seed/seed.jsoncollections, fields, sample contentthe schema lives in git — content does not
.envEMDASH_ENCRYPTION_KEY — encrypts plugin secrets at restbackup tripod: data.db + uploads/ + key
13 · Verdict

Who should actually use it?

Astro developerwanted a DB-backed CMS on Astro? this is the defaultYesMCP + npx emdash types = agent-friendly
Agencytemplates for handoff · sandbox = support blast-radius controlConditionalnew builds you control — not WP-plugin-store clients
WordPress refugeecontent imports real: WXR / REST · CPTs → collectionsConditionaltheme + plugins are a rebuild · migrate low-stakes first
Solo bloggermarkdown-in-git stays simpler until you want admin UI, media, co-editorsConditionalearns its keep only past that threshold

Bottom line: recommended for Astro teams who want a real CMS and will own a database. Not yet a WordPress replacement for plugin-dependent sites.

bitdoze.com/emdash-cms-reviewbitdoze.com/emdash-cms-tutorial
01 / 00