Astro for Content-Driven Sites: A Practical Starting Point
A compact guide to Astro's server-first model, content collections, and deliberate client-side interactivity.
Start with the delivery model
Astro is a strong fit for portfolios, documentation, blogs, and other sites where most of the page can be rendered ahead of time. Components render to HTML by default, so visitors do not download a client runtime just to read static content.
That default is useful because it turns JavaScript into an explicit decision. Add a client directive only when a component truly needs browser state or interaction.
Keep content typed
Content collections provide one boundary for frontmatter and data files. Define the schema once, then let the build reject missing titles, invalid dates, or malformed project metadata.
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const notes = defineCollection({
loader: glob({ pattern: '**/*.mdx', base: './src/content/notes' }),
schema: z.object({
title: z.string(),
publishedAt: z.coerce.date(),
draft: z.boolean().default(false),
}),
});
Add interactivity by exception
Before hydrating a component, check whether semantic HTML, a form submission, a URL parameter, or modern CSS can provide the same behavior. When client code is necessary, load the smallest interactive island and leave the rest of the page as HTML.
A useful baseline
For a content-driven site, start with static output, typed collections, meaningful metadata, and a zero-JavaScript reading path. Add complexity only when a measured requirement earns it.
Further reading: Astro content collections and client directives.