いま読んでいるこのサイトは、Cloudflare が2026年4月に公開した CMS「EmDash」で作られています。Astro をベースにした TypeScript 製の CMS で、コンテンツは Cloudflare の D1(データベース)に、画像は R2(ストレージ)に保存され、Cloudflare Workers 上で動きます。「WordPress の精神的後継」を掲げる、まだ v0.x のベータプロダクトです。

akareco では「企画から運用まで、まるごと引き受ける」ことを掲げています。であれば、自分たちのサイトこそ新しい技術で作って、その知見を持っておきたい。そう考えて、あえてベータの EmDash を本番投入しました。結果として半日ほどで公開まで漕ぎ着けられましたが、道中はいくつもの落とし穴がありました。この記事では、これから EmDash や Cloudflare スタックで CMS を作る方に向けて、実際に踏んだ点と回避策を残しておきます。

なぜ EmDash を選んだか

小規模なサイトに CMS を入れるとき、悩ましいのは「運用コスト」と「所有権」です。WordPress は保守に月数千〜数万円かかりがちで、プラグイン起因のセキュリティ問題も定番の悩みです。

EmDash は Cloudflare の無料枠に載せられる設計で、小規模なら運用費はほぼ0円(プラグインを使う場合のみ Workers の有料プラン=月$5〜)。しかもデータはすべて自分の Cloudflare アカウントに残ります。「低コストで、所有権も手元に残る CMS」という点が、私たちの方針と噛み合っていました。

踏んだ落とし穴

1. パスキーは「初回デプロイ前」にドメインを固定する(最重要)

EmDash の管理画面はパスキー(WebAuthn)でログインします。パスキーは登録したドメインに紐づく仕様なので、動作確認用の *.workers.dev のURLでセットアップウィザードを済ませてしまうと、本番ドメインに切り替えた瞬間にログインできなくなります。

回避策はシンプルで、本番ドメインを最初に設定してからデプロイすること。

// astro.config.mjs
emdash({
  siteUrl: "https://example.com", // 先に本番ドメインを指定
  // ...
})

もし踏んでしまっても復旧はできます(データベースの認証系テーブルを消してウィザードをやり直す)。ただ、認証の要である siteUrl を後回しにすると事故るので、最初に決め切るのが正解です。

2. 自動seedはスキーマだけ。中身は別途入れる

EmDash は seed.json にサイトの構造(コレクション定義・メニュー・設定)と初期コンテンツを書けます。ただし空のデータベースへの初回アクセスで自動的に適用されるのはスキーマ側だけで、記事や固定ページの「中身」は入りません。

中身は、セットアップウィザードで「デモコンテンツを適用」を選ぶか、CLI(emdash seed)で明示的に流し込みます。ここを勘違いすると「seedに書いたのにトップが空っぽ」で悩みます。

3. プラグインを使うなら有料プラン

EmDash の目玉は「プラグインを隔離環境で安全に動かす」仕組みですが、これは Cloudflare の Dynamic Worker Loaders に依存しており、Workers の有料プラン(月$5〜)が必要です。プラグインを使わない構成なら無料枠のまま公開できます。「まず無料で立ち上げて、必要になったら$5」と切り分けられるのは、クライアントワークでも提案しやすいポイントです。

4. ローカルCLIを使うにはネイティブモジュールの許可が要る

emdash の CLI(記事投入やseed適用)はローカルで SQLite を叩くため better-sqlite3 が必要ですが、テンプレートの初期設定ではこのビルドがブロックされています。pnpm-workspace.yaml で許可してリビルドすれば通ります。エラーメッセージだけ見ると原因が分かりにくいので、知っていると数十分節約できます。

5. 「Astro を知っていれば書ける」は本当

ここは落とし穴ではなく良かった点です。EmDash は Astro の統合として動くので、固定ページは普通の Astro ページとして書けます。このサイトの問い合わせフォームも、特別な仕組みではなく Astro のサーバー処理で受けて Slack に飛ばしているだけです。CMS が管理するのは「更新頻度の高い中身(=このコラムなど)」だけで、レイアウトや構造はコードで持つ、という役割分担がきれいに効きました。

(余談ですが、Astro v6 以降は環境変数の取り方が変わっていて、Astro.locals.runtime.env は廃止され import { env } from "cloudflare:workers" になっています。移行時にここで一度つまずきました。)

それで、どうだったか

ベータ版という不安はありましたが、「Astro+Cloudflare を理解していれば、半日で本番CMSを一気通貫で立ち上げられる」というのが率直な感想です。運用費はほぼ0円、データは自分のもの。小〜中規模のオウンドメディアやコーポレートサイトには、十分に現実的な選択肢になってきたと感じます。

一方で、非エンジニアが単独で運用するには管理画面の作り込み(特に日本語まわり)がまだ発展途上で、この辺りは今後の検証課題です。

akareco では、こうして自分たちで作って運用してみた技術を、そのままクライアントの受託開発に持ち込んでいます。「新しめの技術だけど、実際に本番で動かしてハマりどころまで把握している」——その状態で提案できるのが、一気通貫でやることの強みだと思っています。

作りたいものや、技術選定の相談があれば、お問い合わせからお気軽にどうぞ。