Configuration Reference
EmDash is configured through two files: astro.config.mjs for the integration and src/live.config.ts for content collections.
Astro Integration
Section titled “Astro Integration”Configure EmDash as an Astro integration:
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: [], }), ],});Integration Options
Section titled “Integration Options”database
Section titled “database”Required. Database adapter configuration.
// SQLite (Node.js)database: sqlite({ url: "file:./data.db" });
// PostgreSQLdatabase: postgres({ connectionString: process.env.DATABASE_URL });
// libSQLdatabase: libsql({ url: process.env.LIBSQL_DATABASE_URL, authToken: process.env.LIBSQL_AUTH_TOKEN,});
// Cloudflare D1 (import from @emdash-cms/cloudflare)database: d1({ binding: "DB" });See Database Options for details.
storage
Section titled “storage”Required. Media storage adapter configuration.
// Local filesystem (development)storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file",});
// R2 binding (Cloudflare Workers)storage: r2({ binding: "MEDIA", publicUrl: "https://pub-xxxx.r2.dev", // optional});
// S3-compatible (any platform)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});See Storage Options for details.
plugins
Section titled “plugins”Optional. Array of EmDash plugins.
import seoPlugin from "@emdash-cms/plugin-seo";
plugins: [seoPlugin()];Optional. Authentication configuration.
auth: { // Self-signup configuration selfSignup: { domains: ["example.com"], defaultRole: 20, // Contributor },
// OAuth providers 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 configuration session: { maxAge: 30 * 24 * 60 * 60, // 30 days sliding: true, // Reset expiry on activity },
// OR use Cloudflare Access (exclusive mode) cloudflareAccess: { teamDomain: "myteam.cloudflareaccess.com", audience: "your-app-audience-tag", autoProvision: true, defaultRole: 30, syncRoles: false, roleMapping: { "Admins": 50, "Editors": 40, }, },}auth.selfSignup
Section titled “auth.selfSignup”Allow users to self-register if their email domain is allowed.
| Option | Type | Default | Description |
|---|---|---|---|
domains | string[] | [] | Allowed email domains |
defaultRole | number | 20 | Role for self-signups |
selfSignup: { domains: ["example.com", "acme.org"], defaultRole: 20, // Contributor}auth.oauth
Section titled “auth.oauth”Configure OAuth login providers.
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
Section titled “auth.session”Session configuration.
| Option | Type | Default | Description |
|---|---|---|---|
maxAge | number | 2592000 (30d) | Session lifetime in seconds |
sliding | boolean | true | Reset expiry on activity |
auth.cloudflareAccess
Section titled “auth.cloudflareAccess”Use Cloudflare Access as the authentication provider instead of passkeys.
| Option | Type | Default | Description |
|---|---|---|---|
teamDomain | string | required | Your Access team domain |
audience | string | required | Application Audience (AUD) tag |
autoProvision | boolean | true | Create users on first login |
defaultRole | number | 30 | Default role for new users |
syncRoles | boolean | false | Update role on each login |
roleMapping | object | — | Map IdP groups to roles |
Database Adapters
Section titled “Database Adapters”Import from emdash/db:
import { sqlite, libsql, postgres, d1 } from "emdash/db";sqlite(config)
Section titled “sqlite(config)”SQLite database using better-sqlite3.
| Option | Type | Description |
|---|---|---|
url | string | File path with file: prefix |
sqlite({ url: "file:./data.db" });libsql(config)
Section titled “libsql(config)”libSQL database.
| Option | Type | Description |
|---|---|---|
url | string | Database URL |
authToken | string | Auth token (optional for local files) |
libsql({ url: process.env.LIBSQL_DATABASE_URL, authToken: process.env.LIBSQL_AUTH_TOKEN,});postgres(config)
Section titled “postgres(config)”PostgreSQL database with connection pooling.
| Option | Type | Description |
|---|---|---|
connectionString | string | PostgreSQL connection URL |
host | string | Database host |
port | number | Database port |
database | string | Database name |
user | string | Database user |
password | string | Database password |
ssl | boolean | Enable SSL |
pool.min | number | Minimum pool size (default: 0) |
pool.max | number | Maximum pool size (default: 10) |
postgres({ connectionString: process.env.DATABASE_URL });d1(config)
Section titled “d1(config)”Cloudflare D1 database. Import from @emdash-cms/cloudflare.
| Option | Type | Default | Description |
|---|---|---|---|
binding | string | — | D1 binding name from wrangler.jsonc |
session | string | "disabled" | Read replication mode: "disabled", "auto", or "primary-first" |
bookmarkCookie | string | "__ec_d1_bookmark" | Cookie name for session bookmarks |
// Basicd1({ binding: "DB" });
// With read replicasd1({ binding: "DB", session: "auto" });When session is "auto" or "primary-first", EmDash uses the D1 Sessions API to route read queries to nearby replicas. Authenticated users get bookmark-based read-your-writes consistency. See Database Options — Read Replicas for details.
Storage Adapters
Section titled “Storage Adapters”Import from emdash/astro:
import emdash, { local, r2, s3 } from "emdash/astro";local(config)
Section titled “local(config)”Local filesystem storage.
| Option | Type | Description |
|---|---|---|
directory | string | Directory path |
baseUrl | string | Base URL for serving files |
local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file",});r2(config)
Section titled “r2(config)”Cloudflare R2 binding.
| Option | Type | Description |
|---|---|---|
binding | string | R2 binding name |
publicUrl | string | Optional public URL |
r2({ binding: "MEDIA", publicUrl: "https://pub-xxxx.r2.dev",});s3(config)
Section titled “s3(config)”S3-compatible storage.
| Option | Type | Description |
|---|---|---|
endpoint | string | S3 endpoint URL |
bucket | string | Bucket name |
accessKeyId | string | Access key |
secretAccessKey | string | Secret key |
region | string | Region (default: "auto") |
publicUrl | string | Optional CDN URL |
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",});Live Collections
Section titled “Live Collections”Configure the EmDash loader in src/live.config.ts:
import { defineLiveCollection } from "astro:content";import { emdashLoader } from "emdash/runtime";
export const collections = { _emdash: defineLiveCollection({ loader: emdashLoader(), }),};Loader Options
Section titled “Loader Options”The emdashLoader() function accepts optional configuration:
emdashLoader({ // Currently no options - reserved for future use});Environment Variables
Section titled “Environment Variables”EmDash respects these environment variables:
| Variable | Description |
|---|---|
EMDASH_DATABASE_URL | Override database URL |
EMDASH_AUTH_SECRET | Secret for passkey authentication |
EMDASH_PREVIEW_SECRET | Secret for preview token generation |
EMDASH_URL | Remote EmDash URL for schema sync |
Generate an auth secret with:
npx emdash auth secretpackage.json Configuration
Section titled “package.json Configuration”Optional configuration in 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" }}| Option | Description |
|---|---|
label | Template name for display |
description | Template description |
seed | Path to seed JSON file |
url | Remote URL for schema sync |
preview | Demo site URL for template preview |
TypeScript Configuration
Section titled “TypeScript Configuration”EmDash generates types in .emdash/types.ts. Add to your tsconfig.json:
{ "compilerOptions": { "paths": { "@emdash-cms/types": ["./.emdash/types.ts"] } }}Generate types with:
npx emdash types