blog.naokihaba.com

Building a personal blog with Astro and Void

I want to keep writing for a long time, so I kept the setup small. Posts are Markdown files in Git, and every page is static HTML made at build time.

The stack

  • Astro 7 with Content Collections. There is no server adapter: astro build writes plain files to dist/.
  • Vite+ for lint, format, and scripts.
  • Void to deploy dist/ to Cloudflare Workers.

Vite+

I moved the project to Vite+ with vp migrate. It adds a vite.config.ts for Oxlint and Oxfmt, and a pnpm override that makes Astro use the Vite build from Vite+.

vp dev and vp build run Vite directly, so they do not start Astro. Use vp run for the Astro scripts:

vp run dev
vp run check   # vp check && astro check
vp run build

vp check does not type-check .astro files, so the check script also runs astro check.

Deploy

Void can deploy a static directory without a server build:

astro build && void deploy --dir dist --platform cloudflare

The custom domain is in void.config.ts. Void attaches it as a Workers Custom Domain on deploy, and Cloudflare makes the DNS record and the certificate:

import { defineConfig } from 'void/config';

export default defineConfig({
  cloudflare: {
    routes: [{ pattern: 'blog.naokihaba.com', custom_domain: true }],
  },
});

I also tried the new cf CLI. During the beta, it does not build Astro 6 or later, so I kept Void.

Why static

Void became open source on 2026-10-15, so it is still new. If every page is static, the blog keeps working when Void has a problem, and I can move it to a different static host. I will add dynamic features, such as view counts, when I need them.