Astro’s Content Collections provide a powerful way to manage structured content with built-in type safety and validation. This post explores how to migrate from static blog posts to a dynamic, content-driven system.
Why Content Collections?
Traditional static blog implementations require creating individual .astro
files for each post, making content management cumbersome for non-technical users. Content Collections solve this by:
- Type Safety: Automatic TypeScript types for your content
- Content Validation: Schema validation for consistent data
- Better DX: Hot reload and better IDE support
- Scalability: Easy to add hundreds of posts without cluttering your pages directory
Setting Up Content Collections
First, create the configuration file that defines your content schema:
// src/content/config.ts
import { defineCollection, z } from "astro:content";
const blogCollection = defineCollection({
type: "content",
schema: z.object({
title: z.string(),
description: z.string(),
publishDate: z.date(),
tags: z.array(z.string()),
readingTime: z.string(),
draft: z.boolean().optional().default(false),
featured: z.boolean().optional().default(false),
}),
});
export const collections = {
blog: blogCollection,
};
Creating Dynamic Routes
Replace static blog post files with a dynamic route that handles all posts:
---
// src/pages/blog/[slug].astro
import { getCollection, type CollectionEntry } from "astro:content";
import BlogLayout from "@/layouts/BlogLayout.astro";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts
.filter((post: CollectionEntry<"blog">) => !post.data.draft)
.map((post: CollectionEntry<"blog">) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<BlogLayout {...post.data}>
<article class="prose prose-lg mx-auto">
<Content />
</article>
</BlogLayout>
Content Organization
Organize your content in the src/content/blog/
directory:
src/content/
├── config.ts
└── blog/
├── getting-started-astro.md
├── content-collections-guide.md
└── advanced-features.md
Each markdown file includes frontmatter with the required schema fields:
---
title: "Your Post Title"
description: "A compelling description"
publishDate: 2024-02-01
tags: ["astro", "tutorial"]
readingTime: "5 min read"
---
Your content here...
Benefits of This Approach
- Content Management: Non-technical users can add posts by creating markdown files
- Type Safety: Automatic validation and TypeScript support
- Performance: Only published posts are built into the site
- SEO: Proper meta tags and structured data automatically generated
- Developer Experience: Hot reload, syntax highlighting, and better tooling
Advanced Features
Content Collections support advanced features like:
- Content References: Link between different collections
- Asset Optimization: Automatic image optimization for content images
- Internationalization: Multi-language content support
- Custom Renderers: Extend markdown rendering with custom components
This system scales from a simple blog to complex content management needs while maintaining excellent developer experience and performance.