Referencia de configuración

En esta página

La configuración principal de EmDash está en astro.config.mjs, mientras que src/live.config.ts registra el cargador de contenido. Los valores específicos del despliegue también pueden provenir de variables de entorno. Un pequeño bloque de metadatos emdash en package.json admite etiquetas de plantilla y flujos CLI locales heredados.

Integración de Astro

Configure EmDash como integración de Astro en 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: [],
		}),
	],
});

Opciones de integración

database

Obligatorio. Configuración del adaptador de base de datos. Elija un adaptador:

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

Consulte Opciones de base de datos para más detalles.

migrations

Opcional. Controla el tratamiento en tiempo de ejecución de las migraciones internas de la base de datos de EmDash. Si se omite, el valor predeterminado es { runtime: "auto" }.

migrations: {
	runtime: "check", // "auto" | "check" | "manual"
	dev: "auto",     // anulación opcional en desarrollo
}

auto comprueba y aplica las migraciones pendientes, check devuelve 503 cuando hay migraciones pendientes conocidas por la compilación en ejecución, y manual no ejecuta ninguna consulta de migración en tiempo de ejecución. EMDASH_MIGRATIONS_MODE anula la modalidad de tiempo de ejecución efectiva. Consulte Gestionar migraciones del núcleo de la base de datos antes de adoptar check o manual.

storage

Opcional. Configuración del adaptador de almacenamiento de medios. Cuando se omite, EmDash guarda los archivos en ./.emdash/uploads y los sirve a través de /_emdash/api/media/file. Elija un adaptador cuando el directorio local predeterminado no sea adecuado:

// 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.con",
	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.con", // optional
});

Consulte Opciones de almacenamiento para más detalles.

images

Opcional. Controla si EmDash integra medios almacenados con la optimización de imágenes de Astro. El valor predeterminado es true.

Cuando está habilitado, EmDash envuelve el endpoint de imágenes de Astro para que <Image> e getImage() lean los bytes de origen directamente del adaptador de almacenamiento configurado. Esto también funciona cuando la URL de medios original está detrás de Cloudflare Access. Defina images: false cuando otro servicio de imágenes gestione los medios o cuando cada imagen deba renderizarse sin el envoltorio del endpoint de EmDash.

emdash({
	images: false,
});

mediaProviders

Opcional. Añade servicios de medios a biblioteca de medios. El proveedor local baseado en almacenamiento permanece disponible automaticamente; cada descritor en este array añade outro lugar donde editores pueden navegar o subir medios.

El ejemplo siguiente añade Cloudflare Images y Cloudflare Stream:

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

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

Las credenciales de los proveedores son resolvidas en tiempo de ejecución. As configuraciones vacías acima usan as variables de ambiente predeterminado de Cloudflare descritas en las secciones de los adaptadores cloudflareImages(config) e cloudflareStream(config). Consulte Biblioteca de medios: proveedores de medios para configuración de bindings y renderización.

objectCache

Opcional. Almacena en cache resultados de consultas de contenido e configuración en un almacenamiento chave/valor, para que lecturas se sirvan sin consultar la base de datos en cada solicitud. Deshabilitado cuando omitido. Elija un adaptador:

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

Consulte Cache de objetos para configuración e opciones.

middleware.outer

Opcional. Registra un módulo de middleware Astro fuera de la pilha completa de middleware de EmDash. Como la integración o registra en Astro con order: "pre", también ejecuta antes del middleware definido en src/middleware.ts. Úselo para puertas de solicitud o caches de resposta completa que deben evitar inicialización de runtime e base de datos en un hit, o para encabezados de resposta que dependen del HTML final de EmDash.

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

El orden de ejecución es:

  1. El middleware externo ejecuta até await next().
  2. O EmDash inicializa runtime e base de datos, depois ejecuta middleware de setup, autenticación e contexto de solicitud.
  3. A rota Astro renderiza.
  4. O EmDash aplica mutaciones de resposta, incluyendo HTML de edición visual y encabezados de seguridad/timing.
  5. next() resolve para o middleware externo con essa resposta final.

Antes de llamar next(), o middleware tiene el contexto normal de solicitud Astro e de ejecución de la plataforma, mas locals.emdash, locals.user, la base de datos e o estado EmDash escopado a solicitud no están disponíveis. Una Response antecipada ignora EmDash por completo, entonces deve incluir os encabezados de seguridad e cache necesarios. Después de que next() resolve, es seguro finalizar nonces CSP, almacenar en caché el corpo completo o definir Content-Length. Si el middleware alterar o corpo, elimine o recalcule cualquier encabezado Content-Length existente.

El hook usa la API de middleware de Astro tanto en Node como en Cloudflare. Este ejemplo mínimo de la Cloudflare Cache API almacena en caché solo respuestas HTML anónimas e devuelve hits antes de la inicialización de EmDash:

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

En Node, use la mesma forma de middleware con un cache compatible con Node, como Redis. Claves de cache e regras de bypass deben incluir toda propiedad de solicitud que cambia a resposta renderizada.

playground

Opcional. Habilita el middleware usado por playgrounds EmDash desechables basados en el navegador. Crea una base de datos Durable Object escribible por sesión, aplica el seed configurado y autentica al visitante como administrador anónimo antes de que se ejecute el middleware normal de EmDash.

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

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

Este modo requiere @emdash-cms/cloudflare y un binding Durable Object. Omite el middleware normal de configuración y autenticación; úselo solo para sitios de demostración efímeros, no para un CMS de producción.

plugins

Opcional. Array de plugins que executam no mesmo processo del site Astro. Plugins nativos pertencem aqui. Um plugin compatible con sandbox también pode executar aqui cuando você confia nele con acesso total ao processo e no precisa de isolamento.

El ejemplo siguiente registra un plugin nativo:

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

plugins: [seoPlugin()];

Plugins nativos pueden usar APIs de servidor y framework directamente, entonces no pueden ser movidos para sandboxed a menos que o paquete también proporcione un ponto de entrada de plugin compatible con sandbox. Consulte Elegir un formato de plugin para diferencias de autoría y despliegue.

sandboxed

Opcional. Array de plugins compatíveis con sandbox que usan as APIs de plugin declaradas de EmDash e executam en tiempo de ejecucións isolados. No coloque un plugin nativo aqui: código nativo pode depender de acesso a processo y framework que o sandbox no fornece.

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

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

Plugins en sandbox son ignorados cuando nenhum sandbox runner utilizável está configurado. Consulte Sandbox de plugins para configuración del runner no Cloudflare e Node.js.

sandboxRunner

Opcional. Especificador de módulo de la factory que inicia runtimes de plugin isolados. É obligatorio para plugins en sandboxed e para plugins del marketplace o registro.

No Cloudflare Workers, use o adaptador sandbox():

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

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

Despliegues Node.js usan o módulo runner workerd documentado en Sandbox de plugins: Node.js.

sandbox

Opcional. Controla si un sandbox runner configurado isola plugins. O sandboxing es habilitado cuando sandboxRunner está configurado. Defina sandbox: false solo para diagnosticar si un problema vem del plugin o del runtime de sandbox:

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

Com false, plugins declarados en sandboxed e instalados del marketplace executam no processo principal del servidor sem isolamento o limites de recursos. Restaure o sandboxing após o diagnóstico.

registry

Opcional. Configura o agregador y la política del registro de plugins. Sem valor explícito, EmDash usa https://registry.emdashcms.con cuando sandboxRunner está configurado y sandbox no es false.

Defina registry: false para deshabilitar descoberta del registro e plugins instalados por la registro, mantendo o sandbox runner disponible para plugins declarados en sandboxed e plugins legados del Marketplace:

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

Pase la URL del servicio de registro como string, o use un objeto cuando o site neceritar de fontes de moderación o política de idade de release. El ejemplo siguiente usa la forma de objeto:

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

emdash({
	sandboxRunner: sandbox(),
	registry: {
		aggregatorUrl: "https://registry.emdashcms.con",
		acceptLabelers: "did:web:labels.emdashcms.con",
		policy: {
			minimumReleaseAge: "48h",
			minimumReleaseAgeExclude: ["did:plc:yourfirstpartydid"],
		},
	},
});
OpciónTipoDescripción
aggregatorUrlstringURL base del servicio de registro. Use HTTPS en producción.
acceptLabelersstringIdentificadores descentralizados (DIDs) opcionais, separados por coma, de servicios de moderación aceptados por la solicitud. Um DID es un identificador estável de conta Atmosphere. Esta configuración no puede sustituir la política del servicio de registro.
policy.minimumReleaseAgestring | numberRetiene releases más recientes que esta idade. String de duración ("48h", "7d") o segundos.
policy.minimumReleaseAgeExcludestring[]DIDs de publicadores o pares <did>/<plugin-slug> exentos de la retención.

La política de antigüedad de release exime el primer release de un paquete solo cuando el registro informa de un release retenido y confirma que observó el paquete de forma continua. Un paquete rellenado retroactivamente, un release anterior eliminado o evidencia de historial ausente mantienen la retención. Las exenciones explícitas de publicador y paquete se aplican con independencia del historial.

Consulte El registro de plugins para fluxo de instalação e modelo de confiança.

marketplace

Obsoleto. URL base usada para atualizar plugins instalados del Marketplace legado. Navegação e novas instalações del Marketplace no aparecem no admin. Plugins existentes del Marketplace permanecem atualizáveis e desinstaláveis enquanto esta opção estiver configurada.

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

URLs de producción deben usar HTTPS; HTTP es aceito solo para localhost y 127.0.0.1 durante o desarrollo. Mantenha esta opção até que todo plugin del Marketplace tenha sido substituído o desinstalado, depois elimine-a. Siga Migrar desde Marketplace para o procedimento completo.

fonts

Opcional. Configuración de fontes de la UI del admin.

De forma predeterminada, EmDash carrega Noto Sans via a Astro Font API. As fontes son baixadas de Google no build e auto-hospedadas, sem solicitudes CDN en tiempo de ejecución. A fonte base cobre scripts latino, cirílico, grego, devanagari e vietnamita.

Para adicionar suporte a sistemas de escrita adicionais, passe nomes de scripts. El ejemplo siguiente añade árabe e japonês:

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

Os scripts disponíveis son 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 y tibetan.

Cada script mapeia para a variante Noto Sans correspondente no Google Fonts (por exemplo, "arabic" carrega Noto Sans Arabic). Todas as faces compartilham un único nome font-family e usan unicode-range para o navegador baixar solo os archivos necesarios aos caracteres de la página.

Defina false para deshabilitar totalmente a injeção de fontes e usar fontes del sistema:

emdash({
	fonts: false,
})

O CSS del admin usa la variable CSS --font-emdash, definida automaticamente pela configuración de fontes acima.

auth

Opcional. Um adaptador de autenticación. O login integrado de EmDash usa passkeys; definir auth anula passkeys por un proveedor externo. O adaptador Cloudflare Access, access(), es fornecido por @emdash-cms/cloudflare:

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

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

Opciones de access():

OpciónTipoPredeterminadoDescripción
teamDomainstringobligatorioDomínio de la equipe Cloudflare Access
audiencestring—Tag Application Audience (AUD). En Workers, prefira audienceEnvVar.
audienceEnvVarstring"CF_ACCESS_AUDIENCE"Variable de ambiente para ler a tag de audience en tiempo de ejecución
autoProvisionbooleantrueCriar usuario EmDash no primeiro login
defaultRolenumber30Nível de rol para usuarios no correspondidos por roleMapping (consulte Roles de usuario)
syncRolesbooleanfalseReaplicar roleMapping en cada login en vez de solo no provisionamento
roleMappingobject—Mapeia nomes de grupos IdP para níveis de rol EmDash; a primeira correspondência vence

authProviders

Opcional. Array de proveedores de login plugáveis (nível superior, junto con auth). Cada entrada es o resultado de chamar una factory de proveedor, como abaixo:

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

Provedores integrados:

  • github() — lê EMDASH_OAUTH_GITHUB_CLIENT_ID / EMDASH_OAUTH_GITHUB_CLIENT_SECRET (ou fallbacks sem prefixo).
  • google() — lê EMDASH_OAUTH_GOOGLE_CLIENT_ID / EMDASH_OAUTH_GOOGLE_CLIENT_SECRET.
  • atproto() — login con conta Atmosphere (Bluesky y la rede AT Protocol mais ampla). No requiere variables de ambiente. Aceita { allowedDIDs, allowedHandles, defaultRole }. Consulte o guia de login Atmosphere.

Pacotes de terceiros pueden registrar seus próprios proveedores usando a mesma forma AuthProviderDescriptor — consulte Proveedores de inicio de sesión.

mcp

Opcional. Habilita el endpoint Model Context Protocol (MCP) en /_emdash/api/mcp. El endpoint está habilitado de forma predeterminada y requiere un token bearer; habilitarlo no concede acceso anónimo.

Defina a opção como false cuando o site no deve expor un endpoint MCP:

emdash({
	mcp: false,
});

Consulte Referencia del servidor MCP para criação de token e configuración de cliente.

siteUrl

Origem pública voltada ao navegador del site (esquema + host + porta opcional, sem path). Defina-a antes de executar o setup de producción. Apenas hosts de desarrollo loopback pueden concluir o setup sem origem configurada.

Atrás de un proxy reverso con terminação TLS, Astro.url devuelve o endereço interno (http://localhost:4321) en vez del público (https://cms.example.con). Esto quebra passkeys, correspondência de origem CSRF, redirects OAuth, redirects de login, descoberta MCP, exportações de snapshot, sitemap, robots.txt e dados estruturados JSON-LD. Defina siteUrl para corrigir tudo de una vez.

A integración valida este valor no carregamento: deve ser una URL válida con protocolo http: o https: e es normalizada para origin (o path es removido).

El ejemplo siguiente define a origem pública:

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

Cuando siteUrl no está definido na config, EmDash comprueba variables de ambiente nesta ordem: EMDASH_SITE_URL, depois SITE_URL. Esto es útil para implantações en contêiner donde a URL pública es definida en tiempo de ejecución.

O setup falha con SITE_URL_REQUIRED en host no loopback cuando nenhuma fonte está definida. Esto impede que a primeira solicitud de setup no autenticada escolha a origem usada en e-mails de autenticación posteriores.

No Cloudflare Workers, o fallback por variable de ambiente lê process.env. Com nodejs_compat, o Cloudflare popula process.env por predeterminado para datas de compatibilidade en o após 2025-04-01. Projetos fixados en data anterior también deben adicionar nodejs_compat_populate_process_env.

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

allowedOrigins

Opcional. Origens adicionais de navegador aceitas pela verificação de passkey para una despliegue disponible en mais de un hostname.

siteUrl define una única origem canônica. Cuando a mesma despliegue EmDash es acessível por vários hostnames que compartilham un domínio pai registrável (por exemplo, https://example.con y https://preview.example.con), a verificação de passkey rejeita asserções cuja origem no corresponde exatamente a siteUrl — mesmo que WebAuthn permita passkeys válidas entre subdomínios sob o mesmo rpId.

Declare origens adicionais aceitas via allowedOrigins en astro.config.mjs o a variable de ambiente EMDASH_ALLOWED_ORIGINS. A siteUrl canônica permanece a fonte de rpId; entradas listadas aqui son aceitas na verificação. As duas fontes son mescladas en tiempo de ejecución, para a config declarar origens estáveis (versionadas, revisadas en código) enquanto o env añade extras específicos del ambiente (por exemplo, previews efímeros de PR).

El ejemplo siguiente declara una origem extra na config:

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

Valores equivalentes también pueden vir de variables de ambiente:

EMDASH_SITE_URL=https://example.con
EMDASH_ALLOWED_ORIGINS=https://preview.example.con,https://staging.example.con
Validación

O EmDash valida estes valores para evitar config morta que o navegador nunca honraria:

  • Cada entrada deve ser una URL http: o https: analisável, sem ponto final e sem rótulos vazios no hostname.
  • Cuando allowedOrigins no está vazio, siteUrl deve estar definido (cualquier fonte) e no deve ser literal IP nem hostname con ponto final.
  • Cada origem deve ser o mesmo hostname que siteUrl o un subdomínio dele. (WebAuthn requiere que rpId seja sufixo registrável de toda origem.)

Cuando a validação falha, você verá un erro atribuído a fonte como EmDash config error in EMDASH_ALLOWED_ORIGINS: "https://other-site.con" is not a subdomain of siteUrl "https://example.con". Allowed origins must be the same hostname as siteUrl or a subdomain of it.

Onde o erro aparece depende de donde os valores son declarados:

  • Na inicialización de Astro, cuando config.allowedOrigins y config.siteUrl vêm de astro.config.mjs — erros de digitação no código falham o build.
  • Na primeira verificação de passkey, cuando cualquier valor vem de EMDASH_ALLOWED_ORIGINS o EMDASH_SITE_URL — incompatibilidades de env aparecem como 500 na primeira tentativa de verificação.

Configuración de proxy reverso

O Astro só reflete X-Forwarded-* cuando o host público es permitido. Configure security.allowedDomains para o hostname (e esquemas) que seus usuarios acessam. Em astro dev, adicione vite.server.allowedHosts correspondentes para o Vite aceitar o encabezado Host del proxy.

Prefira corrigir allowedDomains (e encabezados encaminhados) primeiro; use siteUrl cuando a URL reconstruída ainda divergir de la origem del navegador (típico cuando TLS termina na frente y la solicitud upstream permanece http://).

Com TLS na frente, vincular o servidor de dev ao loopback (astro dev --host 127.0.0.1) costuma ser suficiente: o proxy conecta localmente enquanto siteUrl corresponde a origem HTTPS pública.

Si el proxy grava un encabezado de IP del cliente, defina trustedProxyHeaders para os rate limits de EmDash usarem o IP real del cliente en vez de agrupar toda solicitud sob una chave compartilhada “unknown”.

A configuración a seguir define allowedDomains, vite.server.allowedHosts y siteUrl juntos para despliegue con proxy reverso:

import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";

export default defineConfig({
	security: {
		allowedDomains: [
			{ hostname: "cms.example.con", protocol: "https" },
			{ hostname: "cms.example.con", protocol: "http" },
		],
	},
	vite: {
		server: {
			allowedHosts: ["cms.example.con"],
		},
	},
	integrations: [
		emdash({
			database: sqlite({ url: "file:./data.db" }),
			storage: local({
				directory: "./uploads",
				baseUrl: "/_emdash/api/media/file",
			}),
			siteUrl: "https://cms.example.con",
		}),
	],
});

trustedProxyHeaders

Opcional. Cabeçalhos confiáveis para resolução de IP del cliente ao executar atrás de un proxy reverso que você controla. Usado por rate limits de auth (magic-link, signup, passkey, fluxo de dispositivo OAuth) e por la endpoint público de comentários.

No Cloudflare, o objeto cf anexado a solicitud es usado automaticamente — normalmente não es necessário definir isto. Em implantações self-hosted atrás de nginx, Caddy, Traefik, Fly, Railway o similar, defina o encabezado que seu proxy grava para rate limits agruparem por IP real del cliente en vez de tratar toda solicitud como “unknown”.

El ejemplo siguiente confia no encabezado x-real-ip definido por nginx, Caddy o Traefik:

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

Os encabezados son tentados en ordem. Valores que correspondem a *-forwarded-sea son analisados como listas separadas por coma y la primeira entrada es usada. El ejemplo siguiente prefere o encabezado del Fly.io e faz fallback para x-forwarded-sea:

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

Cuando no definido na config, EmDash lê a variable de ambiente EMDASH_TRUSTED_PROXY_HEADERS (separada por comas). Um array vazio explícito na config anula a variable de ambiente.

maxUploadSize

Opcional. Tamanho máximo permitido de upload de archivo de medios en bytes. Aplica-si a uploads multipart diretos e uploads por URL assinada. Padrão 52_428_800 (50 MB). El ejemplo siguiente eleva o limite para 100 MB:

emdash({
	database: sqlite({ url: "file:./data.db" }),
	storage: local({
		directory: "./uploads",
		baseUrl: "/_emdash/api/media/file",
	}),
	maxUploadSize: 100 * 1024 * 1024, // 100 MB
});
ValorDescripción
number (bytes)Deve ser inteiro finito positivo
omitidoPredeterminado 50 MB

Uploads que excedem o limite configurado son rejeitados con resposta 413 Payload Too Large no caminho de upload direto, o 400 Validation Error no caminho de URL assinada.

admin

Opcional. Substitui a marca EmDash na interface del admin. Estes valores no alteram título, logo o favicon del site público.

emdash({
	admin: {
		logo: "/images/agency-logo.webp",
		siteName: "Agency CMS",
		favicon: "/favicon.ico",
	},
});
OpciónTipoDescripción
logostringURL o path del logo na página de login e sidebar
siteNamestringNome exibido na sidebar e no título del navegador
faviconstringURL o path del favicon nas páginas del admin

toolbar

Opcional. Controla como a barra de ferramentas del editor (o pill flutuante nas páginas públicas) es entregue. Padrão "server".

ValorComportamento
"server" (padrão)A barra es injetada no servidor en toda resposta HTML renderizada para un editor autenticado.
"client"O HTML público es idêntico para todo visitante. Um pequeno script bootstrap mostra un pill “Edit” en navegadores que fizeram login no admin; ao clicar, comprueba a sessão e recarrega a página con parâmetro de query _edit, sempre renderizada fresca (nunca en cache) con la barra completa.
falseNunca renderiza a barra nem o script bootstrap.
emdash({
	toolbar: "client",
})

Use "client" cuando seu HTML público es servido por cache compartilhado (Cloudflare Cache Everything / Workers Cache, Fastly, Varnish, …). Com injeção no servidor, un editor navegando o site público recebe a variante anônima en cache — sem a barra — sempre que un visitante anónimo preencheu o cache primeiro, entonces a barra aparece e desaparece conforme o estado del cache. No modo client, nada específico de sessão es injetado no HTML compartilhável, o cache permanece totalmente efectivo y la barra es confiável.

Notas sobre o modo "client":

  • Visitantes deslogados que abrem una URL compartilhada ?_edit son redirecionados para a URL canônica, para o parâmetro no vazar rascunhos nem preencher entradas extras de cache con contenido de la página.
  • O sinal de “logado” es una flag localStorage no secreta definida por la admin; o pill comprueba a sessão real antes de entrar na visão de edição.
  • O bootstrap es un <script> inline pequeno. Se seu site envia Content-Security-Policy estrita sem 'unsafe-inline', adicione un hash — o mesmo vale para a barra injetada no servidor.
  • O EmDash no injeta nada específico de sessão — mas si seus templates ramificam en Astro.locals.user (por exemplo, link “Admin” para usuarios logados), essa variação ainda está no HTML e ainda fragmenta o cache.

Em todo modo, a barra pode ser dispensada no navegador por la botão × (por navegador, até a próxima vez que un editor abrir o admin). Respostas de preview e modo de edição sempre renderizam no servidor con Cache-Control: private, no-store.

experimental

Opcional. Recursos opt-in cujo comportamento o formato wire pode mudar o ser removido en release minor. Cada campo es habilitado independentemente.

experimental.registry

Obsoleto. Use a opção de nível superior registry. Configuración experimental.registry existente continua funcionando cuando a opção de nível superior es omitida. Se ambas estiverem presentes, o valor de nível superior prevalece.

A alteração a seguir move una URL de registro existente para o nível superior:

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

Adaptadores de base de datos

Importe os adaptadores de emdash/db:

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

sqlite(config)

Banco SQLite usando o driver de banco integrado de Node.js. El ejemplo siguiente conecta a un archivo local:

OpciónTipoDescripción
urlstringCaminho de archivo con prefixo file:
sqlite({ url: "file:./data.db" });

libsql(config)

Banco libSQL. El ejemplo siguiente conecta a un banco libSQL remoto:

OpciónTipoDescripción
urlstringURL de la base de datos
authTokenstringToken de auth en tiempo de ejecución (opcional para archivos locais)
migrationAuthTokenEnvstringNome de la variable del token de migración (padrão TURSO_AUTH_TOKEN)
libsql({
	url: process.env.LIBSQL_DATABASE_URL,
	authToken: process.env.LIBSQL_AUTH_TOKEN,
});

postgres(config)

Banco PostgreSQL con pool de conexões.

OpciónTipoDescripción
connectionStringstringURL de conexão PostgreSQL
hoststringHost del banco
portnumberPorta del banco
databasestringNome del banco
userstringUsuário del banco
passwordstringSenha del banco
sslbooleanHabilitar SSL
pool.minnumberTamanho mínimo del pool (padrão: 0)
pool.maxnumberTamanho máximo del pool (padrão: 10)
pool.connectionTimeoutMillisnumberEspera máxima de conexão (pg predeterminado: 0, sem timeout)
pool.idleTimeoutMillisnumberTempo de vida del cliente ocioso (pg predeterminado: 10.000 ms)
migrationConnectionStringEnvstringNome de la variable de la connection string de migración (padrão DATABASE_URL)

El ejemplo siguiente conecta con connection string:

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

d1(config)

Banco Cloudflare D1. Importe de @emdash-cms/cloudflare.

OpciónTipoPredeterminadoDescripción
bindingstring—Nome del binding D1 en wrangler.jsonc
sessionstring"disabled"Modo de replicação de leitura: "disabled", "auto" o "primary-first"
bookmarkCookiestring"__em_d1_bookmark"Nome del cookie para bookmarks de sessão
coalescebooleanfalseAgrupa lecturas concorrentes no mesmo turno del event loop; requiere modo de sessão diferente de "disabled"

El ejemplo siguiente mostra un binding básico e outro con réplicas de leitura habilitadas:

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

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

Cuando session es "auto" o "primary-first", EmDash usa la D1 Sessions API para rotear consultas de leitura para réplicas próximas. Usuários autenticados obtêm consistência read-your-writes baseada en bookmark. Consulte Opciones de base de datos — Réplicas de leitura para más detalles.

hyperdrive(config?)

PostgreSQL por un binding Cloudflare Hyperdrive. Importe este adaptador de @emdash-cms/cloudflare.

OpciónTipoPredeterminadoDescripción
bindingstring"HYPERDRIVE"Binding Hyperdrive principal con cache de consultas desabilitado
cachedBindingstring—Segundo binding opcional con cache habilitado para lecturas públicas anónimas
preferUncachedAfterWriteMsnumber60_000Por quanto tempo lecturas públicas usan o primário após escrita de contenido cuando cachedBinding está definido
migrationConnectionStringEnvstringDerivado del binding principalVariable de ambiente con la URL PostgreSQL direta usada por emdash migrate
maxnumber5Máximo de conexões de un isolate Worker ao Hyperdrive

El ejemplo siguiente roteia solicitudes autenticadas e gravações por la binding sem cache, enquanto lecturas públicas anónimas pueden usar o binding con cache:

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

Ambos os bindings deben apontar para o mesmo banco. Instale pg versão 8.16.3 o posterior, habilite a flag de compatibilidade nodejs_compat e configure una URL de banco direta para migraciones de despliegue. Consulte Opciones de base de datos: Hyperdrive para configuración completa de Worker e migración.

durableObjects(config)

Almacena o CMS en un Durable Object con SQLite. Importe este adaptador de @emdash-cms/cloudflare.

OpciónTipoPredeterminadoDescripción
bindingstringobligatorioBinding de namespace Durable Object para a classe EmDashDB
namestring"emdash"Nome del objeto singleton; altere solo para isolar vários bancos atrás de un binding
sessionstring"disabled""auto" roteia lecturas anónimas para réplicas e gravações para o primário
bookmarkCookiestring"__em_do_bookmark"Cookie usado para consistência read-your-writes no modo "auto"
durableObjects({ binding: "DB_DO", session: "auto" });

O roteamento de réplicas requiere as flags de compatibilidade experimental y replica_routing, além de la classe Durable Object e entradas de migración en wrangler.jsonc.

previewDatabase(config)

Cria un banco snapshot isolado por sesión de preview en un Durable Object. A única opção es o nome binding obligatorio:

previewDatabase({ binding: "PREVIEW_DB" });

Este adaptador es para infraestrutura de preview, no para o banco principal de un site de producción.

playgroundDatabase(config)

Cria un banco seeded escribible por sesión de playground en un Durable Object. Combine con la opção de integración playground:

playgroundDatabase({ binding: "PLAYGROUND_DB" });

O binding obligatorio identifica o namespace Durable Object del playground. Use este adaptador solo para sites de demostración desechables.

Adaptadores de almacenamiento

Importe local y s3 de emdash/astro. O adaptador r2 es importado de @emdash-cms/cloudflare:

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

local(config)

Armazenamento en filesystem local. El ejemplo siguiente serve uploads de un directorio local:

OpciónTipoDescripción
directorystringCaminho del directorio
baseUrlstringURL base para sirve archivos
local({
	directory: "./uploads",
	baseUrl: "/_emdash/api/media/file",
});

r2(config)

Binding Cloudflare R2. El ejemplo siguiente usa un binding R2 con URL pública:

OpciónTipoDescripción
bindingstringNome del binding R2
publicUrlstringURL pública opcional
r2({
	binding: "MEDIA",
	publicUrl: "https://pub-xxxx.r2.dev",
});

s3(config?)

Armazenamento compatible con S3. Todos os campos de config son opcionais: cualquier campo omitido en s3({...}) es resolvido de la variable de ambiente S3_* correspondente cuando o processo Node inicia. Valores explícitos sempre têm precedência.

Después de que config e ambiente son mesclados, endpoint y bucket son obligatorios. Se cualquier credencial sea definida, accessKeyId y secretAccessKey son obligatorios. Valores ausentes falham na inicialización con el código de erro MISSING_S3_CONFIG.

Pré-requisito: instale @aws-sdk/client-s3 y @aws-sdk/s3-request-presigner no seu projeto. O core de EmDash no inclui o AWS SDK. Consulte Opciones de almacenamiento: almacenamiento compatible con S3 para más detalles.

OpciónTipoDescripción
endpointstringURL del endpoint S3 (S3_ENDPOINT)
bucketstringNome del bucket (S3_BUCKET)
accessKeyIdstringAccess key (S3_ACCESS_KEY_ID)
secretAccessKeystringSecret key (S3_SECRET_ACCESS_KEY)
regionstringRegião, predeterminado "auto" (S3_REGION)
publicUrlstringURL CDN opcional (S3_PUBLIC_URL)

Os exemplos a seguir resolvem todos os campos del ambiente, misturam config e ambiente o passam cada campo explicitamente:

// All fields from S3_* environment variables (Node container deployments)
s3()

// Mix: CDN from config, rest from environment
s3({ publicUrl: "https://cdn.example.con" })

// All explicit
s3({
	endpoint: "https://xxx.r2.cloudflarestorage.con",
	bucket: "media",
	accessKeyId: process.env.R2_ACCESS_KEY_ID,
	secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
	publicUrl: "https://cdn.example.con",
})

A resolução de variables de ambiente en tiempo de ejecución es recurso solo de Node. No Cloudflare Workers, secrets e variables son expostos por la parâmetro env del handler fetch, no por process.env, entonces variables de ambiente S3_* no son capturadas. Despliegues Workers deben usar o adaptador r2(config) ou passar valores explícitos para s3({...}). Consulte Opciones de almacenamiento para más detalles.

Adaptadores de caché de objetos

Passe un destes para a opção objectCache.

kvCache(config)

Backend Cloudflare KV, compartilhado entre todos os isolates. Importe de @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: "en", // cache key prefix (optional)
})

memoryCache(config?)

Backend in-process para Node.js e desarrollo. Importe de 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: "en", // cache key prefix (optional)
})

Consulte Cache de objetos para configuración e comportamento.

Adaptadores de autenticación y sandbox

Estes adaptadores retornam valores para as opciones de integración auth y sandboxRunner.

access(config)

Substitui o login passkey integrado por autenticación Cloudflare Access. Importe de @emdash-cms/cloudflare e passe o resultado para auth:

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

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

teamDomain es obligatorio. O adaptador pode ler a audience de la aplicação de audience o de la variable nomeada por audienceEnvVar; también aceita autoProvision, defaultRole, syncRoles y roleMapping. A opção auth documenta seus padrões e comportamento de funções.

sandbox()

Seleciona Cloudflare Worker Loader como sandbox runner de plugins. Importe de @emdash-cms/cloudflare e passe o valor retornado para sandboxRunner:

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

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

O site también precisa de un binding Worker Loader e del ponto de entrada ponte de plugins. Consulte Sandbox de plugins: Cloudflare Workers para essas configuraciones de despliegue.

Adaptadores de proveedores de medios

Passe descritores de proveedores de medios para mediaProviders. Ambos os proveedores Cloudflare integrados son importados de @emdash-cms/cloudflare.

Cada opção *EnvVar abaixo nomeia una variable de ambiente. El proveedor lê nesta ordem: un binding Cloudflare Workers con esse nome e, en seguida, process.env no adaptador Node. A opção direta correspondente (accountId, accountHash, apiToken) sempre tem precedência sobre ambas.

cloudflareImages(config)

Añade Cloudflare Images para navegar, subir, excluir e entregar recursos de imagem.

OpciónTipoPredeterminadoDescripción
accountIdstringDe CF_ACCOUNT_IDID de la conta Cloudflare
accountIdEnvVarstring"CF_ACCOUNT_ID"Variable usada cuando accountId es omitido
accountHashstringDe CF_IMAGES_ACCOUNT_HASHHash de la conta usado nas URLs de entrega
accountHashEnvVarstring"CF_IMAGES_ACCOUNT_HASH"Variable usada cuando accountHash es omitido
apiTokenstringDe CF_IMAGES_TOKENToken con permissões de leitura e edição de Cloudflare Images
apiTokenEnvVarstring"CF_IMAGES_TOKEN"Variable usada cuando apiToken es omitido
deliveryDomainstringimagedelivery.netHostname personalizado de entrega de imágenes
defaultVariantstring"public"Variante de imagem usada na exibição
mediaProviders: [cloudflareImages({ defaultVariant: "public" })];

cloudflareStream(config)

Añade Cloudflare Stream para navegar, pesquisar, subir, excluir e reproduzir recursos de vídeo.

OpciónTipoPredeterminadoDescripción
accountIdstringDe CF_ACCOUNT_IDID de la conta Cloudflare
accountIdEnvVarstring"CF_ACCOUNT_ID"Variable usada cuando accountId es omitido
apiTokenstringDe CF_STREAM_TOKENToken con permissões de leitura e edição de Cloudflare Stream
apiTokenEnvVarstring"CF_STREAM_TOKEN"Variable usada cuando apiToken es omitido
customerSubdomainstringPredeterminado CloudflareHostname personalizado de entrega del Stream
controlsbooleantrueExibir controles del player
autoplaybooleanfalseIniciar reproducción automaticamente
loopbooleanfalseRepetir reproducción
mutedbooleanfalse, o true con autoplaySilenciar reproducción
mediaProviders: [cloudflareStream({ controls: true })];

Consulte Biblioteca de medios: proveedores de medios para os bindings necesarios e componentes de renderização.

Adaptador de caché de Astro

cloudflareCache(config?)

O adaptador legado devuelve un cache.provider Astro que guarda respuestas na Workers Cache API e purga tags de cache pela API REST de la Cloudflare:

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

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

Aceita cacheName (padrão "emdash") y bookmarkCookie (padrão "__em_d1_bookmark"), além de zoneId o zoneIdEnvVar y apiToken o apiTokenEnvVar para solicitudes de purge por tag. Os nomes predeterminado de las variables son CF_ZONE_ID y CF_CACHE_PURGE_TOKEN.

Colecciones en vivo

Configure el cargador de EmDash en src/live.config.ts:

import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";

export const collections = {
	_emdash: defineLiveCollection({
		loader: emdashLoader(),
	}),
};

Opciones del cargador

A rol emdashLoader() no recebe argumentos:

emdashLoader();

Variables de entorno

O EmDash respeita estas variables de ambiente:

VariableDescripción
EMDASH_SITE_URLOrigem pública voltada ao navegador (fallback para SITE_URL)
EMDASH_ALLOWED_ORIGINSLista separada por comas de origens adicionais aceitas pela verificação de passkey (implantações multi-subdomínio).
EMDASH_DATABASE_URLSubstitui a URL de la base de datos
EMDASH_ENCRYPTION_KEYChave para cifrar segredos de plugins en repouso. Fornecida por la operador — nunca almacenados no base de datos.
EMDASH_PREVIEW_SECRETSubstituição opcional del segredo HMAC de preview. Cuando no definido, un valor estável por site es gerado e armazenado no base de datos.
EMDASH_IP_SALTSubstituição opcional del salt de hash del IP del comentarista. Cuando no definido, un valor estável por site es gerado e armazenado no base de datos.
EMDASH_AUTH_SECRETLegado. Usado como fonte del salt de IP si definido; instalações existentes deben mantê-lo para preservar hashes estáveis de IP de comentaristas após atualização.
EMDASH_TURNSTILE_SECRET_KEYChave secreta Cloudflare Turnstile (fallback para TURNSTILE_SECRET_KEY). Cuando definida, envios de comentários deben incluir un token Turnstile válido — combine con la prop turnstileSiteKey en <CommentForm>.
EMDASH_URLURL remota de EmDash para sincronização de esquema

Gere una chave de cifrado con el seguinte comando:

npx emdash secrets generate

Configuración de package.json

Templates e sites pueden declarar metadados opcionais sob a chave emdash en package.json:

{
	"emdash": {
		"label": "My Blog Template",
		"schema": ".emdash/schema.sql",
		"seed": ".emdash/seed.json",
		"url": "https://my-site.pages.dev"
	}
}
OpciónDescripción
labelNome del template para exibição
schemaEsquema SQL opcional lido por emdash init
seedCaminho para archivo JSON de seed
urlURL remota usada por la fluxo obsoleto emdash dev --types

Configuración de TypeScript

Durante o desarrollo local, a integración Astro gera emdash-env.d.ts na raiz del projeto e o atualiza após mudanças de esquema. O archivo aumenta o módulo emdash, para que os imports predeterminado getEmDashCollection() y getEmDashEntry() infiram campos de coleção local sem alias de path.

O comando separado emdash types busca o esquema de una instância local o remota en ejecución e grava .emdash/types.ts por predeterminado. Adicione un alias solo cuando o código de la aplicação importar essa saída standalone directamente:

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

Gere os tipos standalone de esquema remoto con el seguinte comando:

npx emdash types