Content Collections
Website Foundation uses Astro's Content Layer API with four collections defined in src/content.config.ts. Each collection uses the glob loader to read markdown files from src/content/<collection>/.
Collections Overview
| Collection | Directory | Required Fields |
|---|---|---|
| blog | src/content/blog/ |
title, description, author, publishedAt |
| gallery | src/content/gallery/ |
title, description, image, category, publishedAt |
| testimonials | src/content/testimonials/ |
author, role, publishedAt |
| promoted | src/content/promoted/ |
title, description, image, link, linkText, order, publishedAt |
File Naming
Use kebab-case .md files: my-first-post.md, sunset-beach.md. The filename (without extension) becomes the content ID used for slugs and routing.
Frontmatter Format
Every markdown file starts with YAML frontmatter between --- fences:
---
title: "My Blog Post"
description: "A short summary"
author: "Jane Doe"
publishedAt: 2026-02-21
tags: ["astro", "tutorial"]
draft: false
---
Body content goes here in markdown.
Dates use z.coerce.date() — accepts YYYY-MM-DD strings or ISO 8601 format.
Querying Content
Use getCollection() from astro:content to fetch all items, then filter and sort in JavaScript:
import { getCollection } from "astro:content";
const posts = (await getCollection("blog"))
.filter((p) => !p.data.draft)
.sort((a, b) => b.data.publishedAt.getTime() - a.data.publishedAt.getTime());
See content queries reference for all query patterns and schemas reference for detailed field documentation.
Rendering Content
Use render() to get a <Content /> component for the markdown body:
import { render } from "astro:content";
const { Content } = await render(post);
Then use <Content /> in your template inside a prose container.