Collections and Schemas
What Are Content Collections?
Content Collections are Astro’s built-in system for organizing and validating your Markdown, MDX, and data content. Instead of using loose Astro.glob() calls with manual type casting, collections give you:
- Schema validation — Invalid frontmatter is caught at build time
- Type safety — Full TypeScript autocompletion for frontmatter fields
- Structured querying —
getCollection()andgetEntry()APIs with typed returns - Content organization — Named directories with clear boundaries
Defining a Collection
Collections are defined in src/content.config.ts using the defineCollection function:
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
author: z.string().default('Anonymous'),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
The type field specifies whether the collection contains content files ('content' for Markdown/MDX) or data files ('data' for JSON/YAML).
Schema Field Types
Zod provides a rich set of validators for your frontmatter. Here are the most commonly used types:
| Zod Type | Use Case | Example |
|---|---|---|
z.string() | Text fields | Title, description, author |
z.number() | Numeric values | Order, priority, rating |
z.boolean() | Flags | Draft, featured, published |
z.date() or z.coerce.date() | Dates | Publication date, update date |
z.array(z.string()) | Lists | Tags, categories |
z.enum(['a', 'b']) | Fixed options | Post type, status |
z.object({...}) | Nested data | SEO metadata, author info |
Default Values and Optional Fields
Use .default() to provide fallback values and .optional() for fields that aren’t required:
schema: z.object({
title: z.string(), // Required
subtitle: z.string().optional(), // Optional (can be undefined)
author: z.string().default('Anonymous'), // Defaults if not provided
tags: z.array(z.string()).default([]), // Empty array if not provided
})
Multiple Collections
You can define as many collections as your project needs. Each gets its own directory under src/content/ and its own schema:
const blog = defineCollection({ /* ... */ });
const docs = defineCollection({ /* ... */ });
const authors = defineCollection({ type: 'data', /* ... */ });
export const collections = { blog, docs, authors };
This separation keeps your content organized and each collection’s schema focused on its specific needs.