BuildBot

Islands First

Content collections

Lesson 4 of 5

What you'll learn

  • Define a content collection with a frontmatter schema
  • Understand how getCollection returns validated, typed entries
  • See validation reject malformed frontmatter at build time

A content collection is a folder of markdown (or MDX) files plus a schema that describes their frontmatter. You declare the shape once in src/content/config.ts, and Astro validates every file against it — turning loose YAML into typed, trustworthy data.

import { defineCollection, z } from "astro:content";

const blog = defineCollection({
  schema: z.object({
    title: z.string(),
    pubDate: z.date(),
    draft: z.boolean().default(false),
  }),
});

export const collections = { blog };

Now each .md file in src/content/blog must carry a title and a pubDate, or the build fails with a clear error. You read the entries with getCollection:

import { getCollection } from "astro:content";
const posts = await getCollection("blog");
// posts: { data: { title, pubDate, draft }, slug, body }[]

The schema is a gate, not a suggestion

Because validation runs at build time, a typo in frontmatter can never reach production. A missing required field or a wrong type stops the build — you fix the data, not chase a runtime crash later.

Defaults fill the gaps

Use .default(...) for optional-with-a-fallback fields like draft. Entries that omit the field still validate and come back with the default already applied, so your templates never special-case undefined.

A schema is just a set of field rules applied to each entry. The challenge models that validator and reports which entries pass and why the others fail.

Validate frontmatter against a schema

Run it. Each schema field has a type and a required flag; the validator checks every entry and reports pass/fail with the reason.

Loading editor…

Next: wrapping every page in shared chrome with layouts.

Sign in to save your progress across devices.