Konfigurationsreferenz

Auf dieser Seite

Die zentrale EmDash-Konfiguration liegt in astro.config.mjs, während src/live.config.ts den Content-Loader registriert. Deployment-spezifische Werte können auch aus Umgebungsvariablen kommen. Ein kleiner Metadaten-Block in package.json unterstützt Template-Labels und ältere lokale CLI-Abläufe.

Astro-Integration

Konfigurieren Sie EmDash als Astro-Integration in astro.config.mjs:

import { defineConfig } from "astro/config";
import emdash, { local, s3 } from "emdash/astro";
import { sqlite, libsql } 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 Datenbank-Adapters. Wählen Sie einen Adapter:

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

Details finden Sie unter Datenbank wählen.

migrations

Optional. Steuert die Laufzeitbehandlung interner EmDash-Datenbankmigrationen. Fehlt diese Option, gilt standardmäßig { runtime: "auto" }.

migrations: {
	runtime: "check", // "auto" | "check" | "manual"
	dev: "auto",     // optional development override
}

auto prüft ausstehende Migrationen und wendet sie an, check liefert 503, wenn dem laufenden Build bekannte Migrationen noch ausstehen, und manual führt keine Laufzeit-Migrationsabfrage aus. EMDASH_MIGRATIONS_MODE überschreibt den effektiven Laufzeitmodus. Lesen Sie Core-Datenbankmigrationen verwalten, bevor Sie check oder manual einsetzen.

storage

Optional. Konfiguration des Medien-Speicher-Adapters. Fehlt diese Option, speichert EmDash Dateien in ./.emdash/uploads und stellt sie über /_emdash/api/media/file bereit. Wählen Sie einen Adapter, wenn das standardmäßige lokale Verzeichnis nicht passt:

// 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) — 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
});

Details finden Sie unter Speicheroptionen.

images

Optional. Steuert, ob EmDash gespeicherte Medien in Astros Bildoptimierung einbindet. Standard ist true.

Ist die Option aktiv, umschließt EmDash Astros Image-Endpoint, sodass <Image> und getImage() Quellbytes direkt vom konfigurierten Speicher-Adapter lesen können. Das funktioniert auch, wenn die ursprüngliche Medien-URL hinter Cloudflare Access liegt. Setzen Sie images: false, wenn ein anderer Bilddienst die Medien verarbeitet oder jedes Bild ohne EmDash-Endpoint-Wrapper gerendert werden soll.

emdash({
	images: false,
});

mediaProviders

Optional. Fügt der Medienbibliothek Medien-Dienste hinzu. Der speicherbasierte lokale Anbieter bleibt automatisch verfügbar; jeder Deskriptor in diesem Array ergänzt einen weiteren Ort, an dem Redakteure Medien durchsuchen oder hochladen können.

Das folgende Beispiel fügt Cloudflare Images und Cloudflare Stream hinzu:

import { cloudflareImages, cloudflareStream } from "@emdash-cms/cloudflare";

emdash({
	mediaProviders: [cloudflareImages({}), cloudflareStream({})],
});

Anbieter-Zugangsdaten werden zur Laufzeit aufgelöst. Die leeren Konfigurationen oben nutzen die standardmäßigen Cloudflare-Umgebungsvariablen aus den Adapter-Abschnitten cloudflareImages(config) und cloudflareStream(config). Siehe Medienbibliothek: Medienanbieter für Bindings und Rendering-Setup.

objectCache

Optional. Cacht Ergebnisse von Content- und Konfigurationsabfragen in einem Key-Value-Store, sodass Lesezugriffe ohne Datenbankabfrage bei jeder Anfrage bedient werden. Deaktiviert, wenn weggelassen. Wählen Sie einen Adapter:

// Cloudflare KV (shared across all isolates)
import { kvCache } from "@emdash-cms/cloudflare";
objectCache: kvCache({ binding: "CACHE" });

// In-memory (Node.js / development)
import { memoryCache } from "emdash/astro";
objectCache: memoryCache();

Setup und Optionen finden Sie unter Objekt-Cache.

middleware.outer

Optional. Registriert ein Astro-Middleware-Modul außerhalb des vollständigen EmDash-Middleware-Stacks. Da die Integration es bei Astro mit order: "pre" registriert, läuft es auch vor Middleware in src/middleware.ts. Nutzen Sie es für Request-Gates oder Full-Response-Caches, die bei einem Treffer Laufzeit- und Datenbankinitialisierung vermeiden müssen, oder für Response-Header, die von EmDashs finalem HTML abhängen.

emdash({
	middleware: {
		outer: "./src/outer-middleware.ts",
	},
});

Die Ausführungsreihenfolge:

  1. Die äußere Middleware läuft bis await next().
  2. EmDash initialisiert Laufzeit und Datenbank und führt Setup-, Authentifizierungs- und Request-Context-Middleware aus.
  3. Die Astro-Route rendert.
  4. EmDash wendet Response-Mutationen an, einschließlich Visual-Editing-HTML sowie Security-/Timing-Header.
  5. next() kehrt mit dieser finalen Response zur äußeren Middleware zurück.

Vor dem Aufruf von next() hat die Middleware den normalen Astro-Request und Plattform-Kontext, aber locals.emdash, locals.user, die Datenbank und request-scoped EmDash-Zustand sind nicht verfügbar. Eine frühe Response überspringt EmDash vollständig und muss daher alle benötigten Security- und Cache-Header enthalten. Nach dem Auflösen von next() können CSP-Nonces finalisiert, der vollständige Body gecacht oder Content-Length gesetzt werden. Ändert die Middleware den Body, entfernen oder berechnen Sie vorhandene Content-Length-Header neu.

Der Hook nutzt Astros Middleware-API auf Node und Cloudflare. Dieses minimale Cloudflare-Cache-API-Beispiel cached nur anonyme HTML-Responses und liefert Treffer vor der EmDash-Initialisierung:

import { waitUntil } from "cloudflare:workers";
import { defineMiddleware } from "astro:middleware";

export const onRequest = defineMiddleware(async ({ request }, next) => {
	if (request.method !== "GET" || request.headers.has("cookie")) {
		return next();
	}

	const cacheKey = new Request(request.url, { method: "GET" });
	const cached = await caches.default.match(cacheKey);
	if (cached) return cached;

	const response = await next();
	const isHtml = response.headers.get("content-type")?.includes("text/html");
	const isPrivate = response.headers.get("cache-control")?.includes("no-store");
	if (response.ok && isHtml && !isPrivate) {
		waitUntil(caches.default.put(cacheKey, response.clone()));
	}

	return response;
});

Auf Node verwenden Sie dieselbe Middleware-Form mit einem Node-kompatiblen Cache wie Redis. Cache-Keys und Bypass-Regeln müssen jede Request-Eigenschaft berücksichtigen, die die gerenderte Response ändert.

playground

Optional. Aktiviert die Middleware für wegwerfbare, browserbasierte EmDash-Playgrounds. Sie erstellt pro Sitzung eine beschreibbare Durable-Object-Datenbank, wendet den konfigurierten Seed an und meldet den Besucher als anonymen Administrator an, bevor die normale EmDash-Middleware läuft.

import { playgroundDatabase } from "@emdash-cms/cloudflare";

emdash({
	database: playgroundDatabase({ binding: "PLAYGROUND_DB" }),
	playground: {
		middlewareEntrypoint: "@emdash-cms/cloudflare/db/playground-middleware",
	},
});

Dieser Modus erfordert @emdash-cms/cloudflare und ein Durable-Object-Binding. Er umgeht normale Setup- und Authentifizierungs-Middleware — nutzen Sie ihn nur für kurzlebige Demo-Sites, nicht für ein Produktions-CMS.

plugins

Optional. Array von Plugins, die im selben Prozess wie die Astro-Site laufen. Native Plugins gehören hierher. Ein sandbox-kompatibles Plugin kann hier ebenfalls laufen, wenn Sie ihm vollen Prozesszugriff vertrauen und keine Isolation brauchen.

Das folgende Beispiel registriert ein natives Plugin:

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

plugins: [seoPlugin()];

Native Plugins können Server- und Framework-APIs direkt nutzen; sie können nicht nach sandboxed verschoben werden, es sei denn, das Paket bietet auch einen sandbox-kompatiblen Plugin-Einstiegspunkt. Siehe Plugin-Format wählen für Unterschiede beim Authoring und Deployment.

sandboxed

Optional. Array sandbox-kompatibler Plugins, die EmDashs deklarierte Plugin-APIs nutzen und in isolierten Laufzeiten laufen. Platzieren Sie hier kein natives Plugin: nativer Code kann von Prozess- und Framework-Zugriff abhängen, den die Sandbox nicht bietet.

import thirdPartyPlugin from "third-party-emdash-plugin";
import { sandbox } from "@emdash-cms/cloudflare";

emdash({
	sandboxed: [thirdPartyPlugin()],
	sandboxRunner: sandbox(),
});

Sandbox-Plugins werden übersprungen, wenn kein nutzbarer Sandbox-Runner konfiguriert ist. Siehe Plugin-Sandbox für Cloudflare- und Node.js-Runner-Setup.

sandboxRunner

Optional. Modul-Spezifizierer für die Factory, die isolierte Plugin-Laufzeiten startet. Erforderlich für Plugins in sandboxed sowie für Marketplace- oder Registry-Plugins.

Auf Cloudflare Workers verwenden Sie den sandbox()-Adapter:

import { sandbox } from "@emdash-cms/cloudflare";

emdash({
	sandboxRunner: sandbox(),
});

Node.js-Deployments nutzen das workerd-Runner-Modul in Plugin-Sandbox: Node.js.

sandbox

Optional. Steuert, ob ein konfigurierter Sandbox-Runner Plugins isoliert. Sandboxing ist aktiv, wenn sandboxRunner konfiguriert ist. Setzen Sie sandbox: false nur zur Diagnose, ob ein Problem vom Plugin oder seiner Sandbox-Laufzeit stammt:

emdash({
	sandboxRunner: sandbox(),
	sandbox: false,
});

Bei false laufen in sandboxed deklarierte und aus dem Marketplace installierte Plugins im Hauptserverprozess ohne Isolation oder Ressourcenlimits. Stellen Sie Sandboxing nach der Diagnose wieder her.

registry

Optional. Konfiguriert Aggregator und Richtlinie der Plugin-Registry. Ohne expliziten Wert nutzt EmDash https://registry.emdashcms.com, wenn sandboxRunner konfiguriert ist und sandbox nicht false ist.

Setzen Sie registry: false, um Registry-Discovery und Registry-installierte Plugins zu deaktivieren, während der Sandbox-Runner für in sandboxed deklarierte und Legacy-Marketplace-Plugins verfügbar bleibt:

emdash({
	sandboxRunner: sandbox(),
	registry: false,
});

Übergeben Sie die Registry-Service-URL als String oder ein Objekt, wenn die Site Moderationsquellen oder eine Release-Alter-Richtlinie braucht. Das folgende Beispiel nutzt die Objektform:

import { sandbox } from "@emdash-cms/cloudflare";

emdash({
	sandboxRunner: sandbox(),
	registry: {
		aggregatorUrl: "https://registry.emdashcms.com",
		acceptLabelers: "did:web:labels.emdashcms.com",
		policy: {
			minimumReleaseAge: "48h",
			minimumReleaseAgeExclude: ["did:plc:yourfirstpartydid"],
		},
	},
});
OptionTypBeschreibung
aggregatorUrlstringBasis-URL des Registry-Dienstes. In Produktion HTTPS verwenden.
acceptLabelersstringOptional kommagetrennte dezentrale Identifikatoren (DIDs) für Moderationsdienste, die die Anfrage akzeptiert. Eine DID ist ein stabiler Atmosphere-Kontobezeichner. Diese Einstellung kann die Richtlinie des Registry-Dienstes nicht überschreiben.
policy.minimumReleaseAgestring | numberHält Releases zurück, die jünger als dieses Alter sind. Dauer-String ("48h", "7d") oder Sekunden.
policy.minimumReleaseAgeExcludestring[]Publisher-DIDs oder <did>/<plugin-slug>-Paare, die vom Holdback ausgenommen sind.

Die Release-Alter-Richtlinie befreit das erste Release eines Pakets nur, wenn die Registry ein behaltenes Release meldet und bestätigt, das Paket durchgängig beobachtet zu haben. Ein backgefülltes Paket, ein gelöschtes früheres Release oder fehlende Historiennachweise lassen den Holdback bestehen. Explizite Publisher- und Paket-Ausnahmen gelten unabhängig von der Historie.

Siehe Die Plugin-Registry für Installationsworkflow und Vertrauensmodell.

marketplace

Veraltet. Basis-URL zum Aktualisieren von Plugins, die aus dem Legacy-Marketplace installiert wurden. Marketplace-Durchsuchen und Neuinstallationen erscheinen nicht im Admin. Bestehende Marketplace-Plugins bleiben aktualisier- und deinstallierbar, solange diese Option gesetzt ist.

emdash({
	marketplace: "https://marketplace.emdashcms.com",
	sandboxRunner: sandbox(),
});

Produktions-URLs müssen HTTPS nutzen; HTTP ist nur für localhost und 127.0.0.1 in der Entwicklung erlaubt. Behalten Sie diese Option, bis jedes Marketplace-Plugin ersetzt oder deinstalliert ist, und entfernen Sie sie danach. Folgen Sie Migration vom Marketplace für das vollständige Vorgehen.

fonts

Optional. Schriftkonfiguration für die Admin-Oberfläche.

Standardmäßig lädt EmDash Noto Sans über die Astro Font API. Schriften werden zur Build-Zeit von Google geladen und self-hosted, es gibt also keine CDN-Anfragen zur Laufzeit. Die Basisschrift deckt Latin, Kyrillisch, Griechisch, Devanagari und Vietnamesisch ab.

Für weitere Schriftsysteme übergeben Sie Script-Namen. Das folgende Beispiel ergänzt Arabisch und Japanisch:

emdash({
  fonts: {
    scripts: ["arabic", "japanese"],
  },
})

Verfügbare Scripts sind arabic, armenian, bengali, chinese-simplified, chinese-traditional, chinese-hongkong, devanagari, ethiopic, farsi, georgian, gujarati, gurmukhi, hebrew, japanese, kannada, khmer, korean, lao, malayalam, myanmar, oriya, sinhala, tamil, telugu, thai und tibetan.

Jedes Script mappt auf die entsprechende Noto-Sans-Variante bei Google Fonts (z. B. lädt "arabic" Noto Sans Arabic). Alle Font-Faces teilen einen font-family-Namen und nutzen unicode-range, sodass der Browser nur die für die Zeichen auf der Seite nötigen Dateien lädt.

Setzen Sie false, um Schrift-Injektion vollständig zu deaktivieren und Systemschriften zu nutzen:

emdash({
	fonts: false,
})

Das Admin-CSS nutzt die CSS-Variable --font-emdash. Sie wird automatisch durch die Schriftkonfiguration oben gesetzt.

auth

Optional. Ein Authentifizierungs-Adapter. EmDashs eingebauter Login sind Passkeys; auth ersetzt sie durch einen externen Anbieter. Den Cloudflare-Access-Adapter access() liefert @emdash-cms/cloudflare:

import { access } from "@emdash-cms/cloudflare";

emdash({
	auth: access({
		teamDomain: "myteam.cloudflareaccess.com",
		audience: "your-app-audience-tag",
		roleMapping: {
			Admins: 50,
			Editors: 40,
		},
	}),
});

Optionen für access():

OptionTypStandardBeschreibung
teamDomainstringerforderlichIhre Cloudflare-Access-Team-Domain
audiencestring—Application-Audience-(AUD)-Tag. Auf Workers audienceEnvVar bevorzugen.
audienceEnvVarstring"CF_ACCESS_AUDIENCE"Umgebungsvariable, aus der der Audience-Tag zur Laufzeit gelesen wird
autoProvisionbooleantrueEmDash-Benutzer beim ersten Login anlegen
defaultRolenumber30Rollenstufe für Benutzer ohne Treffer in roleMapping (siehe Benutzerrollen)
syncRolesbooleanfalseroleMapping bei jedem Login erneut anwenden, nicht nur bei der Bereitstellung
roleMappingobject—IdP-Gruppennamen auf EmDash-Rollenstufen mappen; erster Treffer gewinnt

authProviders

Optional. Array plug-in-fähiger Login-Anbieter (Top-Level, neben auth). Jeder Eintrag ist das Ergebnis eines Provider-Factory-Aufrufs, wie unten gezeigt:

import { github } from "emdash/auth/providers/github";
import { google } from "emdash/auth/providers/google";
import { atproto } from "@emdash-cms/auth-atproto";

emdash({
	authProviders: [github(), google(), atproto()],
});

Eingebaute Anbieter:

  • github() — liest EMDASH_OAUTH_GITHUB_CLIENT_ID / EMDASH_OAUTH_GITHUB_CLIENT_SECRET (oder unprefixed Fallbacks).
  • google() — liest EMDASH_OAUTH_GOOGLE_CLIENT_ID / EMDASH_OAUTH_GOOGLE_CLIENT_SECRET.
  • atproto() — Atmosphere-Kontologin (Bluesky und das breitere AT-Protokoll-Netzwerk). Keine Env-Vars nötig. Akzeptiert { allowedDIDs, allowedHandles, defaultRole }. Siehe die Anleitung zur Atmosphere-Anmeldung.

Drittanbieter-Pakete können eigene Anbieter mit derselben AuthProviderDescriptor-Form registrieren — siehe Login-Anbieter.

mcp

Optional. Aktiviert den Model Context Protocol (MCP)-Endpoint unter /_emdash/api/mcp. Der Endpoint ist standardmäßig aktiv und erfordert ein Bearer-Token; Aktivierung bedeutet also keinen anonymen Zugriff.

Setzen Sie die Option auf false, wenn die Site keinen MCP-Endpoint exponieren soll:

emdash({
	mcp: false,
});

Siehe MCP-Server-Referenz für Token-Erstellung und Client-Konfiguration.

siteUrl

Die öffentliche, browserseitige Origin der Site (Schema + Host + optionaler Port, ohne Pfad). Setzen Sie sie vor dem Produktions-Setup. Nur Loopback-Entwicklungshosts können Setup ohne konfigurierte Origin abschließen.

Hinter einem TLS-beendenden Reverse Proxy liefert Astro.url die interne Adresse (http://localhost:4321) statt der öffentlichen (https://cms.example.com). Das bricht Passkeys, CSRF-Origin-Matching, OAuth-Redirects, Login-Redirects, MCP-Discovery, Snapshot-Exporte, Sitemap, robots.txt und JSON-LD-Structured Data. Setzen Sie siteUrl, um all das auf einmal zu beheben.

Die Integration validiert diesen Wert beim Laden: Er muss eine gültige URL mit Protokoll http: oder https: sein und wird zur Origin normalisiert (Pfad wird entfernt).

Das folgende Beispiel setzt die öffentliche Origin:

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

Ist siteUrl in der Config nicht gesetzt, prüft EmDash nacheinander EMDASH_SITE_URL, dann SITE_URL. Das ist nützlich für Container-Deployments, bei denen die öffentliche URL zur Laufzeit gesetzt wird.

Setup schlägt mit SITE_URL_REQUIRED auf einem Nicht-Loopback-Host fehl, wenn keine Quelle gesetzt ist. So kann die erste unauthentifizierte Setup-Anfrage nicht die Origin wählen, die später in Auth-E-Mails verwendet wird.

Auf Cloudflare Workers liest der Env-Var-Fallback process.env. Mit nodejs_compat füllt Cloudflare process.env standardmäßig ab Compatibility-Datum 2025-04-01. Projekte mit früherem Datum müssen zusätzlich nodejs_compat_populate_process_env setzen.

// wrangler.jsonc
{
	"compatibility_date": "2026-02-24",
	"compatibility_flags": ["nodejs_compat"],
	"vars": { "EMDASH_SITE_URL": "https://cms.example.com" },
}

allowedOrigins

Optional. Zusätzliche Browser-Origins, die die Passkey-Verifikation akzeptiert, wenn ein Deployment unter mehr als einem Hostnamen erreichbar ist.

siteUrl definiert eine kanonische Origin. Ist dieselbe EmDash-Deployment unter mehreren Hostnamen mit gemeinsamer registrable parent domain erreichbar (z. B. https://example.com und https://preview.example.com), lehnt die Passkey-Verifikation Assertions ab, deren Origin nicht exakt siteUrl entspricht — obwohl WebAuthn Passkeys über Subdomains unter derselben rpId erlauben kann.

Deklarieren Sie zusätzliche akzeptierte Origins über allowedOrigins in astro.config.mjs oder die Env-Var EMDASH_ALLOWED_ORIGINS. Die kanonische siteUrl bleibt Quelle der rpId; Einträge hier werden bei der Verifikation akzeptiert. Beide Quellen werden zur Laufzeit zusammengeführt: Config kann stabile Origins (versioniert, code-reviewed) deklarieren, Env ergänzt umgebungsspezifische Extras (z. B. ephemere PR-Previews).

Das folgende Beispiel deklariert eine zusätzliche Origin in der Config:

emdash({
	siteUrl: "https://example.com",
	allowedOrigins: ["https://preview.example.com"],
})

Die gleichen Werte können auch aus Umgebungsvariablen kommen:

EMDASH_SITE_URL=https://example.com
EMDASH_ALLOWED_ORIGINS=https://preview.example.com,https://staging.example.com
Validierung

EmDash validiert diese Werte, um tote Konfiguration zu vermeiden, die der Browser nie akzeptieren würde:

  • Jeder Eintrag muss eine parsebare http:- oder https:-URL ohne abschließenden Punkt und ohne leere Labels im Hostnamen sein.
  • Ist allowedOrigins nicht leer, muss siteUrl gesetzt sein (aus einer der Quellen) und darf kein IP-Literal oder Hostname mit abschließendem Punkt sein.
  • Jede Origin muss derselbe Hostname wie siteUrl oder eine Subdomain davon sein. (WebAuthn verlangt, dass rpId ein registrable suffix jeder Origin ist.)

Schlägt die Validierung fehl, erscheint ein quellenbezogener Fehler wie EmDash config error in EMDASH_ALLOWED_ORIGINS: "https://other-site.com" is not a subdomain of siteUrl "https://example.com". Allowed origins must be the same hostname as siteUrl or a subdomain of it.

Wo der Fehler sichtbar wird, hängt davon ab, wo die Werte deklariert sind:

  • Beim Astro-Start, wenn config.allowedOrigins und config.siteUrl aus astro.config.mjs kommen — Tippfehler im Code brechen den Build.
  • Bei der ersten Passkey-Verifikation, wenn ein Wert aus EMDASH_ALLOWED_ORIGINS oder EMDASH_SITE_URL kommt — Env-Mismatches erscheinen als 500 beim ersten Verify-Versuch.

Reverse-Proxy-Setup

Astro spiegelt X-Forwarded-* nur, wenn der öffentliche Host erlaubt ist. Konfigurieren Sie security.allowedDomains für Hostname (und Schemas), die Ihre Nutzer aufrufen. In astro dev passende vite.server.allowedHosts ergänzen, damit Vite den Proxy-Host-Header akzeptiert.

Beheben Sie zuerst allowedDomains (und Forwarded-Header); nutzen Sie siteUrl, wenn die rekonstruierte URL weiterhin von der Browser-Origin abweicht (typisch, wenn TLS vorn beendet wird und die Upstream-Anfrage http:// bleibt).

Mit TLS davor reicht oft, den Dev-Server an Loopback zu binden (astro dev --host 127.0.0.1): Der Proxy verbindet lokal, während siteUrl der öffentlichen HTTPS-Origin entspricht.

Schreibt Ihr Proxy einen Client-IP-Header, setzen Sie trustedProxyHeaders, damit EmDashs Rate Limits die echte Client-IP nutzen statt jede Anfrage unter einem gemeinsamen „unknown“-Schlüssel zu bündeln.

Die folgende Konfiguration setzt allowedDomains, vite.server.allowedHosts und siteUrl gemeinsam für ein Reverse-Proxy-Deployment:

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

trustedProxyHeaders

Optional. Header, den Sie für die Client-IP-Auflösung hinter einem von Ihnen kontrollierten Reverse Proxy vertrauen. Genutzt von Auth-Rate-Limits (Magic Link, Signup, Passkey, OAuth Device Flow) und dem öffentlichen Kommentar-Endpoint.

Auf Cloudflare wird das an die Anfrage angehängte cf-Objekt automatisch genutzt — Sie müssen dies normalerweise nicht setzen. Bei Self-Hosting hinter nginx, Caddy, Traefik, Fly, Railway o. Ä. setzen Sie den Header, den Ihr Proxy schreibt, damit Rate Limits nach echter Client-IP bucketing statt jede Anfrage als „unknown“ zu behandeln.

Das folgende Beispiel vertraut dem x-real-ip-Header von nginx, Caddy oder Traefik:

emdash({
	database: sqlite({ url: "file:./data.db" }),
	trustedProxyHeaders: ["x-real-ip"],
});

Header werden der Reihe nach probiert. Werte, die *-forwarded-for entsprechen, werden als kommagetrennte Listen geparst; der erste Eintrag wird genutzt. Das folgende Beispiel bevorzugt Fly.io-Header und fällt auf x-forwarded-for zurück:

emdash({
	trustedProxyHeaders: ["fly-client-ip", "x-forwarded-for"],
});

Ist nichts in der Config gesetzt, liest EmDash die Env-Var EMDASH_TRUSTED_PROXY_HEADERS (kommagetrennt). Ein explizites leeres Array in der Config überschreibt die Env-Var.

maxUploadSize

Optional. Maximale erlaubte Medien-Upload-Größe in Bytes. Gilt für direkte Multipart-Uploads und Signed-URL-Uploads. Standard: 52_428_800 (50 MB). Das folgende Beispiel erhöht das Limit auf 100 MB:

emdash({
	database: sqlite({ url: "file:./data.db" }),
	storage: local({
		directory: "./uploads",
		baseUrl: "/_emdash/api/media/file",
	}),
	maxUploadSize: 100 * 1024 * 1024, // 100 MB
});
WertBeschreibung
number (Bytes)Muss eine positive endliche Ganzzahl sein
weggelassenStandard 50 MB

Uploads über dem konfigurierten Limit werden beim direkten Upload mit 413 Payload Too Large abgelehnt, beim Signed-URL-Pfad mit 400 Validation Error.

admin

Optional. Ersetzt EmDash-Branding in der Admin-Oberfläche. Diese Werte ändern nicht Titel, Logo oder Favicon der öffentlichen Site.

emdash({
	admin: {
		logo: "/images/agency-logo.webp",
		siteName: "Agency CMS",
		favicon: "/favicon.ico",
	},
});
OptionTypBeschreibung
logostringLogo-URL oder -Pfad für Login-Seite und Sidebar
siteNamestringName in Sidebar und Browser-Titel
faviconstringFavicon-URL oder -Pfad für Admin-Seiten

toolbar

Optional. Steuert, wie die Editor-Toolbar (die schwebende Pill auf öffentlichen Seiten) ausgeliefert wird. Standard: "server".

WertVerhalten
"server" (Standard)Die Toolbar wird serverseitig in jede HTML-Response eingefügt, die für einen authentifizierten Editor gerendert wird.
"client"Öffentliches HTML ist für alle Besucher identisch. Ein kleines Bootstrap-Skript zeigt eine „Edit“-Pill in Browsern mit Admin-Login; Klick verifiziert die Session und lädt die Seite mit _edit-Query-Parameter neu, immer frisch (nie gecacht) mit voller Toolbar.
falseToolbar und Bootstrap-Skript nie rendern.
emdash({
	toolbar: "client",
})

Nutzen Sie "client", wenn öffentliches HTML über einen gemeinsamen Cache ausgeliefert wird (Cloudflare Cache Everything / Workers Cache, Fastly, Varnish, …). Bei serverseitiger Injektion erhält ein Editor auf der öffentlichen Site die gecachte anonyme Variante — ohne Toolbar — sobald ein anonymer Besucher den Cache zuerst befüllt hat; die Toolbar erscheint und verschwindet mit dem Cache-Zustand. Im Client-Modus wird nichts Session-Spezifisches in teilbares HTML injiziert; der Cache bleibt voll wirksam und die Toolbar ist zuverlässig.

Hinweise zum Modus "client":

  • Ausgeloggte Besucher mit geteilter ?_edit-URL werden zur kanonischen URL umgeleitet, damit der Parameter keine Entwürfe leakt oder zusätzliche Cache-Einträge mit Seiteninhalt befüllt.
  • Das „eingeloggt“-Signal ist ein nicht-geheimes localStorage-Flag vom Admin; die Pill verifiziert die echte Session vor der Edit-Ansicht.
  • Das Bootstrap ist ein kleines Inline-<script>. Sendet Ihre Site eine strenge Content-Security-Policy ohne 'unsafe-inline', fügen Sie einen Hash hinzu — dasselbe gilt für die serverseitig injizierte Toolbar.
  • EmDash injiziert nichts Session-Spezifisches — brancht Ihr Template aber auf Astro.locals.user (z. B. „Admin“-Nav-Link), liegt diese Varianz weiterhin im HTML und fragmentiert den Cache.

In jedem Modus kann die Toolbar im Browser über × geschlossen werden (pro Browser, bis ein Editor den Admin erneut öffnet). Preview- und Edit-Mode-Responses rendern immer serverseitig mit Cache-Control: private, no-store.

experimental

Optional. Opt-in-Features, deren Verhalten oder Wire-Format sich in Minor-Releases ändern oder entfernt werden können. Jedes Feld wird unabhängig aktiviert.

experimental.registry

Veraltet. Nutzen Sie die Top-Level-Option registry. Bestehende experimental.registry-Konfiguration funktioniert weiter, wenn die Top-Level-Option fehlt. Sind beide gesetzt, hat der Top-Level-Wert Vorrang.

Die folgende Änderung verschiebt eine bestehende Registry-URL auf die Top-Ebene:

emdash({
	experimental: {
		registry: "https://registry.example.com",
	},
	registry: "https://registry.example.com",
});

Datenbank-Adapter

Importieren Sie die Adapter aus emdash/db:

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

sqlite(config)

SQLite-Datenbank mit Node.js’ eingebautem Datenbanktreiber. Das folgende Beispiel verbindet mit einer lokalen Datei:

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

libsql(config)

libSQL-Datenbank. Das folgende Beispiel verbindet mit einer remote libSQL-Datenbank:

OptionTypBeschreibung
urlstringDatenbank-URL
authTokenstringAuth-Token zur Laufzeit (optional für lokale Dateien)
migrationAuthTokenEnvstringName der Migrations-Token-Variable (Standard TURSO_AUTH_TOKEN)
libsql({
	url: process.env.LIBSQL_DATABASE_URL,
	authToken: process.env.LIBSQL_AUTH_TOKEN,
});

postgres(config)

PostgreSQL-Datenbank mit Connection Pooling.

OptionTypBeschreibung
connectionStringstringPostgreSQL-Verbindungs-URL
hoststringDatenbank-Host
portnumberDatenbank-Port
databasestringDatenbankname
userstringDatenbank-Benutzer
passwordstringDatenbank-Passwort
sslbooleanSSL aktivieren
pool.minnumberMinimale Pool-Größe (Standard: 0)
pool.maxnumberMaximale Pool-Größe (Standard: 10)
pool.connectionTimeoutMillisnumberMax. Wartezeit auf Verbindung (pg-Standard: 0, kein Timeout)
pool.idleTimeoutMillisnumberLebensdauer idle Clients (pg-Standard: 10.000 ms)
migrationConnectionStringEnvstringName der Migrations-Connection-String-Variable (Standard DATABASE_URL)

Das folgende Beispiel verbindet mit einem Connection String:

postgres({ connectionString: process.env.DATABASE_URL });

d1(config)

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

OptionTypStandardBeschreibung
bindingstring—D1-Binding-Name aus wrangler.jsonc
sessionstring"disabled"Read-Replication-Modus: "disabled", "auto" oder "primary-first"
bookmarkCookiestring"__em_d1_bookmark"Cookie-Name für Session-Bookmarks
coalescebooleanfalseBündelt parallele Reads im selben Event-Loop-Turn; erfordert Session-Modus ≠ "disabled"

Das folgende Beispiel zeigt ein einfaches Binding und eines mit Read Replicas:

// Basic
d1({ binding: "DB" });

// With read replicas
d1({ binding: "DB", session: "auto" });

Ist session "auto" oder "primary-first", nutzt EmDash die D1 Sessions API, um Read-Queries zu nahen Replicas zu routen. Authentifizierte Nutzer erhalten bookmark-basierte Read-your-writes-Konsistenz. Details unter Datenbank wählen — Read Replicas.

hyperdrive(config?)

PostgreSQL über ein Cloudflare-Hyperdrive-Binding. Import dieses Adapters aus @emdash-cms/cloudflare.

OptionTypStandardBeschreibung
bindingstring"HYPERDRIVE"Primäres Hyperdrive-Binding ohne Query-Caching
cachedBindingstring—Optionales zweites, caching-fähiges Binding für anonyme öffentliche Reads
preferUncachedAfterWriteMsnumber60_000Wie lange öffentliche Reads nach Content-Write das Primary nutzen, wenn cachedBinding gesetzt ist
migrationConnectionStringEnvstringVom Primary-Binding abgeleitetEnv-Variable mit direkter PostgreSQL-URL für emdash migrate
maxnumber5Max. Verbindungen von einem Worker-Isolate zu Hyperdrive

Das folgende Beispiel leitet authentifizierte Anfragen und Writes über das uncached Binding; anonyme öffentliche Reads können das cached Binding nutzen:

hyperdrive({
	binding: "HYPERDRIVE",
	cachedBinding: "HYPERDRIVE_CACHED",
	preferUncachedAfterWriteMs: 60_000,
});

Beide Bindings müssen auf dieselbe Datenbank zeigen. Installieren Sie pg ab Version 8.16.3, aktivieren Sie nodejs_compat und konfigurieren Sie eine direkte Datenbank-URL für Deployment-Migrationen. Vollständiges Worker- und Migrations-Setup unter Datenbank wählen: Hyperdrive.

durableObjects(config)

Speichert das CMS in einem SQLite-gestützten Durable Object. Import dieses Adapters aus @emdash-cms/cloudflare.

OptionTypStandardBeschreibung
bindingstringerforderlichDurable-Object-Namespace-Binding für die Klasse EmDashDB
namestring"emdash"Singleton-Objektname; nur ändern, um mehrere DBs hinter einem Binding zu isolieren
sessionstring"disabled""auto" routet anonyme Reads zu Replicas und Writes zum Primary
bookmarkCookiestring"__em_do_bookmark"Cookie für Read-your-writes-Konsistenz im Modus "auto"
durableObjects({ binding: "DB_DO", session: "auto" });

Replica-Routing erfordert die Compatibility-Flags experimental und replica_routing sowie Durable-Object-Klasse und Migrations-Einträge in wrangler.jsonc.

previewDatabase(config)

Erstellt pro Preview-Session eine isolierte Snapshot-Datenbank in einem Durable Object. Die einzige Option ist der erforderliche binding-Name:

previewDatabase({ binding: "PREVIEW_DB" });

Dieser Adapter ist für Preview-Infrastruktur, nicht als Primary-Datenbank einer Produktions-Site.

playgroundDatabase(config)

Erstellt pro Playground-Session eine beschreibbare, geseedete Datenbank in einem Durable Object. Kombinieren Sie ihn mit der Integrationsoption playground:

playgroundDatabase({ binding: "PLAYGROUND_DB" });

Das erforderliche binding identifiziert den Playground-Durable-Object-Namespace. Nutzen Sie diesen Adapter nur für wegwerfbare Demo-Sites.

Speicher-Adapter

Importieren Sie local und s3 aus emdash/astro. Der r2-Adapter kommt aus @emdash-cms/cloudflare:

import emdash, { local, s3 } from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";

local(config)

Speicher im lokalen Dateisystem. Das folgende Beispiel stellt Uploads aus einem lokalen Verzeichnis bereit:

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

r2(config)

Cloudflare-R2-Binding. Das folgende Beispiel nutzt ein R2-Binding mit öffentlicher URL:

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

s3(config?)

S3-kompatibler Speicher. Alle Config-Felder sind optional: Jedes in s3({...}) weggelassene Feld wird beim Start des Node-Prozesses aus der passenden S3_*-Umgebungsvariable aufgelöst. Explizite Werte haben immer Vorrang.

Nach dem Zusammenführen von Config und Umgebung sind endpoint und bucket erforderlich. Ist eine Credential gesetzt, sind accessKeyId und secretAccessKey beide erforderlich. Fehlende Werte brechen den Start mit Fehlercode MISSING_S3_CONFIG ab.

Voraussetzung: Installieren Sie @aws-sdk/client-s3 und @aws-sdk/s3-request-presigner in Ihrem Projekt. EmDash Core bündelt das AWS SDK nicht. Siehe Speicheroptionen: S3-kompatibler Speicher.

OptionTypBeschreibung
endpointstringS3-Endpoint-URL (S3_ENDPOINT)
bucketstringBucket-Name (S3_BUCKET)
accessKeyIdstringAccess Key (S3_ACCESS_KEY_ID)
secretAccessKeystringSecret Key (S3_SECRET_ACCESS_KEY)
regionstringRegion, Standard "auto" (S3_REGION)
publicUrlstringOptionale CDN-URL (S3_PUBLIC_URL)

Die folgenden Beispiele lösen alle Felder aus der Umgebung, mischen Config und Umgebung oder übergeben jedes Feld explizit:

// 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
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 nur auf Node verfügbar. Auf Cloudflare Workers werden Secrets und Variablen über den env-Parameter des Fetch-Handlers exponiert, nicht über process.env; S3_*-Umgebungsvariablen werden daher nicht gelesen. Workers-Deployments sollten entweder den r2(config)-Adapter nutzen oder explizite Werte an s3({...}) übergeben. Details unter Speicheroptionen.

Objekt-Cache-Adapter

Übergeben Sie einen davon an die Option objectCache.

kvCache(config)

Cloudflare-KV-Backend, über alle Isolates geteilt. Import aus @emdash-cms/cloudflare.

kvCache({
	binding: "CACHE", // KV binding name (required)
	defaultTtl: 3600, // entry TTL in seconds (optional, KV minimum 60)
	revalidate: 1000, // cross-isolate staleness window in ms (optional)
	timeout: 2000, // per-op timeout in ms before a miss (optional, 0 disables)
	keyPrefix: "em", // cache key prefix (optional)
})

memoryCache(config?)

In-Process-Backend für Node.js und Entwicklung. Import aus emdash/astro.

memoryCache({
	defaultTtl: 3600, // entry TTL in seconds (optional)
	revalidate: 1000, // staleness window in ms (optional)
	maxEntries: 1000, // max cached keys before eviction (optional)
	keyPrefix: "em", // cache key prefix (optional)
})

Setup und Verhalten unter Objekt-Cache.

Authentifizierungs- und Sandbox-Adapter

Diese Adapter liefern Werte für die Integrationsoptionen auth und sandboxRunner.

access(config)

Ersetzt den eingebauten Passkey-Login durch Cloudflare-Access-Authentifizierung. Import aus @emdash-cms/cloudflare und Ergebnis an auth übergeben:

import { access } from "@emdash-cms/cloudflare";

emdash({
	auth: access({
		teamDomain: "myteam.cloudflareaccess.com",
		audienceEnvVar: "CF_ACCESS_AUDIENCE",
	}),
});

teamDomain ist erforderlich. Der Adapter kann die Application Audience aus audience oder der von audienceEnvVar benannten Variable lesen; er akzeptiert auch autoProvision, defaultRole, syncRoles und roleMapping. Die Option auth dokumentiert deren Defaults und Rollenverhalten.

sandbox()

Wählt Cloudflare Worker Loader als Plugin-Sandbox-Runner. Import aus @emdash-cms/cloudflare und Rückgabewert an sandboxRunner übergeben:

import { sandbox } from "@emdash-cms/cloudflare";

emdash({
	sandboxRunner: sandbox(),
});

Die Site braucht außerdem ein Worker-Loader-Binding und den Plugin-Bridge-Einstiegspunkt. Deployment-Einstellungen unter Plugin-Sandbox: Cloudflare Workers.

Medienanbieter-Adapter

Übergeben Sie Medienanbieter-Deskriptoren an mediaProviders. Beide eingebauten Cloudflare-Anbieter importieren Sie aus @emdash-cms/cloudflare.

Jede *EnvVar-Option unten benennt eine Umgebungsvariable. Der Anbieter liest in dieser Reihenfolge: Cloudflare-Workers-Binding dieses Namens, dann process.env auf dem Node-Adapter. Die passende Direktoption (accountId, accountHash, apiToken) hat immer Vorrang vor beiden.

cloudflareImages(config)

Fügt Cloudflare Images zum Durchsuchen, Hochladen, Löschen und Ausliefern von Bild-Assets hinzu.

OptionTypStandardBeschreibung
accountIdstringAus CF_ACCOUNT_IDCloudflare-Account-ID
accountIdEnvVarstring"CF_ACCOUNT_ID"Variable, wenn accountId fehlt
accountHashstringAus CF_IMAGES_ACCOUNT_HASHAccount-Hash in Delivery-URLs
accountHashEnvVarstring"CF_IMAGES_ACCOUNT_HASH"Variable, wenn accountHash fehlt
apiTokenstringAus CF_IMAGES_TOKENToken mit Cloudflare-Images-Lese- und -Schreibrechten
apiTokenEnvVarstring"CF_IMAGES_TOKEN"Variable, wenn apiToken fehlt
deliveryDomainstringimagedelivery.netHostname für Bild-Delivery
defaultVariantstring"public"Bildvariante für die Anzeige
mediaProviders: [cloudflareImages({ defaultVariant: "public" })];

cloudflareStream(config)

Fügt Cloudflare Stream zum Durchsuchen, Suchen, Hochladen, Löschen und Abspielen von Video-Assets hinzu.

OptionTypStandardBeschreibung
accountIdstringAus CF_ACCOUNT_IDCloudflare-Account-ID
accountIdEnvVarstring"CF_ACCOUNT_ID"Variable, wenn accountId fehlt
apiTokenstringAus CF_STREAM_TOKENToken mit Cloudflare-Stream-Lese- und -Schreibrechten
apiTokenEnvVarstring"CF_STREAM_TOKEN"Variable, wenn apiToken fehlt
customerSubdomainstringCloudflare-StandardHostname für Stream-Delivery
controlsbooleantruePlayer-Steuerung anzeigen
autoplaybooleanfalseWiedergabe automatisch starten
loopbooleanfalseWiedergabe wiederholen
mutedbooleanfalse, oder true mit AutoplayStumm schalten
mediaProviders: [cloudflareStream({ controls: true })];

Erforderliche Bindings und Rendering-Komponenten unter Medienbibliothek: Medienanbieter.

Astro-Cache-Adapter

cloudflareCache(config?)

Der Legacy-Adapter liefert einen Astro-cache.provider, der Responses in der Workers Cache API speichert und Cache-Tags über die Cloudflare-REST-API purgt:

import { cloudflareCache } from "@emdash-cms/cloudflare";

export default defineConfig({
	cache: {
		provider: cloudflareCache(),
	},
});

Er akzeptiert cacheName (Standard "emdash") und bookmarkCookie (Standard "__em_d1_bookmark"), plus zoneId oder zoneIdEnvVar und apiToken oder apiTokenEnvVar für Purge-by-Tag-Anfragen. Standard-Variablennamen sind CF_ZONE_ID und CF_CACHE_PURGE_TOKEN.

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() hat keine Argumente:

emdashLoader();

Umgebungsvariablen

EmDash berücksichtigt diese Umgebungsvariablen:

VariableBeschreibung
EMDASH_SITE_URLÖffentliche Browser-Origin (Fallback: SITE_URL)
EMDASH_ALLOWED_ORIGINSKommagetrennte Liste zusätzlicher Origins für Passkey-Verifikation (Multi-Subdomain-Deployments).
EMDASH_DATABASE_URLDatenbank-URL überschreiben
EMDASH_ENCRYPTION_KEYSchlüssel zum Verschlüsseln von Plugin-Secrets at rest. Vom Betreiber — nie in der DB gespeichert.
EMDASH_PREVIEW_SECRETOptionales Override für Preview-HMAC-Secret. Ohne Wert: stabiler per-Site-Wert, in der DB gespeichert.
EMDASH_IP_SALTOptionales Override für Kommentar-IP-Hash-Salt. Ohne Wert: stabiler per-Site-Wert in der DB.
EMDASH_AUTH_SECRETLegacy. IP-Salt-Quelle, wenn gesetzt; bestehende Installationen beibehalten für stabile Kommentar-IP-Hashes nach Upgrade.
EMDASH_TURNSTILE_SECRET_KEYCloudflare-Turnstile-Secret (Fallback TURNSTILE_SECRET_KEY). Wenn gesetzt, müssen Kommentare ein gültiges Turnstile-Token enthalten — mit turnstileSiteKey auf <CommentForm> kombinieren.
EMDASH_URLRemote-EmDash-URL für Schema-Sync

Verschlüsselungsschlüssel mit folgendem Befehl erzeugen:

npx emdash secrets generate

package.json-Konfiguration

Templates und Sites können optionale Metadaten unter dem Schlüssel emdash in package.json deklarieren:

{
	"emdash": {
		"label": "My Blog Template",
		"schema": ".emdash/schema.sql",
		"seed": ".emdash/seed.json",
		"url": "https://my-site.pages.dev"
	}
}
OptionBeschreibung
labelTemplate-Name zur Anzeige
schemaOptionales SQL-Schema für emdash init
seedPfad zur Seed-JSON-Datei
urlRemote-URL für den veralteten emdash dev --types-Flow

TypeScript-Konfiguration

In der lokalen Entwicklung erzeugt die Astro-Integration emdash-env.d.ts im Projektroot und aktualisiert sie nach Schema-Änderungen. Die Datei erweitert das Modul emdash, sodass Standard-Imports getEmDashCollection() und getEmDashEntry() lokale Collection-Felder ohne Path-Alias inferieren.

Der separate Befehl emdash types holt das Schema von einer laufenden lokalen oder remote Instanz und schreibt standardmäßig .emdash/types.ts. Alias nur hinzufügen, wenn Anwendungscode diese standalone Ausgabe direkt importiert:

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

Standalone Remote-Schema-Typen mit folgendem Befehl erzeugen:

npx emdash types