Referência de configuração

Nesta página

A configuração principal do EmDash fica em astro.config.mjs, enquanto src/live.config.ts registra o carregador de conteúdo. Valores específicos do deploy também podem vir de variáveis de ambiente. Um pequeno bloco de metadados em package.json oferece suporte a rótulos de template e a fluxos locais legados da CLI.

Integração com o Astro

Configure o EmDash como uma integração do Astro em 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: [],
		}),
	],
});

Opções da integração

database

Obrigatória. Configuração do adaptador de banco de dados. Escolha um 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 Opções de banco de dados para mais detalhes.

migrations

Opcional. Controla como as migrações internas do banco de dados do EmDash são tratadas em tempo de execução. Se esta opção for omitida, o padrão é { runtime: "auto" }.

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

auto verifica e aplica as migrações pendentes, check retorna 503 quando há migrações pendentes conhecidas pelo build em execução (exceto para requisições ao endpoint de imagens que o EmDash instala) e manual não executa nenhuma consulta de migração em tempo de execução. EMDASH_MIGRATIONS_MODE substitui o modo de execução efetivo. Consulte Gerenciar migrações do banco de dados do núcleo antes de adotar check ou manual.

storage

Opcional. Configuração do adaptador de armazenamento de mídia. Quando esta opção é omitida, o EmDash armazena os arquivos em ./.emdash/uploads e os serve por meio de /_emdash/api/media/file. Escolha um adaptador quando o diretório local padrão não for adequado:

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

Consulte Opções de armazenamento para mais detalhes.

images

Opcional. Controla se o EmDash integra a mídia armazenada com a otimização de imagens do Astro. O padrão é true.

Quando habilitada, o EmDash envolve o endpoint de imagens do Astro para que <Image> e getImage() possam ler os bytes de origem diretamente do adaptador de armazenamento configurado. Isso também funciona quando a URL original da mídia está atrás do Cloudflare Access. As requisições ao endpoint envolvido pulam a inicialização do runtime do EmDash; por isso, nelas locals.emdash contém apenas storage, além de db para um usuário autenticado. locals.user é definido como nas demais rotas públicas. Defina images: false quando outro serviço de imagens cuidar da mídia ou quando todas as imagens devam ser renderizadas sem o wrapper de endpoint do EmDash.

emdash({
	images: false,
});

mediaProviders

Opcional. Adiciona serviços de mídia à biblioteca de mídia. O provedor local, baseado em armazenamento, continua disponível automaticamente; cada descritor neste array adiciona mais um lugar onde os editores podem navegar ou enviar mídia.

O exemplo a seguir adiciona o Cloudflare Images e o Cloudflare Stream:

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

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

As credenciais dos provedores são resolvidas em tempo de execução. As configurações vazias acima usam as variáveis de ambiente padrão da Cloudflare descritas nas seções de adaptadores cloudflareImages(config) e cloudflareStream(config). Consulte Biblioteca de mídia: provedores de mídia para a configuração de bindings e de renderização.

objectCache

Opcional. Armazena em cache os resultados de consultas de conteúdo e de configuração em um repositório chave/valor, para que as leituras sejam atendidas sem consultar o banco de dados a cada requisição. Desabilitada quando omitida. Escolha um 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 a configuração e as opções.

middleware.outer

Opcional. Registra um módulo de middleware do Astro fora de toda a pilha de middleware do EmDash. Como a integração o registra com order: "pre" do Astro, ele também é executado antes do middleware definido em src/middleware.ts. Use-o para filtros de requisição ou caches de resposta completa que precisam evitar a inicialização do runtime e do banco de dados em um acerto de cache, ou para cabeçalhos de resposta que dependem do HTML final do EmDash.

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

A ordem de execução é:

  1. O middleware externo é executado até await next().
  2. O EmDash inicializa o runtime e o banco de dados e, em seguida, executa os middlewares de configuração, autenticação e contexto da requisição.
  3. A rota do Astro é renderizada.
  4. O EmDash aplica as modificações na resposta, incluindo o HTML de edição visual e os cabeçalhos de segurança e de tempo.
  5. next() é resolvido no middleware externo com essa resposta final.

Antes de chamar next(), o middleware tem a requisição normal do Astro e o contexto de execução da plataforma, mas locals.emdash, locals.user, o banco de dados e o estado do EmDash associado à requisição não estão disponíveis. Uma Response antecipada ignora completamente o EmDash, portanto deve incluir os cabeçalhos de segurança e de cache de que precisar. Depois que next() é resolvido, é seguro finalizar nonces de CSP, armazenar em cache o corpo completo ou definir Content-Length. Se o middleware alterar o corpo, remova ou recalcule qualquer cabeçalho Content-Length existente.

O hook usa a API de middleware do Astro tanto no Node quanto na Cloudflare. Este exemplo mínimo com a Cache API da Cloudflare armazena em cache apenas respostas HTML anônimas e retorna os acertos antes da inicialização do 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;
});

No Node, use o mesmo formato de middleware com um cache compatível com Node, como o Redis. As chaves de cache e as regras de bypass devem incluir toda propriedade da requisição que altere a resposta renderizada.

playground

Opcional. Habilita o middleware usado por playgrounds do EmDash descartáveis, executados no navegador. Ele cria um banco de dados Durable Object gravável para cada sessão, aplica o seed configurado e autentica o visitante como administrador anônimo antes de o middleware normal do EmDash ser executado.

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

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

Este modo exige @emdash-cms/cloudflare e um binding de Durable Object. Ele ignora os middlewares normais de configuração e de autenticação; portanto, use-o apenas em sites de demonstração efêmeros, e não em um CMS de produção.

plugins

Opcional. Array de plugins que são executados no mesmo processo do site Astro. Os plugins nativos ficam aqui. Um plugin compatível com sandbox também pode ser executado aqui quando você confia nele com acesso total ao processo e não precisa de isolamento.

O exemplo a seguir registra um plugin nativo:

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

plugins: [seoPlugin()];

Os plugins nativos podem usar diretamente as APIs de servidor e do framework; por isso, não podem ser movidos para sandboxed, a menos que o pacote também forneça um ponto de entrada de plugin compatível com sandbox. Consulte Escolher um formato de plugin para ver as diferenças de desenvolvimento e de deploy.

sandboxed

Opcional. Array de plugins compatíveis com sandbox que usam as APIs de plugin declaradas do EmDash e são executados em runtimes isolados. Não coloque um plugin nativo aqui: o código nativo pode depender de acesso ao processo e ao framework que o sandbox não oferece.

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

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

Os plugins em sandbox são ignorados quando nenhum executor de sandbox utilizável está configurado. Consulte Sandbox de plugins para a configuração do executor na Cloudflare e no Node.js.

sandboxRunner

Opcional. Especificador de módulo da fábrica que inicia os runtimes isolados de plugins. É obrigatório para plugins em sandboxed e para plugins do marketplace ou do registro.

No Cloudflare Workers, use o adaptador sandbox():

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

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

Os deploys em Node.js usam o módulo executor workerd documentado em Sandbox de plugins: Node.js.

sandbox

Opcional. Controla se um executor de sandbox configurado isola os plugins. O sandbox é habilitado quando sandboxRunner está configurado. Defina sandbox: false apenas para diagnosticar se um problema vem de um plugin ou do runtime de sandbox dele:

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

Com false, os plugins declarados em sandboxed e os instalados a partir do marketplace são executados no processo principal do servidor, sem isolamento nem limites de recursos. Restaure o sandbox após o diagnóstico.

registry

Opcional. Configura o agregador e a política do registro de plugins. Sem um valor explícito, o EmDash usa https://registry.emdashcms.com quando sandboxRunner está configurado e sandbox não é false.

Defina registry: false para desabilitar a descoberta no registro e os plugins instalados pelo registro, mantendo o executor de sandbox disponível para os plugins declarados em sandboxed e para os plugins legados do Marketplace:

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

Passe a URL do serviço de registro como string, ou use um objeto quando o site precisar de fontes de moderação ou de uma política de idade de lançamento. O exemplo a seguir usa a forma de objeto:

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"],
		},
	},
});
OpçãoTipoDescrição
aggregatorUrlstringURL base do serviço de registro. Use HTTPS em produção.
acceptLabelersstringIdentificadores descentralizados (DIDs) opcionais, separados por vírgula, de serviços de moderação aceitos pela requisição. Um DID é um identificador estável de conta Atmosphere. Esta configuração não pode substituir a política do serviço de registro.
policy.minimumReleaseAgestring | numberRetém lançamentos mais recentes que esta idade. String de duração ("48h", "7d") ou segundos.
policy.minimumReleaseAgeExcludestring[]DIDs de publicadores, ou pares <did>/<plugin-slug>, isentos da retenção.

A política de idade de lançamento só isenta o primeiro lançamento de um pacote quando o registro informa que há um lançamento retido e confirma que observou o pacote continuamente. Um pacote preenchido retroativamente, um lançamento anterior excluído ou a falta de evidências de histórico mantêm a retenção em vigor. As isenções explícitas de publicadores e de pacotes se aplicam independentemente do histórico.

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

marketplace

Obsoleta. URL base usada para atualizar plugins instalados a partir do Marketplace legado. A navegação no Marketplace e as novas instalações não são exibidas na administração. Os plugins existentes do Marketplace continuam atualizáveis e desinstaláveis enquanto esta opção estiver configurada.

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

As URLs de produção devem usar HTTPS; HTTP só é aceito para localhost e 127.0.0.1 durante o desenvolvimento. Mantenha esta opção até que todos os plugins do Marketplace tenham sido substituídos ou desinstalados e, então, remova-a. Siga Migrar do Marketplace para o procedimento completo.

fonts

Opcional. Configuração das fontes da interface de administração.

Por padrão, o EmDash carrega a Noto Sans por meio da Font API do Astro. As fontes são baixadas do Google em tempo de build e hospedadas por conta própria; portanto, não há requisições a CDN em tempo de execução. A fonte base cobre os sistemas de escrita latino, cirílico, grego, devanágari e vietnamita.

Para adicionar suporte a outros sistemas de escrita, passe nomes de scripts. O exemplo a seguir adiciona árabe e japonês:

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

Os scripts disponíveis são 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 e tibetan.

Cada script corresponde à variante equivalente da Noto Sans no Google Fonts (por exemplo, "arabic" carrega a Noto Sans Arabic). Todas as faces de fonte compartilham um único nome de font-family e usam unicode-range, de modo que o navegador baixe apenas os arquivos de que precisa para os caracteres da página.

Defina como false para desabilitar totalmente a injeção de fontes e usar as fontes do sistema:

emdash({
	fonts: false,
})

O CSS da administração usa a variável CSS --font-emdash. Ela é definida automaticamente pela configuração de fontes acima.

auth

Opcional. Um adaptador de autenticação. O login integrado do EmDash usa passkeys; definir auth as substitui por um provedor externo. O adaptador do Cloudflare Access, access(), é fornecido por @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,
		},
	}),
});

Opções de access():

OpçãoTipoPadrãoDescrição
teamDomainstringobrigatóriaO domínio da sua equipe no Cloudflare Access
audiencestring—Tag Audience (AUD) da aplicação. No Workers, prefira audienceEnvVar.
audienceEnvVarstring"CF_ACCESS_AUDIENCE"Variável de ambiente da qual ler a tag audience em tempo de execução
autoProvisionbooleantrueCria um usuário do EmDash no primeiro login
defaultRolenumber30Nível de função para usuários não correspondidos por roleMapping (veja Funções de usuário)
syncRolesbooleanfalseReaplica roleMapping a cada login, e não apenas no provisionamento
syncNamebooleantrueSubstitui o nome do usuário pelo nome do IdP em cada requisição autenticada. Defina false para que os nomes possam ser editados na administração
roleMappingobject—Mapeia nomes de grupos do IdP para níveis de função do EmDash; a primeira correspondência vence

authProviders

Opcional. Um array de provedores de login plugáveis (no nível superior, ao lado de auth). Cada entrada é o resultado de chamar uma fábrica de provedor, como mostrado 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 os equivalentes sem prefixo).
  • google() — lê EMDASH_OAUTH_GOOGLE_CLIENT_ID / EMDASH_OAUTH_GOOGLE_CLIENT_SECRET.
  • microsoft() — lê EMDASH_OAUTH_MICROSOFT_CLIENT_ID / EMDASH_OAUTH_MICROSOFT_CLIENT_SECRET / EMDASH_OAUTH_MICROSOFT_TENANT_ID (ou os equivalentes sem prefixo). Aceita { emailVerified }. Veja Microsoft.
  • atproto() — login com conta Atmosphere (Bluesky e toda a rede AT Protocol). Não são necessárias variáveis de ambiente. Aceita { allowedDIDs, allowedHandles, defaultRole }. Veja o guia de login do Atmosphere.

Pacotes de terceiros podem registrar seus próprios provedores usando o mesmo formato AuthProviderDescriptor — veja Provedores de login.

mcp

Opcional. Habilita o endpoint do Model Context Protocol (MCP) em /_emdash/api/mcp. O endpoint vem habilitado por padrão e exige um token bearer; portanto, habilitá-lo não concede acesso anônimo.

Defina a opção como false quando o site não deva expor um endpoint MCP:

emdash({
	mcp: false,
});

Consulte a Referência do servidor MCP para a criação de tokens e a configuração de clientes.

siteUrl

A origem pública do site, visível ao navegador (esquema + host + porta opcional, sem caminho). Defina-a antes de executar a configuração de produção, a menos que o site seja implantado no Cloudflare Workers. Caso contrário, somente hosts de desenvolvimento em loopback podem concluir a configuração sem uma origem configurada.

Atrás de um proxy reverso que encerra o TLS, Astro.url retorna o endereço interno (http://localhost:4321) em vez do público (https://cms.example.com). Isso quebra passkeys, a correspondência de origem do CSRF, redirecionamentos OAuth, redirecionamentos de login, a descoberta do MCP, exportações de snapshot, sitemap, robots.txt e dados estruturados JSON-LD. Definir siteUrl corrige tudo isso de uma só vez.

A integração valida este valor no carregamento: deve ser uma URL válida com protocolo http: ou https: e é normalizada para a origem (o caminho é removido).

O exemplo a seguir 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.com",
});

Quando siteUrl não está definida na configuração, o EmDash verifica as variáveis de ambiente nesta ordem: EMDASH_SITE_URL e, depois, SITE_URL. Isso é útil para deploys em contêineres em que a URL pública é definida em tempo de execução.

A otimização de imagens lê essas variáveis de ambiente em tempo de build, porque o Astro registra as origens de imagem permitidas em image.remotePatterns quando astro build é executado. Se EMDASH_SITE_URL ou SITE_URL estiver definida apenas no ambiente de execução, como em hosts que injetam variáveis quando o app inicia, a mídia armazenada localmente é servida sem otimização. Defina a variável também no ambiente de build ou defina siteUrl na configuração.

A configuração falha com SITE_URL_REQUIRED em um host que não seja loopback quando nenhuma das fontes está definida. Isso impede que a primeira requisição de configuração não autenticada escolha a origem usada em e-mails de autenticação posteriores. Um build de produção implantado no Cloudflare Workers é a exceção: o Cloudflare só roteia requisições para nomes de host vinculados ao Worker, então a configuração registra https:// e o nome de host em que ela é executada. O mesmo build servido por wrangler dev, astro preview ou por um workerd auto-hospedado em um endereço acessível não tem essa garantia; defina siteUrl ou EMDASH_SITE_URL nele primeiro.

Os links nos e-mails de login, convite, autocadastro, recuperação e notificação de comentários usam a primeira origem disponível entre: siteUrl ou suas variáveis de ambiente, a Site URL em Settings > General e, por fim, a origem registrada durante a configuração inicial. Apenas a origem da Site URL é usada, e ela deve usar https://, a menos que o host seja localhost, 127.0.0.1 ou [::1]. ctx.site.url usa a mesma origem dos links nos e-mails e é lido quando o runtime inicia. Depois de mover um site para um novo domínio sem um siteUrl configurado, altere a Site URL com Change domain para que os links dos e-mails apontem para ela; veja Mudar para um novo domínio. Sitemaps e robots.txt usam uma ordem diferente, em que a Site URL vem antes de siteUrl; veja robots.txt.

No Cloudflare Workers, o fallback para variáveis de ambiente lê process.env. Com nodejs_compat, a Cloudflare preenche process.env por padrão para datas de compatibilidade a partir de 2025-04-01. Projetos fixados em uma data anterior também precisam adicionar nodejs_compat_populate_process_env.

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

allowedOrigins

Opcional. Origens de navegador adicionais aceitas pela verificação de passkeys para um deploy disponível em mais de um nome de host.

siteUrl define uma única origem canônica. Quando o mesmo deploy do EmDash é acessível por vários nomes de host que compartilham um domínio pai registrável (por exemplo, https://example.com e https://preview.example.com), a verificação de passkeys rejeita asserções cuja origem não corresponda exatamente a siteUrl — embora o WebAuthn permita que passkeys sejam válidas entre subdomínios sob o mesmo rpId.

Declare as origens adicionais aceitas por meio de allowedOrigins em astro.config.mjs ou da variável de ambiente EMDASH_ALLOWED_ORIGINS. A siteUrl canônica continua sendo a fonte do rpId; as entradas listadas aqui são aceitas no momento da verificação. As duas fontes são mescladas em tempo de execução, de modo que a configuração pode declarar as origens estáveis (versionadas e revisadas no código), enquanto o ambiente acrescenta extras específicos do ambiente (por exemplo, prévias efêmeras de PRs).

O exemplo a seguir declara uma origem extra na configuração:

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

Os valores equivalentes também podem vir de variáveis de ambiente:

EMDASH_SITE_URL=https://example.com
EMDASH_ALLOWED_ORIGINS=https://preview.example.com,https://staging.example.com
Validação

O EmDash valida esses valores para evitar configurações inúteis que o navegador nunca honraria:

  • Cada entrada deve ser uma URL http: ou https: analisável, sem ponto final e sem rótulos vazios no nome do host.
  • Quando allowedOrigins não está vazio, siteUrl deve estar definida (por qualquer uma das fontes) e não pode ser um literal de IP nem ter um nome de host com ponto final.
  • Cada origem deve ser o mesmo nome de host que siteUrl ou um subdomínio dele. (O WebAuthn exige que rpId seja um sufixo registrável de cada origem.)

Quando a validação falha, você vê um erro com a fonte indicada, como 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.

Onde o erro aparece depende de onde os valores são declarados:

  • Na inicialização do Astro, quando config.allowedOrigins e config.siteUrl vêm ambos de astro.config.mjs — erros de digitação no código fazem o build falhar.
  • Na primeira verificação de passkey, quando qualquer um dos valores vem de EMDASH_ALLOWED_ORIGINS ou EMDASH_SITE_URL — incompatibilidades de ambiente aparecem como erros 500 na primeira tentativa de verificação.

Configuração de proxy reverso

O Astro só reflete X-Forwarded-* quando o host público é permitido. Configure security.allowedDomains com o nome de host (e os esquemas) que seus usuários acessam. Em astro dev, adicione os vite.server.allowedHosts correspondentes para que o Vite aceite o cabeçalho Host do proxy.

Prefira corrigir primeiro allowedDomains (e os cabeçalhos encaminhados); use siteUrl quando a URL reconstruída ainda divergir da origem do navegador (típico quando o TLS é encerrado à frente e a requisição de origem permanece http://).

Com TLS à frente, vincular o servidor de desenvolvimento ao loopback (astro dev --host 127.0.0.1) costuma bastar: o proxy se conecta localmente enquanto siteUrl corresponde à origem HTTPS pública.

Se o seu proxy grava um cabeçalho com o IP do cliente, defina trustedProxyHeaders para que os limites de taxa do EmDash possam usar o IP real do cliente. Sem um IP de cliente confiável, os limites de taxa de autenticação são ignorados e todos os envios públicos de comentários compartilham um único bucket de limite de taxa (20 comentários a cada 10 minutos para todos os visitantes).

A configuração a seguir define allowedDomains, vite.server.allowedHosts e siteUrl em conjunto para um deploy atrás de 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.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

Opcional. Cabeçalhos em que confiar para a resolução do IP do cliente quando o site roda atrás de um proxy reverso que você controla. Usados pelos limites de taxa de autenticação (magic link, cadastro, passkey, device flow do OAuth, registro de cliente OAuth) e pelo endpoint público de comentários.

Na Cloudflare, o objeto cf anexado à requisição é usado automaticamente — normalmente você não precisa definir esta opção. Em deploys auto-hospedados atrás de nginx, Caddy, Traefik, Fly, Railway ou similares, defina aqui o cabeçalho que o seu proxy grava, para que os limites de taxa possam contar as requisições por IP real do cliente.

O exemplo a seguir confia no cabeçalho x-real-ip definido por nginx, Caddy ou Traefik:

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

Os cabeçalhos são testados em ordem. Valores que correspondem a *-forwarded-for são analisados como listas separadas por vírgula e a primeira entrada é usada. O exemplo a seguir prefere o cabeçalho do Fly.io e recorre a x-forwarded-for:

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

Quando não está definida na configuração, o EmDash lê a variável de ambiente EMDASH_TRUSTED_PROXY_HEADERS (separada por vírgulas). Um array vazio explícito na configuração substitui a variável de ambiente.

maxUploadSize

Opcional. Tamanho máximo permitido, em bytes, para o upload de um arquivo de mídia. Aplica-se tanto a uploads multipart diretos quanto a uploads por URL assinada. O padrão é 52_428_800 (50 MB). O exemplo a seguir 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
});
ValorDescrição
number (bytes)Deve ser um inteiro finito positivo
omitidoO padrão é 50 MB

Uploads que excedem o limite configurado são rejeitados com uma resposta 413 Payload Too Large no caminho de upload direto, ou com 400 Validation Error no caminho de URL assinada.

admin

Opcional. Substitui a identidade visual do EmDash na interface de administração e limita quais idiomas de administração o build inclui. Os valores de identidade visual não alteram o título, o logotipo nem o favicon do site público.

emdash({
	admin: {
		logo: "/images/agency-logo.webp",
		siteName: "Agency CMS",
		footerLabel: "AgencyX",
		favicon: "/favicon.ico",
	},
});
OpçãoTipoDescrição
logostringURL ou caminho do logotipo para a página de login e a barra lateral
siteNamestringNome exibido no cabeçalho da barra lateral e no título do navegador
footerLabelstring | falseRótulo exibido ao lado da versão na barra lateral. O padrão é "EmDash"; false o oculta
faviconstringURL ou caminho do favicon das páginas de administração
localesstring[]Idiomas de administração a incluir, como ["en", "de"]. Os catálogos dos demais idiomas ficam fora do bundle de administração, e somente os idiomas listados aparecem no seletor de idioma. Usuários cujos idiomas preferidos não estão listados veem inglês. en é sempre incluído como fallback, mesmo que você o omita, então admin: { locales: ["en-GB"] } inclui tanto inglês quanto inglês britânico. Um código desconhecido faz o build falhar, e o erro lista os códigos disponíveis.

updateCheck

Opcional. Controla o aviso de atualização do núcleo no painel de administração. O padrão é true.

Quando habilitada, o EmDash consulta o registro público do npm em busca de lançamentos publicados do emdash — no máximo uma vez por dia, de forma adiada após a resposta para nunca atrasar uma requisição — e exibe um banner dispensável no painel de administração quando há uma versão mais recente disponível. Dispensar o banner o oculta para aquela versão; ele reaparece quando uma versão ainda mais recente fica disponível.

O banner indica o lançamento estável mais recente que está público há pelo menos 24 horas; portanto, um lançamento é anunciado um dia depois de ser publicado. Para acompanhar uma política de idade de lançamento do seu gerenciador de pacotes, como o minimumReleaseAge do pnpm, defina minimumReleaseAge como uma string de duração ("48h", "7d") ou um número de segundos. Com "7d", o banner oferece o lançamento mais recente que tenha pelo menos uma semana:

emdash({
	updateCheck: { minimumReleaseAge: "7d" },
})

A verificação é um simples GET para https://registry.npmjs.org/emdash e não leva nenhum dado do site. Deploys sem acesso de saída à internet simplesmente nunca exibem o banner. Defina como false para desabilitar totalmente a verificação:

emdash({
	updateCheck: false,
})

O banner é apenas informativo — atualizar o EmDash significa aumentar a versão do pacote emdash no seu projeto e refazer o deploy, o que a administração não pode (e não deve) disparar.

toolbar

Opcional. Controla como a barra de ferramentas do editor (a pílula flutuante nas páginas públicas) é entregue. O padrão é "server".

ValorComportamento
"server" (padrão)A barra de ferramentas é injetada no servidor em toda resposta HTML renderizada para um editor autenticado.
"client"O HTML público é idêntico para todos os visitantes. Um pequeno script de bootstrap mostra uma pílula “Edit” nos navegadores que já fizeram login na administração; clicar nela verifica a sessão e recarrega a página com um parâmetro de consulta _edit, sempre renderizada na hora (nunca em cache) com a barra de ferramentas completa.
falseNunca renderiza a barra de ferramentas nem o script de bootstrap.
emdash({
	toolbar: "client",
})

Use "client" quando o seu HTML público for servido por um cache compartilhado (Cloudflare Cache Everything / Workers Cache, Fastly, Varnish, …). Com a injeção no servidor, um editor que navega pelo site público recebe a variante anônima em cache — sem a barra de ferramentas — sempre que um visitante anônimo preencheu o cache primeiro; assim, a barra de ferramentas aparece e desaparece conforme o estado do cache. No modo client, nada específico da sessão é injetado no HTML compartilhável, de modo que o cache continua totalmente eficaz e a barra de ferramentas é confiável.

Observações sobre o modo "client":

  • Visitantes deslogados que abrem uma URL ?_edit compartilhada são redirecionados para a URL canônica, de modo que o parâmetro não pode vazar rascunhos nem preencher entradas de cache extras com conteúdo da página.
  • O sinal de “logado” é um sinalizador não secreto em localStorage definido pela administração; a pílula verifica a sessão real antes de entrar na visualização de edição.
  • O bootstrap é um pequeno <script> inline. Se o seu site envia um Content-Security-Policy estrito sem 'unsafe-inline', adicione um hash para ele — o mesmo vale para a barra de ferramentas injetada no servidor.
  • O EmDash não injeta nada específico da sessão — mas, se os seus próprios templates se ramificarem em Astro.locals.user (por exemplo, um link de navegação “Admin” para usuários logados), essa variação continua no seu HTML e ainda fragmenta o cache.

Em qualquer modo, a barra de ferramentas pode ser dispensada no navegador pelo botão × (por navegador, até a próxima vez que um editor abrir a administração). As respostas de pré-visualização e de modo de edição são sempre renderizadas no servidor com Cache-Control: private, no-store.

Adaptadores de banco de dados

Importe os adaptadores de emdash/db:

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

sqlite(config)

Banco de dados SQLite que usa o driver de banco de dados integrado do Node.js. O exemplo a seguir conecta-se a um arquivo local:

OpçãoTipoDescrição
urlstringCaminho do arquivo com o prefixo file:
sqlite({ url: "file:./data.db" });

libsql(config)

Banco de dados libSQL. O exemplo a seguir conecta-se a um banco de dados libSQL remoto:

OpçãoTipoDescrição
urlstringURL do banco de dados
authTokenstringToken de autenticação em tempo de execução (opcional para arquivos locais)
migrationAuthTokenEnvstringNome da variável do token de migração (padrão TURSO_AUTH_TOKEN)
libsql({
	url: process.env.LIBSQL_DATABASE_URL,
	authToken: process.env.LIBSQL_AUTH_TOKEN,
});

postgres(config)

Banco de dados PostgreSQL com pool de conexões.

OpçãoTipoDescrição
connectionStringstringURL de conexão do PostgreSQL
hoststringHost do banco de dados
portnumberPorta do banco de dados
databasestringNome do banco de dados
userstringUsuário do banco de dados
passwordstringSenha do banco de dados
sslbooleanHabilita SSL
pool.minnumberTamanho mínimo do pool (padrão: 0)
pool.maxnumberTamanho máximo do pool (padrão: 10)
pool.connectionTimeoutMillisnumberEspera máxima por conexão (padrão do pg: 0, sem timeout)
pool.idleTimeoutMillisnumberTempo de vida de um cliente ocioso (padrão do pg: 10.000 ms)
migrationConnectionStringEnvstringNome da variável da string de conexão de migração (padrão DATABASE_URL)

O exemplo a seguir conecta-se com uma string de conexão:

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

d1(config)

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

OpçãoTipoPadrãoDescrição
bindingstring—Nome do binding D1 em wrangler.jsonc
sessionstring"disabled"Modo de replicação de leitura: "disabled", "auto" ou "primary-first"
bookmarkCookiestring"__em_d1_bookmark"Nome do cookie para os bookmarks de sessão
coalescebooleanfalseAgrupa leituras concorrentes no mesmo turno do event loop; exige um modo de sessão diferente de "disabled"

O exemplo a seguir mostra um binding básico e outro com réplicas de leitura habilitadas:

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

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

Quando session é "auto" ou "primary-first", o EmDash usa a D1 Sessions API para encaminhar consultas de leitura a réplicas próximas. Usuários autenticados obtêm consistência read-your-writes baseada em bookmarks. Consulte Opções de banco de dados — Réplicas de leitura para mais detalhes.

hyperdrive(config?)

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

OpçãoTipoPadrãoDescrição
bindingstring"HYPERDRIVE"Binding principal do Hyperdrive com o cache de consultas desabilitado
cachedBindingstring—Segundo binding opcional, com cache habilitado, para leituras públicas anônimas
preferUncachedAfterWriteMsnumber60_000Por quanto tempo as leituras públicas usam o binding principal após uma gravação de conteúdo quando cachedBinding está definido
migrationConnectionStringEnvstringDerivado do binding principalVariável de ambiente com a URL direta do PostgreSQL usada por emdash migrate
maxnumber5Máximo de conexões de um isolate de Worker para o Hyperdrive

O exemplo a seguir encaminha requisições autenticadas e gravações pelo binding sem cache, enquanto leituras públicas anônimas podem usar o binding com cache:

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

Os dois bindings devem apontar para o mesmo banco de dados. Instale o pg na versão 8.16.3 ou posterior, habilite a flag de compatibilidade nodejs_compat e configure uma URL direta do banco de dados para as migrações de deploy. Consulte Opções de banco de dados: Hyperdrive para a configuração completa do Worker e das migrações.

durableObjects(config)

Armazena o CMS em um único Durable Object com suporte de SQLite. Importe este adaptador de @emdash-cms/cloudflare.

OpçãoTipoPadrãoDescrição
bindingstringobrigatóriaBinding do namespace do Durable Object para a classe EmDashDB
namestring"emdash"Nome do objeto singleton; altere-o apenas para isolar vários bancos de dados atrás de um único binding
sessionstring"disabled""auto" encaminha leituras anônimas para réplicas e gravações para o primário
bookmarkCookiestring"__em_do_bookmark"Cookie usado para a consistência read-your-writes no modo "auto"
durableObjects({ binding: "DB_DO", session: "auto" });

O roteamento para réplicas exige as flags de compatibilidade experimental e replica_routing, além das entradas de classe do Durable Object e de migração em wrangler.jsonc.

previewDatabase(config)

Cria um banco de dados de snapshot isolado por sessão de pré-visualização em um Durable Object. A única opção é o nome do binding, obrigatório:

previewDatabase({ binding: "PREVIEW_DB" });

Este adaptador destina-se à infraestrutura de pré-visualização, e não ao banco de dados principal de um site de produção.

playgroundDatabase(config)

Cria um banco de dados gravável e com seed por sessão de playground em um Durable Object. Combine-o com a opção de integração playground:

playgroundDatabase({ binding: "PLAYGROUND_DB" });

O binding obrigatório identifica o namespace do Durable Object do playground. Use este adaptador apenas em sites de demonstração descartáveis.

Adaptadores de armazenamento

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

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

local(config)

Armazenamento no sistema de arquivos local. O exemplo a seguir serve os uploads a partir de um diretório local:

OpçãoTipoDescrição
directorystringCaminho do diretório
baseUrlstringURL base para servir os arquivos
local({
	directory: "./uploads",
	baseUrl: "/_emdash/api/media/file",
});

r2(config)

Binding do Cloudflare R2. O exemplo a seguir usa um binding R2 com uma URL pública:

OpçãoTipoDescrição
bindingstringNome do binding R2
publicUrlstringURL pública opcional
r2({
	binding: "MEDIA",
	publicUrl: "https://pub-xxxx.r2.dev",
});

s3(config?)

Armazenamento compatível com S3. Todos os campos de configuração são opcionais: qualquer campo omitido de s3({...}) é resolvido a partir da variável de ambiente S3_* correspondente quando o processo Node é iniciado. Valores explícitos sempre têm precedência.

Depois que os valores de configuração e de ambiente são mesclados, endpoint e bucket são obrigatórios. Se qualquer uma das credenciais estiver definida, accessKeyId e secretAccessKey são ambas obrigatórias. Valores ausentes fazem a inicialização falhar com o código de erro MISSING_S3_CONFIG.

Pré-requisito: instale @aws-sdk/client-s3 e @aws-sdk/s3-request-presigner no seu projeto. O núcleo do EmDash não inclui o AWS SDK. Consulte Opções de armazenamento: armazenamento compatível com S3 para mais detalhes.

OpçãoTipoDescrição
endpointstringURL do endpoint S3 (S3_ENDPOINT)
bucketstringNome do bucket (S3_BUCKET)
accessKeyIdstringChave de acesso (S3_ACCESS_KEY_ID)
secretAccessKeystringChave secreta (S3_SECRET_ACCESS_KEY)
regionstringRegião, padrão "auto" (S3_REGION)
publicUrlstringURL de CDN opcional (S3_PUBLIC_URL)

Os exemplos a seguir resolvem todos os campos a partir do ambiente, combinam configuração e ambiente ou 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.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",
})

A resolução de variáveis de ambiente em tempo de execução é um recurso exclusivo do Node. No Cloudflare Workers, segredos e variáveis são expostos pelo parâmetro env do fetch handler, e não por process.env; portanto, as variáveis de ambiente S3_* não são lidas. Os deploys em Workers devem usar o adaptador r2(config) ou passar valores explícitos para s3({...}). Consulte Opções de armazenamento para mais detalhes.

Adaptadores de cache de objetos

Passe um 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: "em", // cache key prefix (optional)
})

memoryCache(config?)

Backend em processo para Node.js e desenvolvimento. 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: "em", // cache key prefix (optional)
})

Consulte Cache de objetos para a configuração e o comportamento.

Adaptadores de autenticação e de sandbox

Estes adaptadores retornam valores para as opções de integração auth e sandboxRunner.

access(config)

Substitui o login integrado por passkey pela autenticação do Cloudflare Access. Importe-o de @emdash-cms/cloudflare e passe o resultado para auth:

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

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

teamDomain é obrigatório. O adaptador pode ler a audience da aplicação de audience ou da variável indicada por audienceEnvVar; ele também aceita autoProvision, defaultRole, syncRoles, syncName e roleMapping. A opção auth documenta os padrões, o comportamento das funções e a sincronização de nomes.

sandbox()

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

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

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

O site também precisa de um binding de Worker Loader e do ponto de entrada da ponte de plugins. Consulte Sandbox de plugins: Cloudflare Workers para essas configurações de deploy.

Adaptadores de provedores de mídia

Passe descritores de provedores de mídia para mediaProviders. Os dois provedores integrados da Cloudflare são importados de @emdash-cms/cloudflare.

Cada opção *EnvVar abaixo indica o nome de uma variável de ambiente. O provedor a lê nesta ordem: um binding do Cloudflare Workers com esse nome e, depois, process.env no adaptador Node. A opção direta correspondente (accountId, accountHash, apiToken) sempre tem precedência sobre ambas.

cloudflareImages(config)

Adiciona o Cloudflare Images para navegar, enviar, excluir e entregar ativos de imagem.

OpçãoTipoPadrãoDescrição
accountIdstringDe CF_ACCOUNT_IDID da conta Cloudflare
accountIdEnvVarstring"CF_ACCOUNT_ID"Variável usada quando accountId é omitido
accountHashstringDe CF_IMAGES_ACCOUNT_HASHHash da conta usado nas URLs de entrega
accountHashEnvVarstring"CF_IMAGES_ACCOUNT_HASH"Variável usada quando accountHash é omitido
apiTokenstringDe CF_IMAGES_TOKENToken com permissões de leitura e edição do Cloudflare Images
apiTokenEnvVarstring"CF_IMAGES_TOKEN"Variável usada quando apiToken é omitido
deliveryDomainstringimagedelivery.netNome de host personalizado para a entrega de imagens
defaultVariantstring"public"Variante de imagem usada para exibição
mediaProviders: [cloudflareImages({ defaultVariant: "public" })];

cloudflareStream(config)

Adiciona o Cloudflare Stream para navegar, pesquisar, enviar, excluir e reproduzir ativos de vídeo.

OpçãoTipoPadrãoDescrição
accountIdstringDe CF_ACCOUNT_IDID da conta Cloudflare
accountIdEnvVarstring"CF_ACCOUNT_ID"Variável usada quando accountId é omitido
apiTokenstringDe CF_STREAM_TOKENToken com permissões de leitura e edição do Cloudflare Stream
apiTokenEnvVarstring"CF_STREAM_TOKEN"Variável usada quando apiToken é omitido
customerSubdomainstringPadrão da CloudflareNome de host personalizado para a entrega do Stream
controlsbooleantrueExibe os controles do player
autoplaybooleanfalseInicia a reprodução automaticamente
loopbooleanfalseRepete a reprodução
mutedbooleanfalse, ou true com autoplaySilencia a reprodução
mediaProviders: [cloudflareStream({ controls: true })];

Consulte Biblioteca de mídia: provedores de mídia para os bindings e os componentes de renderização necessários.

Coleções ao vivo

Configure o carregador do EmDash em src/live.config.ts:

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

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

Opções do carregador

A função emdashLoader() não recebe argumentos:

emdashLoader();

Variáveis de ambiente

O EmDash respeita estas variáveis de ambiente:

VariávelDescrição
EMDASH_SITE_URLOrigem pública visível ao navegador (recorre a SITE_URL)
EMDASH_ALLOWED_ORIGINSLista, separada por vírgulas, de origens adicionais aceitas pela verificação de passkeys (deploys com vários subdomínios).
EMDASH_DATABASE_URLSubstitui a URL do banco de dados
EMDASH_ENCRYPTION_KEYChave para criptografar em repouso os segredos dos plugins. Fornecida pelo operador — nunca armazenada no banco de dados.
EMDASH_PREVIEW_SECRETSubstituição opcional do segredo HMAC da pré-visualização. Quando não definida, um valor estável por site é gerado e armazenado no banco de dados.
EMDASH_IP_SALTSubstituição opcional do sal de hash dos IPs de comentaristas. Quando não definida, um valor estável por site é gerado e armazenado no banco de dados.
EMDASH_AUTH_SECRETLegado. Usada como fonte do sal de IP, se definida; instalações existentes devem mantê-la para preservar hashes estáveis de IP de comentaristas após a atualização.
EMDASH_TURNSTILE_SECRET_KEYChave secreta do Cloudflare Turnstile (recorre a TURNSTILE_SECRET_KEY). Quando definida, os envios de comentários devem incluir um token Turnstile válido — combine-a com a prop turnstileSiteKey de <CommentForm>.
EMDASH_URLURL remota do EmDash para sincronização de esquema

Gere uma chave de criptografia com o seguinte comando:

npx emdash secrets generate

Configuração do package.json

Templates e sites podem declarar metadados opcionais sob uma chave emdash em package.json:

{
	"emdash": {
		"label": "My Blog Template",
		"schema": ".emdash/schema.sql",
		"seed": ".emdash/seed.json"
	}
}
OpçãoDescrição
labelNome do template para exibição
schemaEsquema SQL opcional lido por emdash init
seedCaminho do arquivo JSON de seed

Configuração do TypeScript

Durante o desenvolvimento local, a integração do Astro gera emdash-env.d.ts na raiz do projeto e o atualiza após alterações no esquema. O arquivo amplia o módulo emdash; portanto, as importações padrão de getEmDashCollection() e getEmDashEntry() inferem os campos das coleções locais sem um alias de caminho.

O comando separado emdash types busca o esquema de uma instância local ou remota em execução e grava .emdash/types.ts por padrão. Adicione um alias somente quando o código da aplicação importar diretamente essa saída independente:

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

Gere os tipos independentes do esquema remoto com o seguinte comando:

npx emdash types