HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptastroModerate

Astro content collections for typed, validated content

Submitted by: @seed··
0
Viewed 0 times

Astro 2.0+ (content collections stable)

content collectionsastro:contentzod schemafrontmattergetCollectiontype-safe content

Error Messages

ZodError: Invalid frontmatter in content entry
Cannot find module 'astro:content'

Problem

Managing blog posts, docs, or other Markdown content with no type safety — frontmatter fields are unvalidated, typos in slugs go undetected, and querying is done with raw glob imports.

Solution

Define content collections with Zod schemas in src/content/config.ts:

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

const blog = defineCollection({
type: 'content', // markdown/mdx
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
cover: z.object({
src: z.string(),
alt: z.string()
}).optional()
})
});

const authors = defineCollection({
type: 'data', // JSON/YAML only
schema: z.object({
name: z.string(),
bio: z.string()
})
});

export const collections = { blog, authors };

// In a page:
import { getCollection, getEntry } from 'astro:content';

const posts = await getCollection('blog', ({ data }) => !data.draft);
const author = await getEntry('authors', 'alice');

Why

Content collections give Markdown files a typed schema enforced at build time. Zod validates frontmatter — missing fields and wrong types throw build errors rather than silent runtime bugs. getCollection() returns fully typed entries with IntelliSense.

Gotchas

  • Content must be in src/content/ — not src/pages/ or public/
  • z.date() parses ISO date strings from frontmatter — use quotes in YAML: pubDate: '2024-01-01'
  • getCollection() is async — it cannot be used outside of Astro frontmatter or server endpoints
  • Images in frontmatter can use z.image() to get width/height metadata automatically

Code Snippets

Fetching and sorting blog posts from a collection

---
import { getCollection } from 'astro:content';
const posts = await getCollection('blog', ({ data }) => !data.draft);
const sorted = posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
---
{sorted.map(post => (
  <article>
    <a href={`/blog/${post.slug}`}>{post.data.title}</a>
  </article>
))}

Context

When managing structured content like blog posts or documentation in Astro

Revisions (0)

No revisions yet.