EmDash はインテグレーション用の astro.config.mjs とコンテンツコレクション用の src/live.config.ts の 2 つのファイルを通じて設定されます。
Astro インテグレーション
EmDash を Astro インテグレーションとして設定します:
import { defineConfig } from "astro/config";
import emdash, { local, r2, s3 } from "emdash/astro";
import { sqlite, libsql, d1 } from "emdash/db";
export default defineConfig({
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
plugins: [],
}),
],
});
インテグレーションオプション
database
必須。 データベースアダプターの設定。
// SQLite (Node.js)
database: sqlite({ url: "file:./data.db" });
// PostgreSQL
database: postgres({ connectionString: process.env.DATABASE_URL });
// libSQL
database: libsql({
url: process.env.LIBSQL_DATABASE_URL,
authToken: process.env.LIBSQL_AUTH_TOKEN,
});
// Cloudflare D1 (@emdash-cms/cloudflare からインポート)
database: d1({ binding: "DB" });
詳細はデータベースオプションを参照してください。
storage
必須。 メディアストレージアダプターの設定。
// ローカルファイルシステム(開発用)
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
});
// R2 バインディング(Cloudflare Workers)
storage: r2({
binding: "MEDIA",
publicUrl: "https://pub-xxxx.r2.dev", // optional
});
// S3-compatible (any platform) — all fields from S3_* environment variables
storage: s3()
// Or with explicit values
storage: s3({
endpoint: "https://s3.amazonaws.com",
bucket: "my-bucket",
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
region: "us-east-1", // optional, default: "auto"
publicUrl: "https://cdn.example.com", // optional
});
詳細はストレージオプションを参照してください。
plugins
任意。 EmDash プラグインの配列。
import seoPlugin from "@emdash-cms/plugin-seo";
plugins: [seoPlugin()];
auth
任意。 認証設定。
auth: {
// セルフサインアップ設定
selfSignup: {
domains: ["example.com"],
defaultRole: 20, // Contributor
},
// OAuth プロバイダー
oauth: {
github: {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
},
},
// セッション設定
session: {
maxAge: 30 * 24 * 60 * 60, // 30 日
sliding: true, // アクティビティで有効期限をリセット
},
// または Cloudflare Access を使用(排他モード)
cloudflareAccess: {
teamDomain: "myteam.cloudflareaccess.com",
audience: "your-app-audience-tag",
autoProvision: true,
defaultRole: 30,
syncRoles: false,
roleMapping: {
"Admins": 50,
"Editors": 40,
},
},
}
auth.selfSignup
メールドメインが許可されている場合、ユーザーの自己登録を許可します。
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
domains | string[] | [] | 許可されたメールドメイン |
defaultRole | number | 20 | セルフサインアップのロール |
selfSignup: {
domains: ["example.com", "acme.org"],
defaultRole: 20, // Contributor
}
auth.oauth
OAuth ログインプロバイダーを設定します。
oauth: {
github: {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
},
}
auth.session
セッション設定。
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
maxAge | number | 2592000 (30d) | セッション有効期間(秒) |
sliding | boolean | true | アクティビティで有効期限をリセット |
auth.cloudflareAccess
パスキーの代わりに Cloudflare Access を認証プロバイダーとして使用します。
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
teamDomain | string | 必須 | Access チームドメイン |
audience | string | 必須 | アプリケーションオーディエンス (AUD) タグ |
autoProvision | boolean | true | 初回ログイン時にユーザーを作成 |
defaultRole | number | 30 | 新規ユーザーのデフォルトロール |
syncRoles | boolean | false | ログインごとにロールを更新 |
roleMapping | object | — | IdP グループをロールにマッピング |
siteUrl
任意。 サイトのブラウザ向けパブリックオリジン(スキーム + ホスト + 任意のポート、パスなし)。
TLS 終端リバースプロキシの背後では、Astro.url はパブリックアドレス(https://cms.example.com)ではなく内部アドレス(http://localhost:4321)を返します。これにより、パスキー、CSRF オリジンマッチング、OAuth リダイレクト、ログインリダイレクト、MCP ディスカバリー、スナップショットエクスポート、サイトマップ、robots.txt、JSON-LD 構造化データが正しく動作しなくなります。siteUrl を設定すると、これらすべてを一括で修正できます。
インテグレーションはロード時にこの値をバリデートします: http: または https: プロトコルの有効な URL である必要があり、origin に正規化されます(パスは除去されます)。
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
siteUrl: "https://cms.example.com",
});
設定で siteUrl が指定されていない場合、EmDash は環境変数を順番に確認します: まず EMDASH_SITE_URL、次に SITE_URL。これは、パブリック URL がランタイムで設定されるコンテナデプロイメントに便利です。
リバースプロキシの設定
Astro はパブリックホストが許可されている場合にのみ X-Forwarded-* を反映します。ユーザーがアクセスするホスト名(およびスキーム)に対して security.allowedDomains を設定してください。astro dev では、Vite がプロキシの Host ヘッダーを受け入れるように vite.server.allowedHosts も追加します。
まず allowedDomains(および転送ヘッダー)の修正を優先してください。再構築された URL がブラウザオリジンからまだ乖離する場合に siteUrl を使用します(TLS が前面で終端され、アップストリームリクエストが http:// のままの場合に典型的)。
TLS を前面に配置する場合、dev サーバーをループバック(astro dev --host 127.0.0.1)にバインドするだけで十分なことが多いです: プロキシはローカルに接続し、siteUrl がパブリック HTTPS オリジンと一致します。
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";
export default defineConfig({
security: {
allowedDomains: [
{ hostname: "cms.example.com", protocol: "https" },
{ hostname: "cms.example.com", protocol: "http" },
],
},
vite: {
server: {
allowedHosts: ["cms.example.com"],
},
},
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
siteUrl: "https://cms.example.com",
}),
],
});
データベースアダプター
emdash/db からインポートします:
import { sqlite, libsql, postgres, d1 } from "emdash/db";
sqlite(config)
better-sqlite3 を使用した SQLite データベース。
| オプション | 型 | 説明 |
|---|---|---|
url | string | file: プレフィックス付きファイルパス |
sqlite({ url: "file:./data.db" });
libsql(config)
libSQL データベース。
| オプション | 型 | 説明 |
|---|---|---|
url | string | データベース URL |
authToken | string | 認証トークン(ローカルファイルの場合は任意) |
libsql({
url: process.env.LIBSQL_DATABASE_URL,
authToken: process.env.LIBSQL_AUTH_TOKEN,
});
postgres(config)
コネクションプーリング付き PostgreSQL データベース。
| オプション | 型 | 説明 |
|---|---|---|
connectionString | string | PostgreSQL 接続 URL |
host | string | データベースホスト |
port | number | データベースポート |
database | string | データベース名 |
user | string | データベースユーザー |
password | string | データベースパスワード |
ssl | boolean | SSL を有効化 |
pool.min | number | 最小プールサイズ(デフォルト: 0) |
pool.max | number | 最大プールサイズ(デフォルト: 10) |
postgres({ connectionString: process.env.DATABASE_URL });
d1(config)
Cloudflare D1 データベース。@emdash-cms/cloudflare からインポートします。
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
binding | string | — | wrangler.jsonc の D1 バインディング名 |
session | string | "disabled" | リードレプリケーションモード: "disabled", "auto", "primary-first" |
bookmarkCookie | string | "__ec_d1_bookmark" | セッションブックマークの Cookie 名 |
// 基本
d1({ binding: "DB" });
// リードレプリカ付き
d1({ binding: "DB", session: "auto" });
session が "auto" または "primary-first" の場合、EmDash は D1 Sessions API を使用して読み取りクエリを最寄りのレプリカにルーティングします。認証済みユーザーはブックマークベースの read-your-writes 一貫性を得られます。詳細はデータベースオプション — リードレプリカを参照してください。
ストレージアダプター
emdash/astro からインポートします:
import emdash, { local, r2, s3 } from "emdash/astro";
local(config)
ローカルファイルシステムストレージ。
| オプション | 型 | 説明 |
|---|---|---|
directory | string | ディレクトリパス |
baseUrl | string | ファイル配信のベース URL |
local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
});
r2(config)
Cloudflare R2 バインディング。
| オプション | 型 | 説明 |
|---|---|---|
binding | string | R2 バインディング名 |
publicUrl | string | 任意のパブリック URL |
r2({
binding: "MEDIA",
publicUrl: "https://pub-xxxx.r2.dev",
});
s3(config?)
S3 互換ストレージ。すべての設定フィールドは任意です: s3({...}) で省略されたフィールドは、Node プロセス起動時に対応する S3_* 環境変数から解決されます。明示的な値は常に優先されます。
前提条件: プロジェクトに @aws-sdk/client-s3 と @aws-sdk/s3-request-presigner をインストールしてください。EmDash コアは AWS SDK をバンドルしていません。詳細はストレージオプション → S3 互換ストレージを参照してください。
| オプション | 型 | 説明 |
|---|---|---|
endpoint | string | S3 エンドポイント URL(S3_ENDPOINT) |
bucket | string | バケット名(S3_BUCKET) |
accessKeyId | string | アクセスキー(S3_ACCESS_KEY_ID) |
secretAccessKey | string | シークレットキー(S3_SECRET_ACCESS_KEY) |
region | string | リージョン、デフォルト "auto"(S3_REGION) |
publicUrl | string | 任意の CDN URL(S3_PUBLIC_URL) |
// All fields from S3_* environment variables (Node container deployments)
s3()
// Mix: CDN from config, rest from environment
s3({ publicUrl: "https://cdn.example.com" })
// All explicit (unchanged from before)
s3({
endpoint: "https://xxx.r2.cloudflarestorage.com",
bucket: "media",
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
publicUrl: "https://cdn.example.com",
})
ランタイム環境変数の解決は Node 専用の機能です。Cloudflare Workers では、シークレットと変数は process.env ではなく、fetch ハンドラーの env パラメータを通じて公開されるため、S3_* 環境変数は読み取られません。Workers デプロイメントでは r2(config) アダプターを使用するか、s3({...}) に明示的な値を渡してください。詳細はストレージオプションを参照してください。
Live Collections
src/live.config.ts で EmDash ローダーを設定します:
import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";
export const collections = {
_emdash: defineLiveCollection({
loader: emdashLoader(),
}),
};
ローダーオプション
emdashLoader() 関数は任意の設定を受け付けます:
emdashLoader({
// 現在オプションなし - 将来の使用のために予約
});
環境変数
EmDash は以下の環境変数を参照します:
| 変数 | 説明 |
|---|---|
EMDASH_SITE_URL | ブラウザ向けパブリックオリジン(SITE_URL にフォールバック) |
EMDASH_DATABASE_URL | データベース URL のオーバーライド |
EMDASH_AUTH_SECRET | パスキー認証用のシークレット |
EMDASH_PREVIEW_SECRET | プレビュートークン生成用のシークレット |
EMDASH_URL | スキーマ同期用のリモート EmDash URL |
認証シークレットの生成:
npx emdash auth secret
package.json の設定
package.json の任意の設定:
{
"emdash": {
"label": "My Blog Template",
"description": "A clean, minimal blog template",
"seed": ".emdash/seed.json",
"url": "https://my-site.pages.dev",
"preview": "https://emdash-blog.pages.dev"
}
}
| オプション | 説明 |
|---|---|
label | 表示用のテンプレート名 |
description | テンプレートの説明 |
seed | シード JSON ファイルのパス |
url | スキーマ同期用のリモート URL |
preview | テンプレートプレビューのデモサイト URL |
TypeScript の設定
EmDash は .emdash/types.ts に型を生成します。tsconfig.json に追加します:
{
"compilerOptions": {
"paths": {
"@emdash-cms/types": ["./.emdash/types.ts"]
}
}
}
型の生成:
npx emdash types