Summary
Notes on building a fast, SEO-friendly static blog with Astro and Starlight, including content collections and Pagefind search.

This site is a fully static blog built with Astro and Starlight. It ships no JavaScript on first paint beyond a small theme toggle, yet it still has full-text search, RSS, sitemap, and structured data.

Content as data

Every article is a Markdown file with a typed frontmatter schema. Astro validates dates, slugs, and required fields at build time:

---
title: Building a fast static blog with Astro
description: How this site is built.
contentType: article
pubDate: 2026-07-05
slug: building-a-static-blog-with-astro
series: building
tags: [astro, starlight, typescript]
---

The schema is enforced with Zod in src/content.config.ts, so a typo in frontmatter fails the build instead of shipping a broken page.

Full-text search without a backend

Starlight ships full-text search powered by Pagefind. No database, no runtime, no API keys — the index is built once at build time and searched entirely in the browser:

// Search is enabled simply by rendering Starlight's <Search />
// component in the site header.
import Search from '@astrojs/starlight/components/Search.astro';

Because the whole site is static, it can be hosted anywhere — including a plain object store like Amazon S3 behind CloudFront.

Themes

Astro ships the generated HTML with zero client JS; the dark theme is applied by a tiny inline script that runs before first paint, so there is no flash of the wrong theme.

const preference = localStorage.getItem('theme') ?? 'auto';
const isDark = preference === 'dark' ||
(preference === 'auto' && !matchMedia('(prefers-color-scheme: dark)').matches);
document.documentElement.dataset.theme = isDark ? 'dark' : 'light';

Static by default, searchable when needed, fast everywhere.