Getting Started with Astro Content Collections

February 1, 2024 6 min read

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

  1. Content Management: Non-technical users can add posts by creating markdown files
  2. Type Safety: Automatic validation and TypeScript support
  3. Performance: Only published posts are built into the site
  4. SEO: Proper meta tags and structured data automatically generated
  5. 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.