How this site is built, and why I made the choices I did

In my last proper post about this site I said I'd write up a full description once it was rebuilt. That was a while ago now. Classic me. Anyway, here it is.

If you've read any of my older posts you'll know this blog has been rebuilt more times than I'd care to admit, usually as an excuse to learn whatever was new and shiny at the time. This rebuild was different. For once I didn't reach for the trendiest thing on the block, I reached for the most boring option that did the job. I'll let you decide whether that's wisdom or just getting old.

What it used to be

The old version of this site was a React app from around 2017. Create React App, Redux for state management, react-router for the pages, and the actual blog content lived in a Firebase real-time database that the browser fetched on every single page load. There was even a separate tool bolted on top to pre-render the pages so Google could read them.

It worked. But read that list back. For a personal site with a handful of blog posts and a couple of projects, that is a lot of moving parts. A whole state management library. A live database. A real-time socket connection. All to show some text I wrote in 2017. It was massively over-engineered, and most of it was there because at the time those were the things I wanted to play with, not because the site actually needed them.

What it is now

The new site is built with Next.js and exported as a completely static site. No server, no database, no live anything. Just HTML, CSS and a bit of JavaScript sitting in an S3 bucket, served out through CloudFront. Same hosting as before, much simpler everything else.

The biggest change is how content works. Instead of pulling blog posts out of Firebase in the browser, every post and project is now just a Markdown file sitting in the same git repo as the code. When the site builds, those files get turned into HTML and baked straight into the pages. This very article is a Markdown file.

Why go that way? A few reasons.

First, it's better for both speed and search. The old site rendered nothing until the browser had gone off and fetched from Firebase, so for a split second Google and the visitor both saw an empty page with a spinner. Now every page is full HTML the moment it loads. Next.js does that pre-rendering out of the box, so I got to delete that bolted-on tool entirely.

Second, my content now lives in git like everything else. No separate database to log into, no admin panel, no risk of some service quietly shutting down and taking my writing with it. I write a post in my editor, right next to the code, commit it, done. It's version controlled, which means I can see every change I've ever made to a post. Try doing that with a database row.

Third, there's just far less to break. I ripped out Redux, react-router, the Firebase SDK, a syntax-highlighting library, Bootstrap, a date library, the lot. Every dependency you carry is something that can break, fall out of date, or need patching at the worst possible moment. A static site needs almost none of it.

Boring on purpose

There's a trade-off, of course, there always is. Publishing a post now means rebuilding and redeploying the site rather than just updating a database. For someone who posts about once a year, that's a complete non-issue. If I was posting daily it might start to annoy me. The lesson there is to pick the trade-off that fits how you actually work, not how you wish you worked.

And honestly, boring is the point. A static site is about as robust as it gets. There's no server to fall over, no database to corrupt, no traffic spike that suddenly costs me money. It either works, or the entire internet is down and I've got bigger problems. For a personal site that reliability and cost profile is exactly what you want.

The one bit that fought back

In the old write-up I mentioned that securing the connection between the frontend and the API was the unforeseen challenge. This time the gremlin was hosting. Because the site is now a set of real, separate pages instead of one big app, I needed CloudFront to serve /resume/ as the actual resume page and not the homepage. The old setup quietly redirected everything to the homepage, which is grand for a single-page app and very much not grand now. A tiny URL-rewrite function sorted it, but it's a good reminder that the last 5% of "just deploy it" is always where the time quietly disappears.

Full disclosure

One last thing, since my previous post was all about AI in software architecture. Full disclosure: I rebuilt this site with a lot of AI help. It did the grunt work, the migration, the boilerplate, wiring up the Markdown pipeline, while I made the calls on what the architecture should actually be and reviewed everything it produced before it went anywhere near live.

Which, if you read that last post, is exactly the model I argued for. Felt only right to practice what I preach.