Desenvolvimento e IA Aplicada · Explicador
Content Collections do Astro: conteúdo em escala
Quando um site passa de algumas páginas para centenas de textos, o problema deixa de ser escrever e passa a ser manter tudo consistente. Veja como o Astro resolve isso com coleções tipadas.
- Autoria:
- Redação Token & Tech
- Editor responsável:
- Daniel Ferreira
Publicado em · 6 min de leitura
Também disponível em: English
Em três pontos
- Uma coleção agrupa entradas com a mesma estrutura; um loader diz de onde vêm os dados e um schema Zod diz o que é válido.
- Entrada fora do schema faz o build falhar com erro explicativo, o que transforma regras editoriais em verificação automática.
- Referências entre coleções ligam artigos a autores e fontes, mas o código ainda precisa tratar o caso de uma referência não encontrada.
Um site com dez artigos cabe na cabeça de quem o mantém. Com duzentos, em vários idiomas, não cabe mais. Alguém esquece a data de publicação, digita a categoria com acento, aponta para um autor que não existe. Nada disso dá erro visível: a página só sai errada.
As Content Collections do Astro, o framework de sites que gera páginas a partir de componentes e arquivos de conteúdo, existem para esse problema. Este texto explica como elas funcionam segundo a documentação oficial e mostra, como caso documentado, o uso no próprio site do Token & Tech.
O que é uma coleção
A documentação do Astro define uma coleção como um conjunto de dados com a mesma estrutura, como posts de blog ou fichas de produto. Cada item é uma entrada (entry).
A documentação indica três situações em que vale usar coleções:
- várias entradas com a mesma estrutura, como uma pasta de arquivos Markdown com o mesmo cabeçalho;
- conteúdo remoto, de um CMS (sistema de gestão de conteúdo), que você quer consultar com as mesmas funções;
- milhares de entradas processadas no momento do build, a etapa que gera o site.
E indica quando não usar: páginas únicas (que ficam em src/pages/), arquivos que não precisam de processamento, como PDFs (que ficam em public/), ou fontes de dados cuja biblioteca própria você prefere chamar diretamente.
Duas modalidades: no build e ao vivo
Há dois tipos de coleção, segundo a mesma página.
Coleções de build carregam os dados durante a geração do site e os guardam numa camada de dados. Servem para conteúdo relativamente estável, como artigos. São definidas em src/content.config.ts.
Coleções ao vivo (live collections) buscam os dados a cada requisição. Servem para dados que mudam o tempo todo. Ficam em src/live.config.ts, exigem um adaptador de renderização sob demanda e, segundo a documentação, não suportam MDX nem otimização de imagens.
Para um site editorial publicado como arquivos estáticos, o caminho natural é a coleção de build. É dela que trata o resto do texto.
As três peças: coleção, loader e schema
Uma coleção é declarada com defineCollection() e tem duas partes: um loader, obrigatório, e um schema, opcional. Todas as coleções são exportadas juntas num objeto collections.
O loader diz de onde vêm os dados. O Astro traz dois prontos, descritos na referência da API de loaders:
glob()lê vários arquivos locais que batem com um padrão, como**/*.md, a partir de uma pasta base. Aceita Markdown, MDX, Markdoc, JSON, YAML e TOML.file()lê várias entradas de um único arquivo JSON, YAML ou TOML. Cada entrada precisa de umidúnico.
Para outras fontes, como uma API, você escreve um loader próprio. A API prevê, entre outras coisas, um armazenamento por coleção, uma função que valida cada entrada antes de gravá-la e um digest, uma impressão digital do conteúdo que evita regravar o que não mudou.
O schema diz o que é uma entrada válida. Ele é escrito com Zod, uma biblioteca de validação para TypeScript, importada de astro/zod. O schema cumpre dois papéis: valida os dados e gera os tipos que o editor de código usa para autocompletar. A documentação resume a consequência: se um arquivo viola o schema da coleção, o Astro mostra um erro para avisar você.
Essa camada de loaders estreou no Astro 5, lançado em dezembro de 2024. No anúncio, a empresa afirmou que as coleções passaram a gerar páginas Markdown até 5 vezes mais rápido em sites com muito conteúdo e reduziram o uso de memória entre 25% e 50% (Astro 5.0). São números divulgados pela própria empresa, não medições independentes.
Identificadores, referências e consultas
ID. Cada entrada tem um identificador. No glob(), ele é gerado a partir do nome do arquivo. Há um detalhe que costuma surpreender: se o arquivo tiver um campo slug no cabeçalho, esse campo passa a ser o ID. A opção generateId permite definir outra regra.
Referências. A função reference("authors") declara, no schema, que um campo aponta para uma entrada de outra coleção. No arquivo, você escreve só o ID do autor. A referência do módulo astro:content faz uma ressalva importante: a validação da entrada referenciada acontece quando você a busca com getEntry() ou getEntries(). Se ela não existir, o resultado é undefined, e seu código precisa tratar esse caso.
Consultas. getCollection() devolve todas as entradas e aceita um filtro, por exemplo para ficar só com as publicadas. getEntry() devolve uma entrada pelo ID. A documentação avisa que a ordem do resultado não é garantida: ordene você mesmo, por data ou título.
Renderização. render(entrada) devolve um componente Content com o corpo do texto e a lista de intertítulos, útil para montar um sumário.
Tipos. O comando astro sync gera os tipos do módulo astro:content (referência da CLI). O Astro também gera arquivos JSON Schema em .astro/collections/, que editores como o VS Code podem usar para validar arquivos YAML e JSON enquanto você digita.
Regras editoriais que viram erro de build
O schema não precisa se limitar a “este campo é texto”. Com Zod, ele pode expressar regras que envolvem vários campos. O método .superRefine() permite registrar vários problemas numa única função de validação (documentação do Zod 4).
É aqui que coleções deixam de ser só organização de pastas. Uma regra como “artigo publicado precisa de data e de responsável pela aprovação” deixa de ser um item de checklist e passa a impedir que o site seja gerado. Na avaliação da redação, esse é o ganho principal em escala: a regra é aplicada do mesmo jeito no texto 1 e no texto 200, inclusive quando quem escreve é um agente de IA (veja como funciona o Claude Code).
O limite também é claro. O schema confere a forma dos dados, não a verdade deles. Ele garante que existe uma URL de fonte, não que a fonte diz o que o texto afirma.
Caso documentado: o site do Token & Tech
O site que você está lendo é construído com Astro, na versão 7 em outubro de 2026, e organiza o conteúdo em coleções. O desenho está descrito no CONTENT_MODEL.md do projeto e implementado em src/content.config.ts. Os trechos abaixo são resumidos.
Artigo e tradução são coleções separadas. Cada artigo tem um registro independente de idioma (articles/<id>.yaml) com tipo, seção, créditos, status, aprovação e fontes. Cada versão em um idioma é um arquivo próprio (article-translations/<id>/<idioma>.md), com título, slug e texto. O ID do artigo é permanente e igual em todos os idiomas; o slug muda por idioma.
Como as traduções têm um campo slug, o comportamento padrão do glob() usaria o slug como ID. Por isso o projeto define o ID pelo caminho do arquivo:
loader: glob({
pattern: "[a-z0-9]*/[a-z]*.md",
base: "./src/content/article-translations",
generateId: ({ entry }) => entry.replace(/\.md$/, ""),
}),
O padrão também tem outra função: arquivos e pastas que começam com _ são modelos e nunca são carregados.
Valores fechados vêm de dados tipados. Categorias e tópicos são listas em TypeScript, e o schema aceita só esses valores, com z.enum(TOPIC_IDS). Um tópico digitado errado não gera página órfã: derruba o build.
Relações usam reference(). Créditos apontam para a coleção de autores, e fontes apontam para a coleção de fontes, em que cada referência tem título, publicador, URL e data de acesso.
Regras de publicação estão no schema. Um trecho do superRefine dos artigos:
if (a.status === "published" || a.status === "update-required") {
if (!a.publishedAt) ctx.addIssue({ code: "custom", message: "published article needs publishedAt" });
if (!a.approvedBy || !a.approvedAt || !a.approval) ctx.addIssue({ code: "custom", message: "..." });
}
Há regras semelhantes para conteúdo financeiro (exige revisão adicional ou aviso de revisão em andamento) e para notícias (exigem a data do fato). Na hora de montar as páginas, o código filtra com getCollection() só os artigos com status publicável e traduções publicadas.
O schema não cobre tudo. Ele não sabe se um link interno aponta para uma página que existe, nem se as versões em cada idioma apontam umas para as outras. Para isso o projeto usa um verificador que roda depois do build, descrito em como testar links internos e rotas automaticamente.
O que levar deste texto
- Coleções fazem sentido quando há muitas entradas com a mesma estrutura. Para uma página única, um arquivo em
src/pages/basta. - Separe o que não muda entre idiomas (o registro do artigo) do que muda (título, slug, texto). Isso evita duplicar metadados em cada tradução.
- Use o schema para regras editoriais, não só para tipos. Uma regra que derruba o build é seguida sempre.
- Lembre que validação de forma não substitui checagem de conteúdo, nem testes do site gerado.
Divulgação: O site do Token & Tech é construído com Astro e usa as técnicas descritas aqui.
Fontes
- Content collections, Astro Docs. Acesso em 8 de outubro de 2026
- Astro Content Loader API, Astro Docs. Acesso em 8 de outubro de 2026
- Content Collections API Reference (astro:content), Astro Docs. Acesso em 8 de outubro de 2026
- Astro 5.0, Astro. Publicado em 3 de dezembro de 2024 · Acesso em 8 de outubro de 2026
- CLI Commands, Astro Docs. Acesso em 8 de outubro de 2026
- Zod 4 API: refinements (.superRefine), Zod. Acesso em 8 de outubro de 2026