Este guia implanta um site EmDash no Cloudflare Workers com D1 para o banco de dados e R2 para mídia. Comece com um template EmDash Cloudflare ou aplique a mesma configuração a um site Astro existente.
Pré-requisitos
- Uma conta Cloudflare
- As dependências do projeto instaladas
- Wrangler autenticado no Cloudflare (
pnpm wrangler login)
Configurar bindings
Os templates Cloudflare incluem o ponto de entrada do Worker completo e bindings nomeados de D1 e R2. Na primeira implantação, o Wrangler cria qualquer um dos dois recursos se o nome configurado ainda não existir. Mantenha os nomes em wrangler.jsonc; o Wrangler reconecta as implantações seguintes aos mesmos recursos.
O template usa os seguintes bindings:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-emdash-site",
"main": "./src/worker.ts",
"compatibility_date": "2026-02-24",
"compatibility_flags": ["nodejs_compat"],
"d1_databases": [
{
"binding": "DB",
"database_name": "my-emdash-site",
},
],
"r2_buckets": [
{
"binding": "MEDIA",
"bucket_name": "my-emdash-media",
},
],
"worker_loaders": [{ "binding": "LOADER" }],
"triggers": { "crons": ["* * * * *"] },
}
Os nomes DB, MEDIA e LOADER devem corresponder aos adaptadores do EmDash. O Cron Trigger executa a publicação agendada, as tarefas de plugins, os backups e a manutenção. Consulte Plugin sandbox se o site usar plugins em sandbox.
Configurar o EmDash
A configuração do Astro a seguir usa os bindings de D1 e R2.
import { defineConfig } from "astro/config";
import cloudflare from "@astrojs/cloudflare";
import react from "@astrojs/react";
import emdash from "emdash/astro";
import { d1, r2, sandbox } from "@emdash-cms/cloudflare";
export default defineConfig({
output: "server",
adapter: cloudflare(),
integrations: [
react(), // Required — the admin UI is a React app
emdash({
database: d1({ binding: "DB" }),
storage: r2({ binding: "MEDIA" }),
sandboxRunner: sandbox(),
}),
],
});
Se o site não usar plugins de marketplace, registry ou sandboxed, omita sandboxRunner e o binding LOADER.
Adicionar o ponto de entrada do Worker
O ponto de entrada do Worker conecta o Astro ao Cron Trigger e exporta a bridge de plugins:
import handler, { createScheduledHandler, PluginBridge } from "@emdash-cms/cloudflare/worker";
export { PluginBridge };
export default {
...handler,
scheduled: createScheduledHandler(),
} satisfies ExportedHandler;
A exportação de PluginBridge é inofensiva quando nenhum plugin em sandbox está instalado. Mantenha-a se o mesmo projeto puder habilitar plugins mais tarde.
Para executar a manutenção geral em um agendamento diferente de a cada minuto, passe a mesma expressão Cron para createScheduledHandler({ generalCron: "..." }) e para triggers.crons. Se elas forem diferentes, o handler registra o gatilho inesperado e o ignora.
Compilar e implantar
Compile e implante o site uma vez para que o Wrangler provisione o banco de dados D1 e o bucket R2 nomeados. O Wrangler usa o login local criado por pnpm wrangler login.
pnpm build
pnpm wrangler deploy
Com o modo de migração auto padrão, o EmDash aplica as migrações do núcleo pendentes quando o Worker implantado recebe sua primeira requisição. Use Manage core database migrations quando um pipeline de implantação precisar aplicar as migrações antes que o novo código receba tráfego, ou quando você precisar inspecionar, verificar ou recuperar uma migração.
Até que o assistente de configuração seja concluído, o EmDash também aplica uma única vez, na primeira requisição, o esquema e a estrutura de um arquivo seed. O conteúdo de exemplo do seed só é aplicado quando um administrador o escolhe no assistente de configuração. O seed é lido em tempo de build a partir de .emdash/seed.json, do caminho em package.json#emdash.seed ou de seed/seed.json — o que for encontrado primeiro — e incorporado ao bundle. Se nenhum estiver presente, um seed padrão embutido é usado. As implantações seguintes em um banco de dados existente não alteram o conteúdo dele.
Para alterar o esquema ou o modelo de conteúdo de um site que já foi implantado, consulte Evolving a Deployed Site.
Publicação agendada
No Cloudflare, o EmDash publica as entradas agendadas somente a partir do handler scheduled do Worker, que o Cloudflare chama de acordo com o agendamento de um Cron Trigger. O Worker implantado precisa dos dois itens a seguir:
- Um Cron Trigger na lista
triggers.cronsdewrangler.jsonc, como mostrado em Configurar bindings. - O handler
scheduledde@emdash-cms/cloudflare/worker, exportado a partir do ponto de entrada do Worker para o qualmainaponta, como mostrado em Adicionar o ponto de entrada do Worker.
Se qualquer um dos dois estiver ausente, as entradas agendadas não vão ao ar. No desenvolvimento local com astro dev, o EmDash publica as entradas agendadas por meio de um temporizador, então um agendamento que funciona localmente não confirma a configuração implantada.
Execute emdash doctor a partir da raiz do projeto para verificar o Cron Trigger e o handler scheduled nos arquivos do projeto local:
pnpm emdash doctor
Quando emdash doctor encontra os dois, a saída inclui uma verificação scheduler wiring aprovada. Uma verificação do agendador que falha descreve o problema e imprime a correção. A verificação reconhece o ponto de entrada do Worker mostrado nesta página e o re-export de uma linha que ela imprime como correção, então um ponto de entrada escrito de outra forma pode falhar na verificação mesmo funcionando.
Se nenhuma verificação do agendador aparecer, emdash doctor não encontrou nenhuma configuração do Wrangler no diretório atual, ou não encontrou nem o Cron Trigger nem o handler scheduled. Em um projeto D1, a verificação database falha porque procura um arquivo SQLite local (./data.db por padrão). Essa falha não afeta as verificações do agendador.
Implante novamente depois de adicionar ou alterar o Cron Trigger ou o handler scheduled. O Cloudflare pode levar até 15 minutos para começar a executar um Cron Trigger novo ou alterado. Depois que o gatilho começa a ser executado, o EmDash publica as entradas cujo horário agendado já passou.
Para acompanhar o gatilho, execute pnpm wrangler tail. Cada execução imprime uma linha como "* * * * *" @ 9/29/2026, 10:01:00 AM - Ok. Ok significa que a execução terminou sem um erro não capturado. O EmDash captura e registra os erros de publicação, então Ok não confirma que entradas foram publicadas. Uma execução que publica entradas também registra uma mensagem como [scheduled] Published 1 scheduled item(s), e os erros da execução aparecem na mesma saída.
Após a implantação, o painel de administração mostra Scheduled publishing needs attention quando uma entrada agendada passou do horário agendado e nenhuma execução do agendador foi concluída nos últimos cinco minutos. Se o Cron Trigger for executado com menos frequência do que a cada cinco minutos, o aviso também pode aparecer entre as execuções até que a próxima publique a entrada.
Colocar o Worker perto do D1
O Cloudflare executa um Worker perto do visitante por padrão. As requisições renderizadas no servidor do EmDash fazem várias idas e vindas ao D1, então use o Targeted Placement para executar o Worker perto do primário do D1 e acelerar essas requisições.
O Wrangler aceita placement.mode: "targeted" com exatamente um seletor: region, host ou hostname. Selecione o valor que aponta para a localização do primário do D1 e adicione o objeto placement resultante a wrangler.jsonc. Não habilite réplicas de leitura do D1 junto com o Targeted Placement. Mantenha a configuração session do EmDash no valor padrão, "disabled", para que leituras e gravações usem o primário próximo.
Cache de objetos
Para reduzir a carga de leitura no D1, armazene em cache no Cloudflare KV os resultados das consultas de conteúdo e configuração. As leituras são atendidas pelo KV, em vez de consultar o banco de dados a cada requisição:
import { d1, r2, kvCache } from "@emdash-cms/cloudflare";
emdash({
database: d1({ binding: "DB" }),
storage: r2({ binding: "MEDIA" }),
objectCache: kvCache({ binding: "CACHE" }),
}),
Consulte Object Cache para a configuração do KV, as opções e o comportamento de invalidação.
Workers Cache
O Workers Cache do Cloudflare coloca um cache de borda na frente do seu Worker: as requisições correspondentes são atendidas sem executar o seu Worker.
Ativá-lo
-
Use o provedor de cache Cloudflare do Astro para que as regras de rota e
Astro.cachedefinam os cabeçalhos de cache e a invalidação usecache.purge().import { cacheCloudflare } from "@astrojs/cloudflare/cache"; export default defineConfig({ adapter: cloudflare(), cache: { provider: cacheCloudflare(), }, routeRules: { "/": { maxAge: 300, swr: 86400 }, // Other public routes can use different cache lifetimes. }, });O adaptador
@astrojs/cloudflaredetectacacheCloudflare()e habilita o Workers Cache na configuração de implantação gerada. -
Limpe as respostas em cache a partir do código do Worker com a API da plataforma. Essa chamada não precisa de credenciais da API REST do Cloudflare.
import { cache } from "cloudflare:workers"; await cache.purge({ purgeEverything: true }); // Or purge selected tags: await cache.purge({ tags: ["posts"] });
As respostas de administração e de API do EmDash já enviam Cache-Control: private, no-store e nunca são armazenadas. As páginas públicas controlam o próprio cache por meio de Cache-Control / routeRules / Astro.cache.
Duas coisas para saber antes de habilitá-lo:
- Respostas sem cabeçalho
Cache-Controlainda são armazenadas em cache. O Workers Cache aplica a atualidade heurística da RFC 9111 — uma200sem nenhum cabeçalho é armazenada em cache por 2 horas. Dê a cada rota personalizada umCache-Controlexplícito (useprivate, no-storepara qualquer coisa que dependa da sessão). - As páginas em cache são compartilhadas com editores conectados. O cache é executado antes do seu Worker, então não pode ser ignorado com base nos cookies da requisição. Um editor conectado pode receber a variante anônima em cache de uma página pública — sem a barra de ferramentas de edição visual — até que a entrada expire. As respostas renderizadas para o editor nunca são armazenadas (elas carregam
private, no-store), então nada vaza na outra direção.
O Workers Caching é separado do cache de objetos (objectCache: kvCache({ binding: "CACHE" })), que armazena em cache os resultados de consultas ao banco de dados no KV, abaixo do Worker.
Domínios personalizados
A primeira implantação recebe uma URL workers.dev. O domínio personalizado deve já ser um domínio ativo gerenciado pelo Cloudflare na mesma conta do Worker. Depois que o Worker responder com sucesso na URL workers.dev, adicione o domínio de produção como uma rota do Wrangler:
{
"routes": [{ "pattern": "www.example.com", "custom_domain": true }],
}
Implante novamente e verifique os dois endereços. Manter o endereço workers.dev disponível enquanto você testa o DNS ajuda a distinguir um problema de roteamento de um problema da aplicação. Para que o novo domínio seja o endereço nos sitemaps e nos metadados de busca, e nos e-mails e plugins quando siteUrl, EMDASH_SITE_URL ou SITE_URL não está definido, use Change domain em Settings > General; veja Mudar para um novo domínio.
Sem siteUrl, EMDASH_SITE_URL ou SITE_URL, a configuração registra como origem do site o endereço em que ela é executada, e as passkeys criadas durante a configuração só funcionam nesse endereço. Execute a configuração no domínio de produção ou defina EMDASH_SITE_URL com esse domínio antes da configuração. Se você definir EMDASH_SITE_URL com outro domínio depois da configuração, o login passa para esse domínio e as passkeys criadas no endereço antigo deixam de funcionar nele.
Acesso público ao R2
Por padrão, a mídia é servida pela rota de mídia autenticada do EmDash. Se o bucket tiver um domínio personalizado público, defina essa origem como publicUrl para que as URLs de mídia geradas a usem:
storage: r2({
binding: "MEDIA",
publicUrl: "https://media.example.com",
}),
O acesso público ao bucket se aplica a todos os objetos alcançáveis, não apenas à mídia. Os backups JSON automáticos usam o prefixo backups/ no mesmo backend de armazenamento, então não exponha esse prefixo pelo domínio público. Choose media storage explica o limite seguro.
Transformação de imagens
O EmDash redimensiona e recodifica a mídia do R2 dentro do Worker, por meio do binding IMAGES do Cloudflare. O componente Image de emdash/ui e as imagens em rich text são ambos renderizados pelo endpoint de imagens que o EmDash instala sob o adaptador Cloudflare. Para a mídia na rota interna /_emdash/api/media/file/…, esse endpoint lê os bytes de origem diretamente do binding do R2, sem um fetch HTTP. Essas transformações continuam funcionando atrás do Cloudflare Access e com global_fetch_strictly_public. A mídia servida a partir de uma URL de bucket — consulte Acesso público ao R2 — usa, em vez disso, o endpoint de transformação do próprio adaptador, que busca o arquivo por HTTP antes de transformá-lo.
Você não precisa declarar o binding. O @astrojs/cloudflare o adiciona à configuração do Worker que gera durante astro build, da mesma forma que adiciona cache para o Workers Caching. Ele faz isso sempre que o serviço de imagens em tempo de execução é cloudflare-binding: imageService não definido, a própria string ou { runtime: "cloudflare-binding" }. Qualquer outro valor — "passthrough", "compile", "cloudflare", "custom" — deixa o binding de fora. Listá-lo no seu próprio wrangler.jsonc deixa a intenção evidente:
{
"images": {
"binding": "IMAGES",
},
}
Para ver o que uma implantação realmente recebe, leia a configuração gerada em vez de wrangler.jsonc. Um build grava .wrangler/deploy/config.json, que aponta wrangler deploy para o arquivo mesclado (dist/server/wrangler.json por padrão). Procure ali uma entrada images.
O Cloudflare cobra essas transformações como Images transformations. Cada combinação única de imagem de origem e parâmetros é cobrada uma vez por mês-calendário, e as requisições repetidas dentro desse mês são gratuitas. Se um site tem 500 imagens de origem e solicita um tamanho de miniatura e um tamanho de hero para cada imagem, esses dois conjuntos de parâmetros contam como 1.000 imagens transformadas naquele mês. O plano Images Free cobre 5.000 transformações únicas por mês. Acima desse limite, as transformações em cache ainda são servidas, mas as novas retornam um erro 9422 e a requisição da imagem falha.
Autenticação Cloudflare Access
O Cloudflare Access pode substituir a autenticação por passkey pelo provedor de identidade associado a uma aplicação do Access. O valor de audience é uma configuração secreta em tempo de execução; mantenha-o fora de astro.config.mjs informando o nome da variável de ambiente dele:
import { access } from "@emdash-cms/cloudflare";
emdash({
auth: access({
teamDomain: "myteam.cloudflareaccess.com",
audienceEnvVar: "CF_ACCESS_AUDIENCE",
roleMapping: {
Admins: 50,
Editors: 40,
},
}),
}),
Defina CF_ACCESS_AUDIENCE com pnpm wrangler secret put CF_ACCESS_AUDIENCE. O authentication guide explica o provisionamento de usuários, as funções padrão e a sincronização de funções.
Os Workers de produção não têm um serviço padrão de envio de e-mail. O login por link mágico, os convites de equipe e as notificações de comentários retornam Email is not configured até que um plugin de e-mail esteja ativo.
O plugin de e-mail do Cloudflare usa um binding send_email. Primeiro, registre e verifique o domínio remetente com o Cloudflare Email Sending. O Cloudflare rejeita mensagens cujo endereço From não seja um remetente aceito.
Adicione o binding e registre o provedor:
{
"send_email": [{ "name": "EMAIL" }],
}
import { cloudflareEmail } from "@emdash-cms/cloudflare/plugins";
emdash({
plugins: [
cloudflareEmail({
from: { email: "[email protected]", name: "My Site CMS" },
replyTo: "[email protected]",
}),
],
}),
Após a implantação, ative o plugin em Extensions e selecione-o em Settings → Email. O envio falha até que o remetente seja aceito e o binding exista.
O plugin usa o binding chamado EMAIL, a menos que a opção binding dele indique outro nome. Se ele for o único provedor de e-mail ativo, o EmDash o seleciona automaticamente. Se mais de um provedor estiver ativo, escolha o provedor Cloudflare em Settings → Email. O endereço opcional replyTo recebe as respostas sem alterar o endereço From aceito. Um plugin pode definir replyTo em uma mensagem individual, o que substitui essa opção para aquela mensagem.
Cloudflare AI Search
O plugin AI Search precisa de um registro de plugin nativo e de um binding ai_search_namespaces. Depois de implantá-los, abra Cloudflare AI Search na administração, escolha as coleções e execute Sync All Content. A sincronização inicial indexa o conteúdo publicado antes de o plugin ser habilitado; os hooks mantêm as alterações posteriores sincronizadas.
import { aiSearch } from "@emdash-cms/cloudflare/plugins";
emdash({
plugins: [aiSearch()],
}),
{
"ai_search_namespaces": [{ "binding": "AI_SEARCH", "namespace": "default" }],
}
Exponha a rota de busca a partir do site:
export { POST, prerender } from "@emdash-cms/cloudflare/plugins/ai-search";
Adicione a interface de busca a um layout. O slot de gatilho aceita um botão que combine com o design do site:
---
import AISearchSnippet from "@emdash-cms/cloudflare/plugins/ai-search/astro";
---
<AISearchSnippet apiUrl="/api/ai-search" placeholder="Search content">
<button slot="trigger" type="button">Search</button>
</AISearchSnippet>
Segredos do Worker
Armazene os valores secretos com pnpm wrangler secret put <NAME>. Não os coloque em wrangler.jsonc nem os leia de valores de import.meta.env em tempo de build.
EMDASH_ENCRYPTION_KEY criptografa as configurações de plugin declaradas como segredos. Defina-a antes de salvar um segredo de plugin e preserve-a separadamente dos backups do D1. Durante a rotação, forneça primeiro a nova chave e mantenha as chaves antigas após vírgulas até que todos os segredos de plugin tenham sido salvos novamente. Secrets and key management descreve a rotação e a recuperação.
A bridge de plugins lê diretamente esse binding de segredo do Worker. A rota de configurações de administração gerada o lê por meio de process.env. Com nodejs_compat, o 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 antes de salvar configurações criptografadas.
O EmDash lê seus segredos de process.env em tempo de execução. O código do Worker lê os bindings de env, importado de cloudflare:workers. Nunca leia segredos por meio de import.meta.env: o Vite substitui esses valores em tempo de build e pode gravá-los no bundle do servidor.
O segredo HMAC de preview e o salt de IP dos autores de comentários são gerados e armazenados no banco de dados, a menos que você forneça substituições em tempo de execução. Secrets and key management lista as variáveis exatas, os locais de armazenamento e os efeitos da rotação.
Implantações de preview
Um preview pode ser executado como um Worker Preview, que dá a cada branch sua própria URL no Worker de produção, ou como um Worker separado em um ambiente nomeado do Wrangler. Em ambos os casos, o preview precisa de um banco de dados e de um bucket separados da produção. Nunca aponte um binding de preview para um banco de dados ou bucket de produção.
Worker Previews
Worker Previews exige Wrangler 4.135.0 ou posterior nas dependências do projeto. Projetos criados a partir de um template antigo do EmDash podem fixar uma versão anterior; atualize-a com pnpm add -D wrangler@latest. Os previews não herdam bindings nem vars da configuração de nível superior; liste em um bloco previews todos os bindings que o preview usa.
O adaptador do Astro para Cloudflare adiciona um binding KV SESSION. O wrangler deploy o provisiona automaticamente, mas o wrangler preview o rejeita sem um ID de namespace. Crie os recursos de preview, incluindo um namespace KV para sessões:
pnpm wrangler d1 create my-emdash-site-preview
pnpm wrangler r2 bucket create my-emdash-media-preview
pnpm wrangler kv namespace create my-emdash-site-preview-session
Adicione ao wrangler.jsonc os identificadores de recursos que o Wrangler imprime:
{
"previews": {
"d1_databases": [
{
"binding": "DB",
"database_name": "my-emdash-site-preview",
"database_id": "00000000-0000-0000-0000-000000000000",
},
],
"r2_buckets": [
{
"binding": "MEDIA",
"bucket_name": "my-emdash-media-preview",
},
],
"kv_namespaces": [{ "binding": "SESSION", "id": "00000000000000000000000000000000" }],
"worker_loaders": [{ "binding": "LOADER" }],
},
}
Repita send_email, AI Search, vars e outros bindings quando o preview usar esses recursos.
O assistente de configuração e as passkeys precisam da URL do site do preview. Sem siteUrl ou EMDASH_SITE_URL, a configuração falha com SITE_URL_REQUIRED. Passe a URL do preview, https://<preview-name>-<worker-name>.<subdomain>.workers.dev, em cada implantação de preview:
pnpm build
pnpm wrangler preview --name my-branch \
--var EMDASH_SITE_URL:https://my-branch-my-emdash-site.example.workers.dev
Use o mesmo nome de preview em --name e na URL. Um siteUrl em astro.config.mjs substitui EMDASH_SITE_URL e é embutido em todo preview, então as passkeys no preview ficam vinculadas ao domínio de produção e nem a configuração nem o login funcionam ali. Defina a URL de produção com EMDASH_SITE_URL nos vars de nível superior.
Se o Worker definir workers_dev como false, os previews não têm URL até que você defina "preview_urls": true no nível superior de wrangler.jsonc e execute wrangler deploy uma vez. O wrangler preview não aplica essa configuração. O wrangler deploy publica em produção o código do seu checkout atual, não apenas a configuração, então faça o commit da alteração e implante a partir de um checkout limpo da sua branch de produção. Depois volte para a sua branch e execute wrangler preview novamente.
Defina um secret para um único preview com pnpm wrangler preview secret put <NAME> --name my-branch. pnpm wrangler preview base-config secret put <NAME> define um secret para os previews criados depois; os previews existentes mantêm seus secrets.
Tenha em mente estas diferenças em relação à produção:
- Os previews compartilham os recursos do bloco
previews. Owrangler previewlê o blocopreviewsda branch que implanta, então toda branch que mantém a configuração da branch base usa o mesmo banco de dados. A primeira requisição a um preview aplica as migrações do núcleo pendentes, de modo que uma branch que atualiza o EmDash também migra o banco de dados usado pelos outros previews. Para isolar uma branch, crie outro banco de dados D1 e alteredatabase_nameedatabase_idno blocopreviewsdessa branch antes de implantá-la. - Um banco de dados de preview vazio mostra o assistente de configuração. As URLs de preview são públicas, e o primeiro visitante a concluir o assistente se torna o administrador. Conclua a configuração imediatamente após criar o preview ou proteja as URLs de preview com o Cloudflare Access.
- Os Cron Triggers não são executados. Posts agendados não são publicados, e as tarefas cron de plugins e os backups agendados não são executados em um preview.
- As passkeys funcionam apenas no hostname que as registrou. As passkeys de produção não funcionam em um preview, e o administrador criado no primeiro preview só pode entrar com uma passkey nessa URL de preview. Em outro preview que compartilha o banco de dados, entre com um magic link, que precisa de um provedor de e-mail e do binding dele no bloco
previews, e adicione ali uma passkey. Como alternativa, isole a branch com um banco de dados próprio, como descrito acima, e execute a configuração nela.
Ambientes nomeados
Ambientes nomeados do Wrangler não herdam bindings. Crie recursos de preview separados e grave-os no ambiente preview antes de compilar:
pnpm wrangler d1 create my-emdash-site-preview \
--binding DB --env preview --update-config
pnpm wrangler r2 bucket create my-emdash-media-preview \
--binding MEDIA --env preview --update-config
O ambiente de preview deve repetir todos os bindings que o Worker de preview usa. Os bindings principais de D1, R2 e sandbox têm este formato depois que o Wrangler grava os identificadores dos recursos:
{
"env": {
"preview": {
"d1_databases": [
{
"binding": "DB",
"database_name": "my-emdash-site-preview",
"database_id": "00000000-0000-0000-0000-000000000000",
},
],
"r2_buckets": [
{
"binding": "MEDIA",
"bucket_name": "my-emdash-media-preview",
},
],
"worker_loaders": [{ "binding": "LOADER" }],
},
},
}
Use o UUID de preview gravado pelo Wrangler. Repita os bindings opcionais de KV, AI Search, e-mail e outros quando o preview usar esses recursos. Adicione segredos exclusivos do preview com pnpm wrangler secret put <NAME> --env preview.
Compile e implante o ambiente de preview. A primeira requisição dele aplica as migrações do núcleo pendentes por meio do modo auto padrão.
pnpm build
pnpm wrangler deploy --env preview
Verifique a URL de preview, o login na administração, o upload de mídia e qualquer binding opcional antes de compartilhá-la.
Verificar a implantação
Após a implantação, solicite uma página pública, faça login em /_emdash/admin, envie e recupere um arquivo de mídia de teste e confirme que o handler scheduled aparece em pnpm wrangler tail.
Solução de problemas
”D1 binding not found”
Verifique se o nome do binding em wrangler.jsonc corresponde à configuração do seu banco de dados:
// Must match: d1({ binding: "DB" })
"binding": "DB"
“R2 binding not found”
Verifique se o bucket R2 está corretamente vinculado:
// Must match: r2({ binding: "MEDIA" })
"binding": "MEDIA"
Erros de migração
Se você vir erros de esquema, acompanhe os logs do Worker (wrangler tail) e reproduza o erro para capturar a mensagem subjacente — depois abra uma issue com essa saída.