Building This Blog with Astro on Cloudflare Pages
Zero to live: a free, blazing-fast, low-maintenance setup for a personal blog.
The blog you’re reading was built with exactly the method in this post. The setup has only three goals: fast, cheap, easy to maintain.
Why Astro
There are plenty of blogging frameworks. I landed on Astro for simple reasons:
- Zero JavaScript by default. A post page is essentially static HTML — the browser doesn’t have to run a pile of framework code before showing you a paragraph of text.
- Markdown as a first-class citizen. Content collections manage posts and even type-check the frontmatter.
- Component-based without holding you hostage.
.astrocomponents read like HTML; bring in React or Vue only if you need them.
Up and running in three steps
# 1. Create the project
npm create astro@latest my-blog
# 2. Preview locally
cd my-blog && npm run dev
# 3. Build the static files
npm run build # output lands in dist/
Posts are written in Markdown and dropped into src/content/blog/. A content collection definition looks roughly like this:
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
schema: z.object({
title: z.string(),
pubDate: z.coerce.date(),
category: z.enum(['tech', 'ai', 'essay']),
}),
});
export const collections = { blog };
The schema validates every post’s frontmatter at build time — a typo’d field fails the build, which beats discovering it after you’ve shipped.
Deploying to Cloudflare Pages
Cloudflare Pages is effectively free for static sites, with a global CDN and very low latency. Two ways to deploy:
- Connect a Git repo (recommended). In Pages, pick the repo, set the build command to
npm run buildand the output directory todist. Everygit pushdeploys automatically. - Direct upload. Run
npm run buildlocally, then push the output withwrangler pages deploy dist.
It comes down to one line: build command
npm run build, output directorydist. Cloudflare handles the rest.
Squeezing out a bit more speed
- Set
max-age=31536000, immutableon hashed assets like/_astro/*so the browser caches them forever. - Use a system font stack to skip the wait on web fonts.
- Run images through Astro’s
<Image />component for automatic compression.
Put it together and a perfect Lighthouse score comes easily — while your monthly bill is exactly zero.