Os plugins EmDash usam um de dois formatos: sandboxed ou native. Escolha o formato antes de escrever o plugin porque a forma de autoria, o caminho de instalação e o limite de confiança diferem.
Escolha um plugin sandboxed a menos que o plugin precise de uma integração apenas nativa. Plugins sandboxed podem ser publicados no registry e instalados pela UI de administração. Um plugin nativo é um pacote npm que um operador do site instala no projeto e adiciona a astro.config.mjs antes de redesployar.
Em resumo
| Sandboxed | Native | |
|---|---|---|
| Authoring shape | emdash-plugin.jsonc + src/plugin.ts | definePlugin() descriptor |
| Install method | One-click from the admin registry | npm install + edit astro.config |
| Runs in | An isolated runtime provided by a sandbox runner | Same process as your Astro site |
Capability-gated ctx APIs | Enforced by the sandbox bridge | Gated by PluginContext, but not a security boundary |
| Resource limits | Runner limits for CPU, subrequests, and wall time; platform memory ceiling | No per-plugin limits |
| Network access | ctx.http, restricted to declared access | ctx.http follows declarations; native code can also call fetch() |
Direct fetch() / process.env | Blocked by the runner | Possible (plugin code shares the runtime) |
| Distribution | Signed release in the plugin registry | npm package |
| Admin UI | Block Kit (JSON-described) routes | React components, or Block Kit |
| Settings UI | Block Kit page + ctx.settings | admin.settingsSchema (auto-form) or Block Kit |
| Portable Text rendering components | Not available | componentsEntry provides Astro components |
| Page metadata contributions | page:metadata hook — meta/property tags, allowlisted <link> rels, JSON-LD | page:metadata hook (same surface) |
| Page fragment injection | Not available — meta/JSON-LD only via page:metadata | page:fragments hook — inline scripts, external scripts, raw HTML |
| Constructor options | None — read settings from KV at runtime | options on the descriptor |
Custos de um plugin nativo
Plugins nativos têm um modelo de instalação e confiança diferente:
- Instalação no nível do projeto. Cada site precisa instalar seu pacote npm, editar
astro.config.mjse redesployar. - Sem isolamento. Um bug no seu plugin pode derrubar o processo host ou consumir seu orçamento de CPU. Uma rejeição não tratada em um hook pode derrubar a requisição ao redor junto.
- Carga de confiança no usuário. Plugins nativos têm o mesmo acesso que o site host. Declarações de capability sozinhas não conseguem mostrar tudo o que o código pode fazer.
Se o seu plugin puder fazer o trabalho no sandbox, deve fazê-lo.
Quando ir para nativo
Escolha nativo para recursos que precisam de integração em tempo de build com o site host:
-
Páginas ou widgets de administração React personalizados. Plugins sandboxed descrevem a UI de administração com Block Kit — um esquema JSON que a administração renderiza em nome do plugin. Se você precisa de React completo (hooks personalizados, componentes de terceiros, estado complexo), precisa de nativo.
-
Tipos de bloco Portable Text personalizados. Sua configuração de edição e componentes de renderização Astro são carregados do pacote npm instalado. Só plugins nativos podem fornecer essa superfície em tempo de build.
-
Injetar HTML bruto, scripts ou folhas de estilo em páginas públicas. O hook
page:fragmentsenvia código de primeira parte aos navegadores dos visitantes — fora de qualquer limite de sandbox. É restrito a plugins nativos. Plugins sandboxed ainda podem contribuir para páginas públicas pelo hookpage:metadata, que cobre muitos casos de uso reais:- tags
meta(name+content) — descrições SEO, diretivas robots, Twitter cards - tags
property— OpenGraph e outro meta baseado em property - tags
linkcom uma allowlist de rel bloqueada por segurança (canonical,alternate,author,license,nlweb,site.standard.document) —stylesheet,prefetche rels semelhantes de carregamento de recursos são deliberadamente não permitidos - grafos JSON-LD
Se sua necessidade de «injeção de página» for dados estruturados ou metadados SEO, fique sandboxed e use
page:metadata. Se você realmente precisa enviar JavaScript ou HTML ao navegador do visitante, esse é o caso para ir a nativo. - tags
Se nenhum desses recursos se aplicar, use o formato sandboxed.
Runners de sandbox e suporte de plataforma
O sandbox em si é plugável. EmDash expõe uma opção de configuração sandboxRunner e o runner decide como o código do plugin é isolado — não há nada específico do Cloudflare no formato do plugin.
Dois runners vêm com EmDash: sandbox() de @emdash-cms/cloudflare, que executa cada plugin como Dynamic Worker pelo Worker Loader da Cloudflare, e @emdash-cms/sandbox-workerd/sandbox, que executa plugins em um processo filho workerd no Node.js. Plugin Sandbox cobre a configuração de cada runner, os limites de recursos que aplica e as diferenças entre os dois.
Se nenhum runner estiver configurado, plugins listados em sandboxed: [] não são carregados. Se o runner configurado estiver indisponível na plataforma atual, também não são carregados, e EmDash registra um aviso na inicialização.
Se quiser que um plugin sandboxed rode em uma plataforma sem runner de sandbox, mova-o de sandboxed: [] para o array plugins: [] — ele executará in-process. Declarações de capability ainda são honradas (a mesma factory PluginContext limita ctx.content, ctx.http e similares), mas não há limite de isolamento, nem limites de recursos, e um plugin com bugs ou malicioso pode chamar fetch() diretamente, ler variáveis de ambiente ou bloquear o event loop. Sem um runner de sandbox ativo, trate cada plugin como um plugin nativo para fins de confiança.