Marek Miláček
7th week with astro

7th week with astro

Week 7: Content Collections & Data

November 24-30, 2025

Finally understand Content Collections. Spent the week moving from plain JavaScript data files to Astro’s collection system. Also wrote blog posts about my learning journey and built a projects collection.

Content Collections vs data files

Week 3 approach: One big JavaScript file with an array of objects. No validation, easy to make mistakes, all content in code.

Week 7 approach: Each piece of content is its own Markdown file with frontmatter. Schema validates everything. Much cleaner.

src/content/projects/
├── project-1.md
├── project-2.md
└── project-3.md

Each file has YAML frontmatter (metadata) and Markdown content. Way easier to write and edit than JavaScript objects.

Schemas and validation

Defined schemas using Zod in config.ts:

const projectCollection = defineCollection({
  schema: z.object({
    title: z.string(),
    date: z.coerce.date(),
    technologies: z.array(z.string()),
    featured: z.boolean().default(false),
    category: z.enum(['web', 'mobile', 'design']),
  }),
});

Now if I forget a required field or use the wrong type, I get a clear error at build time instead of silent bugs in production.

The validation is strict but helpful - caught several mistakes in my frontmatter formatting.

Querying collections

Used getCollection() to retrieve content:

const projects = await getCollection('projects');

// Filter featured
const featured = projects.filter(p => p.data.featured);

// Sort by date
const sorted = projects.sort((a, b) => 
  b.data.date - a.data.date
);

Content comes back with data (frontmatter), slug (URL), and render() (converts Markdown to HTML).

Created a projects page that displays everything, filters by category, and highlights featured items.

Blog posts about learning

Wrote 3 blog posts documenting Weeks 1-3. Each post:

  • 300+ words
  • Code examples from what I actually built
  • Honest about what was hard
  • Proper frontmatter structure

Writing about what I learned helped solidify it. Also realized how much I’ve actually progressed.

Custom projects collection

Created a projects collection with 8 fields:

  • title, description, dates
  • technologies (array)
  • category (enum)
  • status (completed/in-progress)
  • URLs for live site and GitHub
  • featured flag

Made 3 project entries - one for each major thing I built in Weeks 1-4.

Built both a listing page (all projects with filtering) and individual project pages (full Markdown content rendered).

What didn’t work

  • Schema errors were cryptic at first - took time to understand Zod’s error messages
  • Kept forgetting to use z.coerce.date() for dates, got type errors
  • First attempt at frontmatter had YAML syntax errors (indentation matters)
  • Forgot to restart dev server after changing schema - wasted 20 minutes debugging
  • Writing 3 blog posts took way longer than expected (about 4 hours total)

Comparison to Week 3

Week 3 was easier to get started (just write JavaScript), but Content Collections are way better for real projects:

  • Validation catches errors early
  • Each file is independent and easy to edit
  • Markdown for long content is much nicer than string literals
  • Type safety helps when querying
  • Better organization as content grows

Would use Collections for anything with 3+ items now.

What’s next

Week 8 is about pages and routing patterns. At least now I have content to route to.

Time invested: about 12 hours (blog posts took forever)