Adding Collections
Add custom content collections to your project.
Creating a Collection
Section titled “Creating a Collection”-
Define the schema in
src/content.config.ts:import { defineCollection, z } from 'astro:content';import { glob } from 'astro/loaders';const projects = defineCollection({loader: glob({ pattern: '**/*.md', base: './src/content/projects' }),schema: z.object({title: z.string(),client: z.string(),year: z.number(),image: z.string().optional(),url: z.string().url().optional(),featured: z.boolean().default(false),}),});export const collections = {blog,pages,authors,faqs,projects, // Add new collection}; -
Create the content folder:
src/content/projects/ -
Add content files:
---title: "E-commerce Platform"client: "Acme Corp"year: 2026image: ./screenshot.pngurl: https://acme.example.comfeatured: true---Built a custom e-commerce platform with... -
Query and display:
---import { getCollection } from 'astro:content';const projects = await getCollection('projects');const featured = projects.filter(p => p.data.featured);---{projects.map((project) => (<article><h2>{project.data.title}</h2><p>{project.data.client} • {project.data.year}</p></article>))}
Schema Types
Section titled “Schema Types”Basic Types
Section titled “Basic Types”z.string()z.number()z.boolean()z.date()z.array(z.string())Optional Fields
Section titled “Optional Fields”z.string().optional()z.number().default(0)z.enum(['draft', 'published', 'archived'])Objects
Section titled “Objects”z.object({ name: z.string(), email: z.string().email(),})Images
Section titled “Images”import { image } from 'astro:schema';
schema: z.object({ cover: image(),})JSON Collections
Section titled “JSON Collections”For structured data like authors or FAQs:
const team = defineCollection({ loader: glob({ pattern: '*.json', base: './src/content/team' }), schema: z.object({ name: z.string(), role: z.string(), bio: z.string(), avatar: z.string(), social: z.object({ twitter: z.string().optional(), linkedin: z.string().optional(), }).optional(), }),});{ "name": "Jane Doe", "role": "Lead Developer", "bio": "Building great software since 2015.", "avatar": "/team/jane.jpg", "social": { "twitter": "@janedoe", "linkedin": "janedoe" }}Dynamic Pages
Section titled “Dynamic Pages”Create pages from collection:
---import { getCollection, render } from 'astro:content';
export async function getStaticPaths() { const projects = await getCollection('projects'); return projects.map((project) => ({ params: { slug: project.id }, props: { project }, }));}
const { project } = Astro.props;const { Content } = await render(project);---
<h1>{project.data.title}</h1><Content />Filtering and Sorting
Section titled “Filtering and Sorting”---const projects = await getCollection('projects');
// Filter featuredconst featured = projects.filter(p => p.data.featured);
// Sort by year (newest first)const sorted = projects.sort((a, b) => b.data.year - a.data.year);
// Filter by clientconst acmeProjects = projects.filter(p => p.data.client === 'Acme Corp');---