Blog
· 2 min read AstroTypeScriptWeb

Getting Started with Astro Content Collections

Content collections are one of Astro’s most powerful features. They give you a type-safe way to work with local content — markdown files living in src/content/blog/.

Defining a schema

In src/content/config.ts, you define a collection with a Zod schema:

import { defineCollection, z } from 'astro:content'

const blog = defineCollection({
  schema: z.object({
    title: z.string(),
    date: z.date(),
    description: z.string(),
    tags: z.array(z.string()).optional(),
  }),
})

export const collections = { blog }

Astro validates every file against this schema at build time. If a post is missing a required field, the build fails — no more production errors from frontmatter typos.

Querying content

Use getCollection to fetch all entries, or getEntry for a single one:

import { getCollection } from 'astro:content'

const posts = await getCollection('blog')
// posts are sorted by date, newest first
const sorted = posts.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf())

Rendering a post

In a dynamic route like src/pages/blog/[...slug].astro:

---
import { getCollection } from 'astro:content'
const { slug } = Astro.params
const entry = await getEntry('blog', slug as string)
const { Content } = await entry.render()
---

<Content />

The render() method returns the compiled component — drop it in with <Content /> and you’re done.

Why it matters

Before content collections, you’d manage markdown files manually — reading the filesystem, parsing frontmatter, hoping nothing was malformed. Now Astro owns that contract. The schema is the contract.

If you’re starting a blog or docs site with Astro, content collections are the way to go.

READY