What’s the sitch

I wanted a small blog of my own. Not a product, not a portfolio, just a place to write. The catch I set for myself: it had to run on free resources. No monthly server bill, no database to babysit, no platform I would have to keep patching.

That constraint sounds limiting. It turned out to be the best design decision I made, because it ruled out almost every heavy option before I could talk myself into one.

Drake searches for his fortune

I spent a while looking at how people host things cheaply now. The answer kept coming back to static sites: write your pages ahead of time, turn them into plain HTML, CSS, and a little JavaScript, and let a CDN serve those files from somewhere close to the reader.

I had underestimated how far this goes today. A CDN like Cloudflare will host the files, hand out HTTPS, sit in front as a cache, and soak up bad traffic, and for a site this size it costs nothing. There is no app server in the picture at all. The thing that serves your page is the same thing that would serve an image.

Once I saw that, the shape of the project was obvious.

The plan

The plan was deliberately boring, and that was the point.

  • Content is Markdown in Git. Each post is a file. Git is the CMS. No admin panel, no login.
  • Astro builds the site. It reads the Markdown, validates the frontmatter against a schema, highlights code at build time, and emits static files. No server-side rendering, everything is prerendered.
  • Cloudflare Pages hosts the output. GitHub Actions runs the build on every push to main, checks it, and deploys the dist/ folder. The public site has no backend.
  • Minimal JavaScript. Theme switching and search only. The pages work with JavaScript turned off.
  • Search is a static index. Built at deploy time, downloaded on demand, no search API.
  • Privacy is a constraint, not a feature. No analytics platform, no user accounts, no comment system. One cookie for the light or dark theme.

The visual side was just as restrained: system fonts, a narrow reading column, three themes built from CSS variables, and a signature colour used sparingly.

The execution

I did the deciding and the checking. Claude did most of the typing.

The pattern was simple. I described what I wanted, Claude proposed a plan, I approved or corrected it, and only then did any code get written. Every phase ended with a build, the automated checks, and a set of browser tests before we moved on. When something looked wrong, I said so, and we fixed it before adding anything new.

The part that irks me the most is the fact that even for a barebones website, claude would end up doing things and adding features that would relate to scaling, large user base or just in general, bloaty. It bubbles up a common problem with failing AI projects - Once you think that AIs suggestions are beginning to make sense, check thrice for what went wrong because something has. New developers in general do not have this gut instinct, and this is what needs to develop to become better at our jobs as engineers. The instinct requires time, because deliberate, time taking actions optimise themselves over time in our brains and turn into instinct.

It is very hard to bake the instinct into claude. It is not quantifiable(yet; someday I will try and take a stab at it.) which is why vigilance is the key to avoid rework, and understanding the plan better than claude is necessary to prevent token misuse.

The result

This website. Static files on a CDN, built from Markdown, deployed by a script, served from blog.vjawsm.dev. It loads fast, it costs nothing to run, and there is very little of it to maintain or to explain.

What I learned

I have been doing deployments for years, but I only ever knew one side of them. Push to a pipeline, watch it go green, move on. I did not have real depth in what was underneath: how far cloudflare has come, how CDNs can not only serve images but pages and even permanent redirects without needing any appservers or loadbalancers, what a nameserver change breaks while it propagates. Building this from the bottom forced me to learn those parts properly.

The takeaway is to start with the bare minimum and expand from there. If you begin with abundance, plenty of compute, a database, a framework for everything, you tend to end up with something bloated, hard to maintain, and even harder to explain. Starting from almost nothing keeps you honest. You add a piece only when the solution cannot work without it. Most importantly, build the courage to run rm -rf ./ on a piece of shit codebase without remorse, loss aversion will make you a better engineer.