Content Collections: Structured Content with Type Safety
Astro's own answer to "structured, validated content" is Content Collections — a real, first-class feature for organizing Markdown/MDX content into typed, schema-validated groups, kept in src/content/.
Defining a Collection
The schema is a real Zod object — Zod is a popular TypeScript-first schema validation library, used here to declare exactly what fields every entry's own frontmatter must have, and of what type. Every Markdown file in src/content/blog/ gets validated against this schema.
title, or writes publishDate as plain text instead of a real date, Astro reports a real, build-time type error — not a silent runtime bug discovered later. TypeScript also infers the exact shape of every entry's own data object directly from this schema, so autocomplete and type-checking work correctly anywhere a collection entry is used in code.
Reading a Collection: getCollection()
getCollection('blog') returns every entry in the collection, each with a validated, typed data object matching the Zod schema above.
Rendering a Single Entry — Connecting Back to getStaticPaths()
Chapter 3's own getStaticPaths() can return a props object alongside params — whatever's passed here becomes directly available as Astro.props in the page, avoiding a second lookup. post.render() returns a real <Content /> component rendering that entry's own Markdown body.
blog collection, a docs collection — but there's no built-in mechanism for a genuinely self-referencing, arbitrary-depth tree the way a real database and ORM provide. Zod's own reference() helper can link one entry to another (a parent field referencing a sibling entry), but that's a schema-level cross-reference, not the same thing as the adjacency-list-plus-materialized-path hybrid every course in the Website Rebuild series independently arrived at. A future Website Rebuild with Astro course would genuinely need to choose between building that reference pattern by hand within Content Collections, or reaching for database-backed content in server output mode (Chapter 10) instead — not assume Content Collections alone already solve the same problem.
Coding Challenges
Define a docs collection with a Zod schema (title: string, order: number), add at least three content files, and use getCollection() to list all entries sorted by order.
📄 View solutionBuild a dynamic route rendering a single docs entry's own Content, passing the entry through getStaticPaths()'s props rather than looking it up a second time.
📄 View solutionDeliberately break one content file's frontmatter (e.g. write order as text instead of a number), run the dev server, and report the exact build-time type error Astro produces.
📄 View solutionChapter 5 Quick Reference
src/content/config.ts— defines every collection and its own Zod schemadefineCollection({ schema: z.object({...}) })— validated, typed frontmattergetCollection('name')— returns every validated, typed entry in a collectionpost.render()— returns a<Content />component for that entry's Markdown bodygetStaticPaths()'s ownprops— passes data straight through, avoiding a second lookup- Honest limit — no built-in self-referencing arbitrary-depth tree; a future rebuild needs
reference()or database-backed content instead - Next chapter: Styling in Astro