EmDash para desenvolvedores Astro

Nesta página

O EmDash adiciona a um site Astro um aplicativo de administração, coleções respaldadas por banco de dados, mídia, menus, taxonomias, configurações, revisões e pré-visualizações. As páginas e os componentes continuam sendo arquivos Astro comuns.

O que o EmDash adiciona

RecursoO que ele oferece
AdministraçãoGerenciamento no navegador de coleções, mídia, menus, taxonomias e configurações em /_emdash/admin
Coleções em banco de dadosConteúdo gerenciado por editores e consultado no momento da requisição
Biblioteca de mídiaImagens e arquivos armazenados, com valores de campos de mídia para os templates
Rascunhos, revisões e pré-visualizaçõesTrabalho editorial antes da publicação
Menus e áreas de widgetsRegiões do site ordenadas e editáveis, fora dos campos das entradas
Configurações do siteValores compartilhados de identidade e exibição, como título, slogan, logotipo e tamanho da paginação
PluginsHooks, rotas, armazenamento e extensões opcionais da administração

Esses recursos convivem com o Astro em vez de substituí-lo. O Astro continua controlando o roteamento, os layouts, a renderização, os estilos e o adaptador de implantação.

EmDash e coleções Astro

As coleções de conteúdo do Astro e as coleções do EmDash podem coexistir. Use coleções Astro para o conteúdo que pertence ao repositório e o EmDash para o conteúdo gerenciado por meio de /_emdash/admin.

Coleção de conteúdo AstroColeção EmDash
ArmazenamentoArquivos no projetoBanco de dados SQL
EdiçãoFluxo de trabalho do repositórioAdministração do EmDash
ConsultagetCollection()getEmDashCollection()
Rich textMarkdown ou MDXPortable Text
EntregaEm tempo de build ou com um loader ao vivoLoader ao vivo em tempo de execução

Use os dois sistemas de coleções quando a propriedade do conteúdo for diferente. Por exemplo, o site de um produto pode manter as notas de versão escritas por desenvolvedores em uma coleção de conteúdo Astro e os artigos escritos por editores no EmDash:

---
import { getCollection } from "astro:content";
import { getEmDashCollection } from "emdash";

const [releaseNotes, { entries: articles }] = await Promise.all([
  getCollection("releases"),
  getEmDashCollection("articles", { limit: 3 }),
]);
---

Os dois resultados permanecem separados. O EmDash não copia as entradas baseadas em arquivos para o seu banco de dados.

Configurar um site

Os templates Node atuais configuram o Astro para saída de servidor, adicionam a integração do EmDash e usam os adaptadores de SQLite e de armazenamento local.

A configuração reduzida a seguir contém essas peças necessárias:

import node from "@astrojs/node";
import react from "@astrojs/react";
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";

export default defineConfig({
  output: "server",
  adapter: node({ mode: "standalone" }),
  integrations: [
    react(),
    emdash({
      database: sqlite({ url: "file:./data.db" }),
      storage: local({
        directory: "./uploads",
        baseUrl: "/_emdash/api/media/file",
      }),
    }),
  ],
});

O EmDash também fornece templates do Cloudflare configurados para D1 e R2. Comece pelo template do destino de implantação em vez de converter manualmente os adaptadores Node.

Registrar a coleção ao vivo

Os templates expõem o conteúdo do EmDash por meio de uma única coleção ao vivo do Astro chamada _emdash:

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

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

getEmDashCollection() e getEmDashEntry() selecionam o tipo de conteúdo solicitado por meio desse loader.

Consultar coleções

A consulta a seguir lê os posts publicados mais recentemente. orderBy usa os nomes de campo armazenados e associa cada nome a "asc" ou "desc":

---
import { getEmDashCollection } from "emdash";

const { entries: posts, error, cacheHint } = await getEmDashCollection("posts", {
  orderBy: { published_at: "desc" },
  limit: 10,
});

if (error) return new Response("Could not load posts", { status: 500 });
if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---

{posts.map((post) => (
  <article>
    <h2><a href={`/posts/${post.id}`}>{post.data.title}</a></h2>
  </article>
))}

As consultas anônimas retornam conteúdo publicado. Um filtro status explícito é útil em código autenticado ou com suporte a pré-visualização. where aceita campos de conteúdo e nomes de taxonomias; consulte Consultar conteúdo para ver os formatos completos de filtros e paginação.

Consultar uma entrada

Passe um slug ou um ID de banco de dados para getEmDashEntry(). A rota a seguir usa o slug da sua URL:

---
import { decodeSlug, getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";

const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.rewrite("/404");

const { entry: post, error, cacheHint } = await getEmDashEntry("posts", slug);
if (error) return new Response("Could not load the post", { status: 500 });
if (!post) return Astro.rewrite("/404");
if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---

<article>
  <h1>{post.data.title}</h1>
  <PortableText value={post.data.content} />
</article>

O entry.id retornado é o identificador de rota do Astro e normalmente é o slug. O ID de conteúdo do banco de dados é entry.data.id. Use data.id com helpers que exigem um ID de conteúdo armazenado.

Usar recursos dinâmicos do CMS

O EmDash exporta helpers de servidor para dados que não pertencem a uma única entrada de coleção:

---
import { getMenu, getSiteSettings } from "emdash";
import { WidgetArea } from "emdash/ui";

const [menu, settings] = await Promise.all([
  getMenu("primary"),
  getSiteSettings(),
]);
---

<header>
  <a href="/">{settings.title}</a>
  <nav>
    {menu?.items.map((item) => <a href={item.url}>{item.label}</a>)}
  </nav>
</header>

<main><slot /></main>
<aside><WidgetArea name="sidebar" /></aside>

Escolher um formato de plugin

Plugins em sandbox e plugins nativos têm estruturas de pacote diferentes. Os plugins em sandbox usam emdash-plugin.jsonc mais um objeto src/plugin.ts exportado como padrão. Os plugins nativos exportam uma fábrica de descritor e um createPlugin() construído com definePlugin().

Leia Escolher um formato de plugin antes de adicionar um plugin. Não copie um exemplo nativo de definePlugin() para um pacote em sandbox.

Próximos passos