Konfigurationsreferenz

Auf dieser Seite

EmDash wird über zwei Dateien konfiguriert: astro.config.mjs für die Integration und src/live.config.ts für Inhaltssammlungen.

Astro-Integration

Konfigurieren Sie EmDash als 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: [],
		}),
	],
});

Integrationsoptionen

database

Erforderlich. Konfiguration des Datenbankadapters.

// 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 (Import aus @emdash-cms/cloudflare)
database: d1({ binding: "DB" });

Weitere Informationen finden Sie unter Datenbankoptionen.

storage

Erforderlich. Konfiguration des Medienspeicheradapters.

// Lokales Dateisystem (Entwicklung)
storage: local({
	directory: "./uploads",
	baseUrl: "/_emdash/api/media/file",
});

// R2-Bindung (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
});

Weitere Informationen finden Sie unter Speicheroptionen.

plugins

Optional. Array von EmDash-Plugins.

import seoPlugin from "@emdash-cms/plugin-seo";

plugins: [seoPlugin()];

auth

Optional. Authentifizierungskonfiguration.

auth: {
  // Selbstregistrierungskonfiguration
  selfSignup: {
    domains: ["example.com"],
    defaultRole: 20, // Contributor
  },
  
  // OAuth-Anbieter
  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,
    },
  },
  
  // Sitzungskonfiguration
  session: {
    maxAge: 30 * 24 * 60 * 60, // 30 Tage
    sliding: true, // Ablauf bei Aktivität zurücksetzen
  },
  
  // ODER Cloudflare Access verwenden (exklusiver Modus)
  cloudflareAccess: {
    teamDomain: "myteam.cloudflareaccess.com",
    audience: "your-app-audience-tag",
    autoProvision: true,
    defaultRole: 30,
    syncRoles: false,
    roleMapping: {
      "Admins": 50,
      "Editors": 40,
    },
  },
}

auth.selfSignup

Ermöglicht Benutzern die Selbstregistrierung, wenn ihre E-Mail-Domäne zugelassen ist.

OptionTypStandardBeschreibung
domainsstring[][]Zugelassene E-Mail-Domänen
defaultRolenumber20Rolle für Selbstregistrierungen
selfSignup: {
  domains: ["example.com", "acme.org"],
  defaultRole: 20, // Contributor
}

auth.oauth

Konfigurieren Sie OAuth-Anmeldeanbieter.

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

Sitzungskonfiguration.

OptionTypStandardBeschreibung
maxAgenumber2592000 (30d)Sitzungsdauer in Sekunden
slidingbooleantrueAblauf bei Aktivität zurücksetzen

auth.cloudflareAccess

Verwenden Sie Cloudflare Access als Authentifizierungsanbieter anstelle von Passkeys.

OptionTypStandardBeschreibung
teamDomainstringerforderlichIhre Access-Team-Domäne
audiencestringerforderlichAnwendungs-Audience-Tag (AUD)
autoProvisionbooleantrueBenutzer beim ersten Login erstellen
defaultRolenumber30Standardrolle für neue Benutzer
syncRolesbooleanfalseRolle bei jeder Anmeldung aktualisieren
roleMappingobjectIdP-Gruppen Rollen zuordnen

siteUrl

Optional. Der öffentliche, browserseitige Ursprung der Website (Schema + Host + optionaler Port, kein Pfad).

Hinter einem TLS-terminierenden Reverse-Proxy gibt Astro.url die interne Adresse (http://localhost:4321) statt der öffentlichen (https://cms.example.com) zurück. Dies bricht Passkeys, CSRF-Origin-Matching, OAuth-Weiterleitungen, Login-Weiterleitungen, MCP-Erkennung, Snapshot-Exporte, Sitemap, robots.txt und JSON-LD strukturierte Daten. Setzen Sie siteUrl, um all dies auf einmal zu beheben.

Die Integration validiert diesen Wert beim Laden: Es muss eine gültige URL mit dem Protokoll http: oder https: sein und wird auf origin normalisiert (der Pfad wird entfernt).

emdash({
	database: sqlite({ url: "file:./data.db" }),
	storage: local({
		directory: "./uploads",
		baseUrl: "/_emdash/api/media/file",
	}),
	siteUrl: "https://cms.example.com",
});

Wenn siteUrl nicht in der Konfiguration gesetzt ist, prüft EmDash Umgebungsvariablen in dieser Reihenfolge: EMDASH_SITE_URL, dann SITE_URL. Dies ist nützlich für Container-Deployments, bei denen die öffentliche URL zur Laufzeit gesetzt wird.

Reverse-Proxy-Einrichtung

Astro berücksichtigt X-Forwarded-* nur, wenn der öffentliche Host zugelassen ist. Konfigurieren Sie security.allowedDomains für den Hostnamen (und die Schemata), über die Ihre Benutzer zugreifen. Fügen Sie in astro dev passende vite.server.allowedHosts hinzu, damit Vite den Host-Header des Proxys akzeptiert.

Korrigieren Sie vorzugsweise zuerst allowedDomains (und weitergeleitete Header). Verwenden Sie siteUrl, wenn die rekonstruierte URL weiterhin vom Browser-Ursprung abweicht (typisch, wenn TLS vor der Anwendung terminiert wird und die Upstream-Anfrage http:// bleibt).

Wenn TLS vorgeschaltet ist, reicht es oft aus, den Entwicklungsserver an Loopback zu binden (astro dev --host 127.0.0.1): Der Proxy verbindet sich lokal, während siteUrl mit dem öffentlichen HTTPS-Ursprung übereinstimmt.

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",
		}),
	],
});

Datenbankadapter

Import aus emdash/db:

import { sqlite, libsql, postgres, d1 } from "emdash/db";

sqlite(config)

SQLite-Datenbank mit better-sqlite3.

OptionTypBeschreibung
urlstringDateipfad mit dem Präfix file:
sqlite({ url: "file:./data.db" });

libsql(config)

libSQL-Datenbank.

OptionTypBeschreibung
urlstringDatenbank-URL
authTokenstringAuthentifizierungstoken (optional für lokale Dateien)
libsql({
	url: process.env.LIBSQL_DATABASE_URL,
	authToken: process.env.LIBSQL_AUTH_TOKEN,
});

postgres(config)

PostgreSQL-Datenbank mit Verbindungspooling.

OptionTypBeschreibung
connectionStringstringPostgreSQL-Verbindungs-URL
hoststringDatenbankhost
portnumberDatenbankport
databasestringDatenbankname
userstringDatenbankbenutzer
passwordstringDatenbankpasswort
sslbooleanSSL aktivieren
pool.minnumberMinimale Poolgröße (Standard: 0)
pool.maxnumberMaximale Poolgröße (Standard: 10)
postgres({ connectionString: process.env.DATABASE_URL });

d1(config)

Cloudflare-D1-Datenbank. Import aus @emdash-cms/cloudflare.

OptionTypStandardBeschreibung
bindingstringD1-Bindungsname aus wrangler.jsonc
sessionstring"disabled"Lesereplikationsmodus: "disabled", "auto" oder "primary-first"
bookmarkCookiestring"__ec_d1_bookmark"Cookie-Name für Sitzungs-Lesezeichen
// Einfach
d1({ binding: "DB" });

// Mit Lesereplikaten
d1({ binding: "DB", session: "auto" });

Wenn session auf "auto" oder "primary-first" gesetzt ist, verwendet EmDash die D1-Sessions-API, um Leseabfragen an nahegelegene Replikate weiterzuleiten. Authentifizierte Benutzer erhalten eine lesezeichenbasierte Lese-nach-Schreib-Konsistenz. Weitere Informationen finden Sie unter Datenbankoptionen — Lesereplikate.

Speicheradapter

Import aus emdash/astro:

import emdash, { local, r2, s3 } from "emdash/astro";

local(config)

Lokaler Dateisystemspeicher.

OptionTypBeschreibung
directorystringVerzeichnispfad
baseUrlstringBasis-URL zum Bereitstellen von Dateien
local({
	directory: "./uploads",
	baseUrl: "/_emdash/api/media/file",
});

r2(config)

Cloudflare-R2-Bindung.

OptionTypBeschreibung
bindingstringR2-Bindungsname
publicUrlstringOptionale öffentliche URL
r2({
	binding: "MEDIA",
	publicUrl: "https://pub-xxxx.r2.dev",
});

s3(config?)

S3-kompatibler Speicher. Alle Konfigurationsfelder sind optional: Felder, die in s3({...}) weggelassen werden, werden beim Start des Node-Prozesses aus der entsprechenden S3_*-Umgebungsvariable aufgelöst. Explizite Werte haben immer Vorrang.

Voraussetzung: Installieren Sie @aws-sdk/client-s3 und @aws-sdk/s3-request-presigner in Ihrem Projekt. Der EmDash-Kern enthält das AWS SDK nicht. Siehe Speicheroptionen → S3-kompatibler Speicher für Details.

OptionTypBeschreibung
endpointstringS3-Endpunkt-URL (S3_ENDPOINT)
bucketstringBucket-Name (S3_BUCKET)
accessKeyIdstringZugriffsschlüssel (S3_ACCESS_KEY_ID)
secretAccessKeystringGeheimer Schlüssel (S3_SECRET_ACCESS_KEY)
regionstringRegion, Standard "auto" (S3_REGION)
publicUrlstringOptionale 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",
})

Die Auflösung von Umgebungsvariablen zur Laufzeit ist eine reine Node-Funktion. Auf Cloudflare Workers werden Secrets und Variablen über den env-Parameter des Fetch-Handlers bereitgestellt, nicht über process.env, sodass S3_*-Umgebungsvariablen nicht erfasst werden. Workers-Deployments sollten den r2(config)-Adapter verwenden oder explizite Werte an s3({...}) übergeben. Siehe Speicheroptionen für Details.

Live-Sammlungen

Konfigurieren Sie den 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-Optionen

Die Funktion emdashLoader() akzeptiert optionale Konfiguration:

emdashLoader({
	// Derzeit keine Optionen - reserviert für zukünftige Nutzung
});

Umgebungsvariablen

EmDash berücksichtigt die folgenden Umgebungsvariablen:

VariableBeschreibung
EMDASH_SITE_URLÖffentlicher browserseitiger Ursprung (Fallback auf SITE_URL)
EMDASH_DATABASE_URLDatenbank-URL überschreiben
EMDASH_AUTH_SECRETGeheimnis für die Passkey-Authentifizierung
EMDASH_PREVIEW_SECRETGeheimnis für die Vorschau-Token-Generierung
EMDASH_URLRemote-EmDash-URL für die Schemasynchronisierung

Generieren Sie ein Authentifizierungsgeheimnis mit:

npx emdash auth secret

package.json-Konfiguration

Optionale Konfiguration 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"
	}
}
OptionBeschreibung
labelVorlagenname für die Anzeige
descriptionVorlagenbeschreibung
seedPfad zur Seed-JSON-Datei
urlRemote-URL für die Schemasynchronisierung
previewDemo-Site-URL für die Vorlagenvorschau

TypeScript-Konfiguration

EmDash generiert Typen in .emdash/types.ts. Fügen Sie Folgendes zu Ihrer tsconfig.json hinzu:

{
	"compilerOptions": {
		"paths": {
			"@emdash-cms/types": ["./.emdash/types.ts"]
		}
	}
}

Typen generieren mit:

npx emdash types