Alternar tema

Astro Content Collections: do conceito à validação de Schema

Easton editorial illustration: performance inspection lens

A página inicial do blog caiu porque o campo publishDate de um post estava no formato errado. Levei meia hora procurando o arquivo até descobrir o problema: a data estava escrita como 2024/12/01, e não 2024-12-01. Isso aconteceu em um blog com apenas 30 posts. Com centenas deles, conferir todos os arquivos manualmente sempre que um campo novo for adicionado não é viável.

Content Collections resolve esse problema: o Astro passa a detectar erros no conteúdo da mesma forma que o TypeScript detecta erros no código. Depois que o Schema é configurado, o editor também oferece sugestões, sem que você precise consultar a documentação para lembrar o nome de cada campo. A seguir, você verá o que é Content Collections, como escrever o arquivo de configuração e como usar a validação de Schema.

O que é Content Collections e por que usar esse recurso?

Talvez você esteja pensando: Content Collections não é apenas uma forma de organizar pastas com arquivos Markdown? Eu não poderia simplesmente criar uma pasta blog/ dentro de src/pages/ e implementar o blog do mesmo jeito?

Sim, em termos de funcionalidade. O problema é que essa abordagem não oferece segurança de tipos.

Na abordagem tradicional, o frontmatter do Markdown seria assim:


---

title: "Título do meu blog"
date: "2024-12-01"
tags: ["Astro", "Tutorial"]

---

Conteúdo do post...

Parece correto, certo? Agora considere estes cenários:

  • Em um post, você escreve tag em vez de tags, esquecendo o s
  • Você usa o formato de data 12/01/2024 em vez de 2024-12-01
  • Você adiciona um campo author, mas esquece de incluí-lo em alguns posts antigos

O Astro não avisa sobre esses erros com antecedência. Você só descobre o problema em tempo de execução, quando a renderização da página falha.

Content Collections existe justamente para resolver isso. Em essência, é um sistema de gerenciamento de conteúdo com segurança de tipos. Pense nele como uma forma de adicionar verificação de tipos do TypeScript aos arquivos Markdown.

Na prática, Content Collections oferece estes recursos:

  1. Validação de Schema: define os tipos e a estrutura dos campos do frontmatter e gera um erro imediato quando algo não corresponde à definição
  2. Geração automática de tipos: cria tipos TypeScript a partir do Schema, com sugestões inteligentes no editor
  3. API de consulta unificada: permite consultar o conteúdo com métodos como getCollection(), que retornam dados tipados
  4. Otimização de desempenho: a Content Layer API introduzida no Astro 5.0 acelera as consultas

Em outras palavras, a abordagem tradicional é livre, mas insegura; Content Collections impõe regras e oferece confiabilidade. O tempo investido na configuração do Schema evita 99% dos erros mais básicos.

Sinceramente, hoje uso Content Collections em todos os meus projetos Astro. Você configura uma vez e aproveita os benefícios durante todo o projeto.

Configuração prática de Content Collections

Terminada a teoria, vamos configurar o recurso. O processo tem três etapas: criar os diretórios, escrever a configuração e criar o conteúdo.

Primeira etapa: criar os diretórios

Content Collections exige que o conteúdo fique dentro de src/content/. Esse é um diretório reservado pelo Astro desde a versão 2.0 e destinado às coleções de conteúdo.

A estrutura fica mais ou menos assim:

src/
├── content/
│   ├── blog/          # Coleção do blog
│   │   ├── post-1.md
│   │   └── post-2.md
│   └── docs/          # Coleção da documentação
│       ├── guide-1.md
│       └── guide-2.md
├── content.config.ts   # Arquivo de configuração (observe a localização)
└── pages/
    └── ...

Atenção: o arquivo de configuração é src/content.config.ts (ou .js, .mjs) e não fica dentro do diretório content/. Quando comecei, coloquei o arquivo no lugar errado e levei um bom tempo para encontrar a causa do problema.

Cada subdiretório representa uma coleção. Por exemplo, src/content/blog/ é a coleção blog, enquanto src/content/docs/ é a coleção docs.

Segunda etapa: escrever o arquivo de configuração

Crie src/content.config.ts, o arquivo central de Content Collections:

// src/content.config.ts
import { defineCollection, z } from 'astro:content';

// Define a coleção blog
const blogCollection = defineCollection({
  type: 'content',  // Tipo content para arquivos Markdown/MDX
  schema: z.object({
    title: z.string(),                    // Título (obrigatório)
    description: z.string(),              // Descrição (obrigatória)
    pubDate: z.coerce.date(),             // Data de publicação (convertida automaticamente em Date)
    tags: z.array(z.string()).optional(), // Array de tags (opcional)
    draft: z.boolean().default(false),    // Estado de rascunho (false por padrão)
  }),
});

// Exporta o objeto collections
export const collections = {
  'blog': blogCollection,  // A chave corresponde ao nome do diretório
};

O código pode parecer um pouco complexo, então vamos dividir cada parte:

  1. defineCollection(): define a configuração de uma coleção
  2. type: 'content': informa que a coleção contém arquivos Markdown/MDX
  3. schema: usa Zod, uma biblioteca de validação, para definir a estrutura do frontmatter
  4. Objeto collections: exporta as configurações; cada chave deve ser igual ao nome do diretório correspondente

O ponto principal está em schema. Cada campo recebe um tipo com z.xxx():

  • z.string(): string
  • z.coerce.date(): converte automaticamente uma string em um objeto Date
  • z.array(z.string()): array de strings
  • .optional(): torna o campo opcional
  • .default(false): define um valor padrão

Terceira etapa: criar um arquivo de conteúdo

Depois da configuração, você pode criar um arquivo Markdown em src/content/blog/:


---

title: "Introdução ao Astro Content Collections"
description: "Aprenda a configurar e usar Content Collections"
pubDate: "2024-12-01"
tags: ["Astro", "Tutorial"]

---

Este é o conteúdo do post...

Se o frontmatter estiver de acordo com o Schema, o Astro poderá analisá-lo normalmente. Quando um campo é incompatível, como um pubDate em formato incorreto, o Astro exibe um erro já durante a compilação.

Consultar dados em uma página

Depois de configurar a coleção, você pode consultar o conteúdo em qualquer arquivo Astro:


---

// src/pages/blog/index.astro
import { getCollection } from 'astro:content';

// Busca todos os posts do blog
const allPosts = await getCollection('blog');

// Remove os rascunhos (draft: true)
const publishedPosts = allPosts.filter(post => !post.data.draft);

---

<ul>
  {publishedPosts.map(post => (
    <li>
      <a href={`/blog/${post.slug}`}>
        {post.data.title}
      </a>
      <p>{post.data.description}</p>
    </li>
  ))}
</ul>

Observe que post.data contém os dados do frontmatter e tem tipagem completa do TypeScript. Quando você digita post.data. no VS Code, o editor sugere automaticamente campos como title, description e pubDate.

Essa é a principal vantagem de Content Collections: segurança de tipos e sugestões inteligentes no editor, que melhoram bastante a experiência de desenvolvimento.

Validação de Schema em detalhes

Na seção anterior, usamos tipos básicos como z.string() e z.coerce.date(). A validação de Schema, porém, oferece muito mais. Agora vamos explorar outros recursos do Zod.

Referência rápida de tipos básicos

Comece pelos tipos mais usados:

import { z } from 'astro:content';

z.string()           // String
z.number()           // Número
z.boolean()          // Booleano
z.date()             // Objeto Date
z.coerce.date()      // Converte automaticamente uma string em Date
z.array(z.string())  // Array de strings
z.enum(['draft', 'published'])  // Enumeração (aceita apenas os valores definidos)

z.coerce.date() é especialmente útil. No frontmatter de um arquivo Markdown, as datas são escritas como strings, por exemplo, "2024-12-01". Se você usar z.date(), ocorrerá um erro porque esse tipo exige um objeto Date. Já z.coerce.date() faz a conversão automaticamente e evita esse trabalho.

Campos opcionais e valores padrão

Nem todos os campos precisam ser obrigatórios. Alguns posts podem não precisar de tags; nesse caso, use .optional():

schema: z.object({
  title: z.string(),                    // Obrigatório
  tags: z.array(z.string()).optional(), // Opcional
  draft: z.boolean().default(false),    // Com valor padrão
})

.default() é útil porque o Astro preenche automaticamente o valor padrão quando o campo não existe no frontmatter.

Uso avançado: validação de imagens

O Astro também oferece o tipo image(), específico para validar caminhos de imagens:

import { defineCollection, z } from 'astro:content';

const blogCollection = defineCollection({
  schema: ({ image }) => z.object({  // Aqui usamos a forma de função
    title: z.string(),
    cover: image(),  // Validação do caminho da imagem
  }),
});

image() verifica se o caminho aponta para um arquivo de imagem válido e aceita caminhos relativos. Esse recurso é particularmente útil para exibir capas na página inicial de um blog.

Referenciar outras coleções com z.reference()

Às vezes, o conteúdo tem relações internas. Um post pode pertencer a uma categoria que, por sua vez, também é uma coleção. Nesse caso, use z.reference():

// Define a coleção de categorias
const categoryCollection = defineCollection({
  schema: z.object({
    name: z.string(),
    slug: z.string(),
  }),
});

// A coleção blog referencia uma categoria
const blogCollection = defineCollection({
  schema: z.object({
    title: z.string(),
    category: z.reference('category'),  // Referencia a coleção category
  }),
});

export const collections = {
  'category': categoryCollection,
  'blog': blogCollection,
};

No frontmatter do post, o campo category precisa conter apenas o nome do arquivo da categoria, sem a extensão:


---

title: "Meu blog"
category: "tech"  # Referencia src/content/category/tech.md

---

O Astro verifica automaticamente se a categoria existe, mantendo também a segurança de tipos.

Objetos complexos aninhados

Se o frontmatter tiver uma estrutura mais complexa, você pode aninhar objetos:

schema: z.object({
  title: z.string(),
  author: z.object({
    name: z.string(),
    email: z.string().email(),  // Valida o formato do e-mail
    avatar: z.string().url(),   // Valida o formato da URL
  }),
  seo: z.object({
    keywords: z.array(z.string()),
    description: z.string().max(160),  // Limita o tamanho máximo
  }).optional(),
})

O frontmatter correspondente seria:


---

title: "Título do post"
author:
  name: "Zhang San"
  email: "[email protected]"
  avatar: "https://example.com/avatar.jpg"
seo:
  keywords: ["Astro", "Tutorial"]
  description: "Este é um tutorial sobre Astro"

---

A segurança de tipos na prática: inferência automática do TypeScript

Depois que o Schema é configurado, o Astro gera automaticamente os tipos TypeScript. Ao consultar os dados no código, o editor oferece todas as sugestões:

import { getCollection } from 'astro:content';

const posts = await getCollection('blog');

posts.forEach(post => {
  // O editor sugere todos os campos de post.data
  console.log(post.data.title);       // ✅ Tipo: string
  console.log(post.data.pubDate);     // ✅ Tipo: Date
  console.log(post.data.tags);        // ✅ Tipo: string[] | undefined
  console.log(post.data.notExist);    // ❌ Erro de compilação: o campo não existe
});

Esse é um dos melhores aspectos de Content Collections. Você não precisa escrever definições de tipos manualmente; o Astro as gera a partir do Schema, com precisão.

getEntry() versus getCollection()

Para concluir, vale distinguir as duas APIs de consulta:

  • getCollection('blog'): busca todo o conteúdo da coleção
  • getEntry('blog', 'my-post'): busca um único item pelo slug informado

A consulta individual é mais eficiente e adequada às páginas de detalhes:


---

// src/pages/blog/[slug].astro
import { getEntry } from 'astro:content';

const { slug } = Astro.params;
const post = await getEntry('blog', slug);

if (!post) {
  return Astro.redirect('/404');
}

const { Content } = await post.render();

---

<article>
  <h1>{post.data.title}</h1>
  <Content />
</article>

Sinceramente, a sintaxe do Zod também me confundiu no começo. Depois de usá-la algumas vezes, ela fica familiar, e as mensagens de erro do Zod são claras o suficiente para facilitar a investigação.

Erros comuns e soluções

Ao configurar Content Collections, é normal encontrar alguns erros. Estes são os problemas que apareceram com mais frequência nos meus projetos e como resolvê-los.

Erro 1: MarkdownContentSchemaValidationError

Esse é o erro mais comum. Ele indica que o frontmatter não corresponde à definição do Schema. A mensagem pode ser parecida com esta:

blog → my-post.md frontmatter does not match collection schema.
- "title" is required
- "pubDate" must be a valid date

Como interpretar esse erro?

O Astro informa claramente qual arquivo (my-post.md) e quais campos (title, pubDate) estão com problemas.

Causas comuns e soluções:

  1. Campo ausente: o Schema define um campo obrigatório, mas ele não está no frontmatter

    • Solução: adicione o campo ausente ou marque-o com .optional() no Schema
  2. Nome de campo digitado incorretamente: por exemplo, publishDate em vez de pubDate

    • Solução: padronize os nomes e use o preenchimento automático do editor
  3. Tipo incompatível: por exemplo, o Schema exige z.number(), mas o frontmatter contém uma string

    • Solução: confira o formato do valor

Erro 2: InvalidContentEntryFrontmatterError

Esse erro indica que o formato do próprio frontmatter está incorreto. Em outras palavras, há um erro de sintaxe YAML que impede até mesmo a análise do arquivo.

Uma causa comum seria:


---

title: "Meu título
description: "As aspas do título não foram fechadas"

---

Para corrigir, verifique a sintaxe YAML, em especial aspas, dois-pontos e recuo. Uma extensão de editor com validação de YAML também ajuda.

Erro 3: formato de data

Já caí nessa armadilha várias vezes. Se você usar z.date() em vez de z.coerce.date(), o Astro exigirá que a data do frontmatter seja um objeto Date, e não uma string. Mas, no YAML, a data é escrita como texto.

Solução: use z.coerce.date() no Schema para converter a string automaticamente em um objeto Date:

// ❌ Incorreto: exige um objeto Date, mas o frontmatter contém uma string
pubDate: z.date()

// ✅ Correto: converte automaticamente a string em Date
pubDate: z.coerce.date()

Tratar dados legados com .passthrough()

Se o blog já tiver muitos posts antigos, talvez os campos de frontmatter não estejam padronizados. Nesse caso, .passthrough() pode flexibilizar temporariamente a validação:

schema: z.object({
  title: z.string(),
  // ... Outros campos
}).passthrough()  // Permite campos adicionais que não foram definidos

Essa é apenas uma solução provisória. No longo prazo, é melhor padronizar a estrutura do frontmatter.

Como organizar várias coleções

Se o site reúne blog, documentação, estudos de caso e outros tipos de conteúdo, você pode criar várias coleções:

src/content/
├── blog/
├── docs/
└── case-studies/

Depois, defina cada coleção separadamente em content.config.ts:

const blogCollection = defineCollection({ /* ... */ });
const docsCollection = defineCollection({ /* ... */ });
const caseStudiesCollection = defineCollection({ /* ... */ });

export const collections = {
  'blog': blogCollection,
  'docs': docsCollection,
  'case-studies': caseStudiesCollection,
};

Cada coleção pode ter seu próprio Schema sem interferir nas demais.

Boas práticas de design de Schema

Estas são as práticas que funcionaram melhor para mim:

  1. Mantenha poucos campos obrigatórios: exija apenas o necessário e use .optional() ou .default() nos demais
  2. Use z.coerce.date() para datas: isso evita conversões manuais
  3. Use camelCase nos nomes dos campos: pubDate combina melhor com as convenções do JavaScript do que pub_date
  4. Divida objetos complexos: se o frontmatter ficar complicado, considere criar várias coleções relacionadas por z.reference()
  5. Escreva comentários claros: explique no Schema a finalidade de cada campo para a equipe

Checklist para investigar problemas

Quando encontrar um erro, confira estes itens na ordem:

  • O diretório src/content/ existe?
  • O arquivo src/content.config.ts está no local correto, fora de content/?
  • No objeto collections exportado pelo Schema, as chaves correspondem aos nomes dos diretórios?
  • A sintaxe YAML do frontmatter está correta, incluindo aspas, dois-pontos e recuo?
  • Todos os campos obrigatórios estão preenchidos?
  • Os tipos dos campos correspondem à definição do Schema?

Esses problemas podem parecer complexos, mas as mensagens de erro do Astro são claras. Se você ler os detalhes com atenção, normalmente encontra a causa rapidamente.

Conclusão

Depois de tudo isso, podemos voltar às três dúvidas iniciais.

O que é Content Collections? É uma forma de adicionar verificação de tipos do TypeScript ao conteúdo Markdown. Assim, o Astro encontra erros durante a compilação, antes que eles derrubem a página em tempo de execução.

Como escrever o arquivo de configuração? Lembre-se das três etapas: criar o diretório src/content/, criar src/content.config.ts e definir o Schema com defineCollection() e Zod. Cada chave deve ser igual ao nome do diretório correspondente.

Como usar a validação de Schema? Domine os tipos básicos, como z.string(), z.coerce.date() e z.array(), use .optional() e .default() quando necessário e leia as mensagens do Astro ao investigar erros.

Content Collections é um dos recursos mais úteis do Astro. A configuração exige algum tempo no início, mas depois poupa inúmeras horas de investigação. As sugestões inteligentes do editor também tornam a experiência de programação muito melhor.

Próximos passos

Se você quiser testar Content Collections agora, siga estas sugestões:

  1. Use desde o início em projetos novos: configure Content Collections ao criar o projeto Astro e estabeleça as regras logo no começo
  2. Migre projetos antigos aos poucos: use .passthrough() para manter o conteúdo atual funcionando e padronize gradualmente a estrutura do frontmatter
  3. Consulte a documentação oficial: quando surgir uma dúvida, veja a documentação oficial do Astro, que traz a referência completa da API

Content Collections não é difícil, mas exige prática. Ler tutoriais ajuda; escrever o arquivo de configuração por conta própria ajuda muito mais. Faça um teste e veja como a segurança de tipos muda o fluxo de trabalho.

Configuração completa do Astro Content Collections

Etapas para configurar Content Collections do zero até a validação de Schema e criar um sistema de conteúdo com segurança de tipos

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Criar a estrutura de diretórios

    Crie o diretório src/content/ na raiz do projeto:
    • Diretório reservado pelo Astro desde a versão 2.0
    • Crie subdiretórios dentro de content/ para representar coleções, como blog/ e docs/
    • Cada subdiretório corresponde a uma coleção

    Atenção: o arquivo de configuração src/content.config.ts fica em src/, e não dentro de content/.
  2. 2

    Step 2: Criar o arquivo de configuração

    Crie o arquivo src/content.config.ts:

    1. Importe as dependências:
    import { defineCollection, z } from 'astro:content'

    2. Defina a configuração da coleção:
    const blogCollection = defineCollection({
    type: 'content',
    schema: z.object({
    title: z.string(),
    description: z.string(),
    pubDate: z.coerce.date(),
    tags: z.array(z.string()).optional(),
    draft: z.boolean().default(false)
    })
    })

    3. Exporte o objeto collections:
    export const collections = { 'blog': blogCollection }
    Atenção: a chave deve ser igual ao nome do diretório
  3. 3

    Step 3: Criar um arquivo de conteúdo

    Crie um arquivo Markdown em src/content/blog/:

    O frontmatter deve seguir o Schema definido:
    • title (string obrigatória)
    • description (string obrigatória)
    • pubDate (data no formato '2024-12-01'; z.coerce.date() faz a conversão automática)
    • tags (array opcional de strings)
    • draft (booleano opcional, false por padrão)

    Se algum campo não corresponder ao Schema, o Astro exibirá um erro durante a compilação.
  4. 4

    Step 4: Consultar dados em uma página

    Importe getCollection em um arquivo Astro:
    import { getCollection } from 'astro:content'

    Busque todos os posts do blog:
    const allPosts = await getCollection('blog')

    Filtre os rascunhos:
    const publishedPosts = allPosts.filter(post => !post.data.draft)

    Use os dados:
    • post.data conta com tipagem completa do TypeScript
    • O editor sugere automaticamente campos como title, description e pubDate
    • Para consultar um único post, getEntry('blog', slug) é mais eficiente
  5. 5

    Step 5: Configurar Schemas avançados

    Validação de imagens:
    schema: ({ image }) => z.object({
    cover: image()
    })

    Referência a outra coleção:
    z.reference('category')

    Objetos complexos aninhados:
    z.object({
    author: z.object({
    name: z.string(),
    email: z.string().email(),
    avatar: z.string().url()
    })
    })

    Tratamento de dados legados:
    .passthrough() permite campos adicionais que não foram definidos

    Cenários com várias coleções:
    defina blog, docs, case-studies e outras coleções separadamente no objeto collections
  6. 6

    Step 6: Investigar erros comuns

    MarkdownContentSchemaValidationError: verifique campos ausentes (adicione o campo ou use .optional()), nomes digitados incorretamente (padronize os nomes) e tipos incompatíveis (confira o formato do valor). InvalidContentEntryFrontmatterError: verifique a sintaxe YAML, incluindo aspas, dois-pontos e recuo. Problemas com datas: use z.coerce.date(), não z.date(). Checklist: o diretório content/ existe, content.config.ts está no local correto, as chaves de collections correspondem aos nomes dos diretórios, o YAML está válido, todos os campos obrigatórios foram preenchidos e os tipos correspondem ao Schema.

FAQ

O que é Content Collections e por que usar esse recurso?
Content Collections é um sistema de gerenciamento de conteúdo com segurança de tipos. Na prática, ele adiciona verificação de tipos do TypeScript aos arquivos Markdown.

A abordagem tradicional, criando uma pasta blog/ diretamente em src/pages/, não oferece segurança de tipos e facilita problemas como:
• Erros de digitação em campos, como tags escrito como tag
• Formatos de data incorretos, como 12/01/2024 em vez de 2024-12-01
• Campos novos que não foram adicionados aos posts antigos
• O Astro não avisa antes; o problema só aparece quando a página falha em tempo de execução

Content Collections oferece:
1) Validação de Schema, com tipos e estrutura definidos para o frontmatter e erro imediato em caso de incompatibilidade
2) Geração automática de tipos TypeScript com base no Schema e sugestões no editor
3) Uma API de consulta unificada, com métodos como getCollection() que retornam dados tipados
4) Otimização de desempenho com a Content Layer API do Astro 5.0

A abordagem tradicional é livre, mas insegura; Content Collections impõe regras e oferece confiabilidade. Uma única configuração beneficia o projeto inteiro.
Como configurar Content Collections do início ao fim?
A configuração tem três etapas:

1) Criar os diretórios:
• Crie src/content/ na raiz do projeto, um diretório reservado pelo Astro desde a versão 2.0
• Dentro de content/, crie subdiretórios para as coleções, como blog/ e docs/; cada subdiretório representa uma coleção

2) Escrever o arquivo de configuração:
• Crie src/content.config.ts, fora do diretório content/
• Importe defineCollection e z
• Defina a coleção: type: 'content' representa arquivos Markdown/MDX, e schema usa Zod para definir a estrutura do frontmatter
• Exporte o objeto collections; a chave deve corresponder ao diretório, como 'blog': blogCollection

3) Criar o conteúdo:
• Crie um arquivo Markdown em src/content/blog/
• O frontmatter deve seguir o Schema; caso contrário, o Astro exibirá um erro durante a compilação
Como usar a validação de Schema e quais são os tipos mais comuns?
Use Zod para definir os tipos:
• z.string() para strings
• z.number() para números
• z.boolean() para booleanos
• z.date() para objetos Date
• z.coerce.date() para converter strings em Date automaticamente, algo muito útil porque datas no YAML são escritas como texto
• z.array(z.string()) para arrays de strings
• z.enum(['draft', 'published']) para enumerações

Campos opcionais e valores padrão:
• .optional() torna o campo opcional
• .default(false) define um valor padrão

Recursos avançados:
• image() valida caminhos de imagem: schema: ({ image }) => z.object({ cover: image() })
• z.reference('category') referencia outra coleção
• Objetos complexos podem ser aninhados: z.object({ author: z.object({ name: z.string(), email: z.string().email() }) })

Depois que o Schema é configurado, o Astro gera automaticamente os tipos TypeScript. O editor passa a oferecer sugestões completas, e todos os campos de post.data ficam protegidos por tipos.
Como consultar dados de Content Collections e qual é a diferença entre getCollection e getEntry?
APIs de consulta:
• getCollection('blog') busca todo o conteúdo da coleção e retorna um array
• getEntry('blog', 'my-post') busca um único item pelo slug e retorna um objeto, sendo mais eficiente para páginas de detalhes

Importe em um arquivo Astro:
import { getCollection, getEntry } from 'astro:content'

Uso dos dados:
• post.data contém os dados do frontmatter com tipagem completa do TypeScript
• O editor sugere automaticamente title, description, pubDate e outros campos

Filtragem de rascunhos:
const publishedPosts = allPosts.filter(post => !post.data.draft)

Exemplo de consulta individual:
const post = await getEntry('blog', slug)
if (!post) return Astro.redirect('/404')
const { Content } = await post.render()
Quais são os erros mais comuns em Content Collections e como corrigi-los?
Erros comuns:

1) MarkdownContentSchemaValidationError, quando o frontmatter não corresponde ao Schema:
• Verifique campos ausentes e adicione-os ou use .optional()
• Corrija nomes digitados incorretamente e padronize-os com o preenchimento automático do editor
• Confira o formato dos valores quando houver incompatibilidade de tipos

2) InvalidContentEntryFrontmatterError, quando há erro de sintaxe YAML:
• Verifique aspas, dois-pontos e recuo
• Use uma extensão de editor que valide a sintaxe YAML

3) Problemas com datas:
• Use z.coerce.date() em vez de z.date(); datas no YAML são escritas como strings, e z.coerce.date() faz a conversão automática

4) Tratamento de dados legados:
• Use .passthrough() para permitir temporariamente campos adicionais não definidos, mas apenas como solução provisória
• No longo prazo, padronize a estrutura do frontmatter

Checklist:
• O diretório content/ existe
• content.config.ts está no local correto, fora de content/
• As chaves de collections correspondem aos nomes dos diretórios
• A sintaxe YAML está correta
• Todos os campos obrigatórios estão preenchidos
• Os tipos dos campos correspondem ao Schema
Como organizar várias coleções e quais são as boas práticas de Schema?
Cenários com várias coleções:
• Se o site reúne blog, documentação e estudos de caso, crie coleções diferentes em src/content/blog/, docs/ e case-studies/
• Em content.config.ts, defina cada uma separadamente:
const blogCollection = defineCollection({...})
const docsCollection = defineCollection({...})
• Exporte o objeto collections:
'blog': blogCollection,
'docs': docsCollection,
'case-studies': caseStudiesCollection
• Cada coleção pode ter seu próprio Schema sem interferir nas demais

Boas práticas de design de Schema:
1) Mantenha poucos campos obrigatórios: exija apenas o necessário e use .optional() ou .default() nos demais
2) Use z.coerce.date() para datas e evite conversões manuais
3) Use camelCase nos nomes dos campos; pubDate combina melhor com as convenções do JavaScript do que pub_date
4) Divida objetos complexos; se o frontmatter ficar complicado, considere criar várias coleções ligadas por z.reference()
5) Escreva comentários claros no Schema para explicar à equipe a finalidade de cada campo

14 min de leitura · Publicado em: 24 nov 2025 · Atualizado em: 4 set 2026

Comentários

Entre com GitHub para comentar

Easton BlogEaston Blog