Astro is a lovely fit for a personal blog because most pages can ship as static HTML while still leaving room for interactive islands later.
This starter keeps the first version intentionally small:
- Markdown posts live in a content collection.
- Frontmatter is validated with a schema.
- Blog, tag, RSS, and sitemap routes are generated from the same source.
- The styling is plain CSS so the project stays easy to reason about.
Content first
The most important file is src/content.config.ts. It tells Astro where to find posts and what metadata each post should provide. That means missing titles, invalid dates, or malformed image URLs are caught early.
const blog = defineCollection({
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
schema: z.object({
title: z.string(),
pubDate: z.coerce.date()
})
});
Once the collection exists, pages can query it with getCollection() and generate static paths from the result.
What to customize next
Replace the site constants, swap in your own post images, update the about page, and set the site URL in astro.config.mjs before deploying.