Rebuilding my site with Astro 7
Why I dropped my old blog, picked Astro 7 served statically from Cloudflare Workers, and what I learned on the way.
My old site got heavier every year: one more UI library, one more tracker, until opening it meant waiting a few seconds before any text appeared. This time I wanted the opposite: less stuff, slower pace, and almost no JavaScript in the browser.
Why Astro
Astro generates static HTML and only ships JavaScript when I actually ask for it. For a site that is mostly text and photos, that is enough. Content lives in src/content and is validated by Zod at build time, so a missing alt line fails the build instead of slipping out.
The short list of what I kept:
- Markdown and MDX for posts, with footnotes and callouts.
- Two languages, Vietnamese as the default with no URL prefix.
- Self-hosted fonts, tested hard against letters such as
ằ,ẳ,ỡ,ự. - Search with Pagefind, loaded only on the
/searchpage.
Picking a language at the edge
Visitors to / are redirected based on their browser language, decided in the Worker rather than in the page. The core is one small function:
type Lang = "vi" | "en";
export function resolveLang(cookie: string | null, acceptLanguage: string | null): Lang {
const fromCookie = cookie?.match(/(?:^|;\s*)lang=(vi|en)/)?.[1];
if (fromCookie) return fromCookie as Lang;
return acceptLanguage?.toLowerCase().startsWith("en") ? "en" : "vi";
}
NOTE
The cookie always wins over Accept-Language, so anyone who picked a language once will not have it changed for them.
The static files part
Cloudflare Workers serves the dist folder as static assets. Only the root path goes through the Worker; everything else comes straight from the CDN:
{
"assets": {
"directory": "./dist",
"binding": "ASSETS",
// only "/" runs the Worker first, the rest is static
"run_worker_first": ["/"],
"not_found_handling": "404-page"
}
}
WARNING
If you set run_worker_first to true, every static file request costs a Worker invocation. List only the paths you really need.
What I almost broke
At first I planned to add an animation layer to every page. After a few days I saw it served nobody, and it dragged the performance score down.1
CAUTION
Do not upload original photos with EXIF to a public site. The attached GPS data can reveal exactly where you took them.
Wrapping up
This site is not finished, and probably never will be. But it is fast, light, and I understand every line of it.
Footnotes
-
All animation now runs only when the operating system reduced-motion setting is off. ↩
