Rebuilding mirzadedic.ca on Cloudflare Workers
This site has been a Hugo blog for years. It worked, but the platform underneath it has changed: Cloudflare no longer just fronts your origin — it is the origin. Time to rebuild accordingly.
The goal
One constraint drove every decision: everything runs on Cloudflare, no third-party hosting anywhere. No Netlify, no Vercel, no GitHub Pages — the repo builds and deploys straight into a Worker.
The stack
| Layer | Choice | Why |
|---|---|---|
| Framework | Astro 5 | Content-first, ships zero JS by default |
| Styling | Tailwind CSS 4 | Design tokens in CSS, no config file |
| Hosting | Workers + static assets | The successor to Cloudflare Pages |
| Content | Markdown in git | Posts are files, versioned like code |
| Fonts | Self-hosted variable fonts | No requests leave the domain |
The interesting part is the hosting model. Cloudflare has been steering new projects from Pages to Workers with static assets: the same free static hosting, but with the full Workers runtime attached. Every page on this site is prerendered to plain HTML at build time and served from the edge cache — but the deployment also contains a Worker, so any route can opt into running server-side:
// src/pages/api/health.ts (trimmed) — runs at the edge on every request
export const prerender = false;
export const GET: APIRoute = ({ locals }) => {
const cf = locals.runtime?.cf;
return Response.json(
{ status: 'online', colo: cf?.colo ?? 'LOCAL' },
{ headers: { 'cache-control': 'no-store' } },
);
};
That little endpoint powers the status badge on the homepage — it reports which Cloudflare data center answered you and the round trip time. Useless? Almost. But it proves the pipeline: static where possible, compute where wanted, one deployment.
Deploying
The whole release process is one command:
npm run deploy # astro build && wrangler deploy
Connect the repo to Workers Builds and even that goes away — every push to
main builds and deploys automatically, and pull requests get preview URLs.
CI/CD without a single external service.
What’s next
The skeleton is deliberately boring so the platform can be the playground:
- D1 for a view counter or post reactions — SQLite at the edge
- R2 for images and file downloads, zero egress fees
- Workers AI for related-post embeddings, because why not
- Migrating the old Hugo posts into the new content collection
The old advice was “use a static site generator and put a CDN in front of it.” The new version is shorter: build for the CDN directly.