本サイトの構成
このページで示すこと:本サイトが、EmDashをどの構成で動かし、どの手順で更新・公開・巻き戻しをしているか
本サイトは、EmDash自身で運営しています。各実践ページの「本サイトではこうしている」は、このページの構成と一致させています。構成を変えたときは、このページと対応する実践ページを更新します。
全体構成
本サイトは、Cloudflare Workers・D1・R2の上でEmDash 0.38系を動かしています。原文の取得、差分の検出、翻訳の下書き作成はGitHub Actionsと生成AIが自動で行い、公開は運営者1名が最終チェックしてから行います。
図のテキストを読む
flowchart LR
UP["公式GitHub<br/>emdash-cms/emdash"] --> GA["GitHub Actions<br/>同期・差分検出"]
NPM["npm / レジストリ"] --> GA
GA --> TR["下訳<br/>Claude API+用語集"]
TR --> API["EmDash<br/>下書きとして保存"]
API --> CMS["EmDash<br/>Workers+D1+R2"]
ED["運営者の最終チェック<br/>管理画面"] --> CMS
CMS --> WEB["公開サイト<br/>Workers Cache"]
原文の変更は自動で下書きになります。自動処理が公開状態を変えることはありません。
技術スタック
| 項目 | 採用しているもの |
|---|---|
| CMS | emdash 0.38系。@emdash-cms/cloudflare を同じ版に固定 |
| フレームワーク | Astro 6以上、output: "server" |
| 実行環境 | Cloudflare Workers(有料プラン) |
| データベース | Cloudflare D1 |
| メディア | Cloudflare R2(非公開のバケット。EmDashのメディアルート経由で配信)。画像の変換は IMAGES バインディング |
| キャッシュ | Workers Cache(前段)と、KVのオブジェクトキャッシュ |
| 配置 | Targeted PlacementでWorkerをD1の近くに置く |
| 開始テンプレート | starter-cloudflare |
| ローカルでの開発 | Node.js 22.16以上、pnpm |
| 自動化 | GitHub Actions、Claude API |
| ソースの保管 | GitHubの非公開リポジトリ |
プロジェクトは、Cloudflare版のStarterテンプレートから作成しています。
npm create emdash@latest emdash-ja -- --template cloudflare:starter --pm pnpm --yes
環境
環境は、ローカル(開発)、プレビュー、本番の3つです。D1・R2・KVは環境ごとに別に作り、プレビュー環境を本番のデータベースにはつないでいません。プレビュー環境はWranglerの名前付き環境 preview で、バインディングはすべて書き直しています。秘密の値は pnpm wrangler secret put で登録しています。
選択の理由と他の選択肢は開発環境の持ち方にあります。
Cloudflareのリソース
| リソース | バインディング名 | 用途 |
|---|---|---|
| D1 | DB |
本文、スキーマ、ユーザー |
| R2 | MEDIA |
画像・ファイル。バケットは公開せず、publicUrl を指定しない。メディアはEmDashのメディアルート(/_emdash/api/media/file)から配信する |
| KV | ― | オブジェクトキャッシュ(kvCache()) |
| Worker Loader | LOADER |
サンドボックス型プラグイン用 |
| Images | IMAGES |
画像のリサイズ・変換 |
| Cron Trigger | ― | 予約公開とプラグインの定期処理(テンプレートで毎分に設定済み) |
データベースとメディアの選択はDBとファイル置き場の選び方、実行環境の選択は実行環境の選び方にあります。
コンテンツの持ち方
コンテンツは、9つのコレクション(公式ドキュメントの翻訳、全体像・入門・実践の記事、固定ページ、リリース要約、ニュース、用語集、パッケージ一覧、テンプレート一覧、プラグイン一覧)に分けています。すべてのコレクションで、下書き、リビジョン、プレビューを有効にしています。
- 本文の正本はEmDashのデータベース(D1)だけに置き、履歴はリビジョンで持っています。翻訳結果はGitに持っていません。
- コレクションとフィールドの定義は、シードファイル(
seed/seed.json)としてGitで管理しています。公開後にスキーマを変えたときは、emdash export-seedでシードファイルに書き戻します。 - 公式ドキュメントの翻訳84ページは、
src/pages/docs/[...path].astroの1つのルートで描画しています。 - 本文の投入は、変換・投入スクリプトがEmDash CLIを呼び出し、下書きとして保存しています。管理画面での手入力はしていません。
選択の理由はコンテンツの正本の置き場所にあります。
認証と権限
管理画面は、EmDash標準のパスキー認証で守っています。Cloudflare Accessは使っていません。人のユーザーは運営者1名だけで、パスキーを複数の端末に登録しています。
| ロール | 利用者 | 受け持つこと |
|---|---|---|
| 管理者(Admin) | 運営者(1名) | 最終チェックと公開、スキーマの変更、設定 |
| 寄稿者(Contributor) | 自動処理用のユーザー(GitHub Actions、AIエージェント) | 下書きの作成・更新。公式「認証」の表では、寄稿者はコンテンツを作成できますが、公開には承認が必要です。そのため、自動処理はロールの権限として公開できません |
自動処理用のユーザーは、管理画面の招待で作り、そのユーザーの個人アクセストークン(ec_pat_ で始まるAPIトークン)でREST APIとMCPサーバーを使っています。組み込みのMCPサーバーは有効にし、AIツールから下書きを編集できるようにしています。トークンに付与する範囲は最小限にし、公開の操作は運営者が管理画面で行います。
プラグイン
| プラグイン | 形式 | 用途 |
|---|---|---|
| 自作:ドキュメント用ブロック | ネイティブ型 | 注意書き、手順、タブ、カード、図、やさしい解説、AIに聞いてみよう、選択肢の比較、本サイトではこうしている、の9種類のブロックと、その公開側の描画 |
| 自作:運用パネル | ネイティブ型 | 管理画面の確認キュー、ダッシュボードのウィジェット、編集画面の横のパネル |
@emdash-cms/plugin-audit-log |
公式(plugins: [] に登録) |
誰がいつ何を変えたかの記録 |
@emdash-cms/plugin-webhook-notifier |
公式・サンドボックス型 | 公開時の通知 |
| メール送信プラグイン | 未定 | 招待・通知メール |
選択の理由はプラグインの使い方にあります。
原文の同期から公開まで
GitHub Actionsが毎日、公式リポジトリの変更と新しいリリースを検知します。運営者が行うのは、通知を受けて、プレビューで確認し、公開することです。
図のテキストを読む
sequenceDiagram
participant GA as GitHub Actions
participant AI as 生成AI
participant CMS as EmDash
participant OP as 運営者
GA->>GA: 公式の変更・新リリースを検知
GA->>AI: 翻訳・解説の生成を依頼
AI-->>GA: 訳文と解説
GA->>AI: 別モデルで相互レビュー
GA->>CMS: 下書きとして保存
GA->>OP: 変更一覧とプレビューURLを通知
OP->>CMS: 確認して公開
| 起きること | 自動で行うこと | 運営者が行うこと |
|---|---|---|
| 公式ドキュメントの変更 | 該当ページを再翻訳し、下書きを更新する。公開中のページには「要更新」の警告を出す | 差分を確認して公開する |
| EmDashの新しいリリース | リリース要約の下書きを作る。本サイトのEmDashをプレビュー環境で更新して検証する | 要約を公開する。本番の更新を判断する |
| 本サイトの構成の変更 | 対応する実践ページと、このページの更新案を作る | 確認して公開する |
| サイトの表示障害 | 稼働監視が検知して通知する | 原因を確認し、必要ならロールバックする |
本番へのデプロイは pnpm build → pnpm wrangler deploy の順で実行します。コアマイグレーションは本番デプロイの前にCIで emdash migrate を実行し、emdash migrate --check で確認します。
EmDashの更新の手順はEmDashの更新の追いかけ方に、人とAIの分担は生成AIとの分担にあります。
巻き戻しの仕組み
戻したいものを6つに分け、それぞれを別の仕組みで守っています。GitHubは、ソースを戻せる場所として、非公開リポジトリ1つを保管庫として使っています。
| 戻したいもの | 戻す仕組み | 提供元 | 戻せる範囲 |
|---|---|---|---|
| 1ページの本文 | リビジョンから前の版を復元 | EmDash標準 | 保存された全ての版 |
| 削除したページ | ゴミ箱から復元 | EmDash標準 | 完全に削除するまで |
| データベース全体(本文、スキーマ、設定、メニュー、ユーザー) | D1のTime Travel | Cloudflare標準 | 有料プランで30日前まで |
| 30日より前のデータベース | 週1回のSQLダンプ(wrangler d1 export)をR2の別バケットに保存 |
Cloudflare標準の組み合わせ | 保存した分 |
| 動いているコード | Workersのロールバック | Cloudflare標準 | 直近100版 |
| コードの元(ソース) | Gitのコミット履歴 | GitHub(非公開リポジトリ) | 全履歴 |
| 画像・ファイル | R2の別バケットへの毎日のコピー | 自動処理で実装 | コピーした時点 |
| 秘密情報・暗号化キー | パスワード管理ツールに控えを保管 | 運営者の手元 | 控えた時点 |
本番デプロイ、EmDash本体の更新、スキーマ変更、一括投入の直前には、D1の現在の時点(ブックマーク)を自動処理が記録し、通知に載せています。データベースを戻すときは、先に自動処理を止めて書き込みを止めます。管理画面から取れるJSONのバックアップは控えとしてだけ扱い、巻き戻しの手段には数えていません。
事態ごとの戻し方は巻き戻しの備えにあります。
費用
本サイトの費用は、Cloudflare Workersの有料プラン(月額5ドルから)と、D1・R2・KVなどの使用量に応じた料金で決まります。料金の範囲は実行環境の選び方とDBとファイル置き場の選び方にまとめています。本サイトでは、実際にかかっている月額は載せていません。
実践ページとの対応
| 実践ページ | このページの該当箇所 |
|---|---|
| 開発環境の持ち方 | 環境 |
| バージョン履歴の持ち方 | 技術スタック(ソースの保管)、巻き戻しの仕組み |
| 巻き戻しの備え | 巻き戻しの仕組み |
| EmDashの更新の追いかけ方 | 原文の同期から公開まで |
| 生成AIとの分担 | 原文の同期から公開まで、認証と権限 |
| コンテンツの正本の置き場所 | コンテンツの持ち方 |
| 実行環境の選び方 | 技術スタック |
| DBとファイル置き場の選び方 | Cloudflareのリソース |
| 管理画面の守り方 | 認証と権限 |
| プラグインの使い方 | プラグイン |
根拠にした公式ページ
- Cloudflareへのデプロイ(原文:https://docs.emdashcms.com/deployment/cloudflare/)
- バックアップと復旧(原文:https://docs.emdashcms.com/guides/backups/)
- コアDBマイグレーション(原文:https://docs.emdashcms.com/deployment/core-migrations/)
- EmDashのアップデート(原文:https://docs.emdashcms.com/deployment/updating/)
- 認証(原文:https://docs.emdashcms.com/guides/authentication/)
- メディアストレージの選択(原文:https://docs.emdashcms.com/deployment/storage/)
- MCPサーバーリファレンス(原文:https://docs.emdashcms.com/reference/mcp-server/)
- はじめてのネイティブ型プラグイン(原文:https://docs.emdashcms.com/plugins/creating-native-plugins/your-first-native-plugin/)
- CLIリファレンス(原文:https://docs.emdashcms.com/reference/cli/)
- Cloudflare Workersの料金(https://developers.cloudflare.com/workers/platform/pricing/)
- Cloudflare R2の料金(https://developers.cloudflare.com/r2/pricing/)