Typed, Validated Content as First-Class Data
Content Collections
Content collections turn folders of Markdown, MDX, JSON, or YAML into typed, queryable data with a Zod schema.
What you'll learn
- Understand what a collection is
- See the high-level shape
- Know when to reach for one
A content collection is a folder of content files (Markdown, MDX, YAML, JSON) plus a schema that describes the shape of each entry. Astro validates the frontmatter at build time and gives you typed entries to query from your pages.
It’s the killer feature for blogs, docs, and any content-heavy site.
What a Collection Looks Like
src/
├── content.config.ts ← schema definitions
└── blog/ ← collection folder (anywhere — we'll wire it up)
├── hello-world.md
├── second-post.md
└── advanced.mdx Each .md file has frontmatter that the schema validates:
---
title: Hello, World
pubDate: 2026-05-12
tags: [intro, astro]
draft: false
---
# Hello, World
This is the body... Querying It
In any .astro page:
---
import { getCollection } from "astro:content";
const posts = await getCollection("blog");
const published = posts.filter(p => !p.data.draft);
---
<ul>
{published.map(post => (
<li>
<a href={`/blog/${post.id}`}>{post.data.title}</a>
</li>
))}
</ul> post.data is typed — your editor knows data.title is a
string, data.pubDate is a Date, etc.
When To Use a Collection
| Situation | Use a collection? |
|---|---|
| Blog posts, docs pages, recipes, authors | Yes |
| Anything with consistent frontmatter | Yes |
| One-off “About” page | No — just src/pages/about.astro |
| Data from a CMS or external API | A loader: ... collection (see later lessons) |
The Next Few Lessons
We’ll cover, in order:
- Defining a collection in
src/content.config.ts - Loading from a glob of files
- Loading from a single JSON/YAML file
- Markdown and MDX entries
- Zod schemas for frontmatter
- Querying with
getCollectionandgetEntry - References between collections
- Rendering content to HTML