Over-engineering a blog
I’ve been threatening to write my own blogging framework for ages, and have started multiple attempts at it. This blog is not the result of any of those attempts. This is just an Astro site kindly configured and set up for me by Claude Code. Incredibly simple and easy to do with about three prompts.
It’s got RSS, has an llms.txt and every page is published as html and markdown to make it easy for LLMs to read. I even added standard.site support, though not yet configured as it looks like I’ll have to implement atproto OAuth to enable my deploy pipeline to update my Eurosky.social hosted PDS.
My quandary came in when it came time to host it somewhere. I could do the easy thing and use any of the hosting adapters Astro ships with, and would have had this up days ago. That would be far too simple. I wanted to host it on AWS. I enjoy AWS’s primitives and the control it gives me. I also have my own AWS Organization, so can spin up and down accounts easily. Some people have home labs, I have an AWS Organization.
The problem of course with AWS and its fantastic primitives is that they are primitive. There isn’t the wonderful developer experience that the average Netlify, Cloudflare, or Vercel user would be used to. All I need to do is create an S3 bucket, a CloudFront distribution, and have an easy way to update that S3 bucket with static files generated by Astro. This needs to be automated, I just want to write a post, push to my repo and it all gets updated. Simple right?
In the world of AWS the correct way to do this would be to use an Infrastructure as Code (IaC) framework to create the infrastructure, and a script to update the content. LLMs make writing IaC code easier than ever before, so it should be simple. The problem is IaC frameworks are big, bloated and complex. They cover the length and breadth of AWS and many potential workflows.
IaC frameworks have to be updated and maintained. They cover a ton of use cases, of which mine is but a tiny one. The underlying APIs they call are stable, but the frameworks are always moving as they look to expand their usefulness by adding features. I don’t want that for me.
The sane thing of course is to write my own tool that deploys just what I want and nothing else. Which is of course what I did. The lifecycle of this blog is managed by a custom CLI that handles all cloud operations. LLMs may be good at writing IaC code, they’re also very good at cutting out the middle man and writing a hard coded set of API calls that deploys the infrastructure required for this blog. No IaC framework, and no SDKs. Just a credential helper, a Sigv4 signing library and REST API calls.
The CLI in reality is a few scripts in a trenchcoat with a help file. It hard codes the infrastructure topology, and takes a parameter file for the configurable bits. The blog is deployed in three commands. Run aws login in your terminal to get local credentials. Then blog bootstrap to deploy the infrastructure. Followed by blog deploy to make the latest changes live.
It supports named persistent environments alongside ephemeral preview environments. It can be easily integrated with GitHub Actions or your CI tool of choice to create PR previews.
It tracks deployment history, and can stream deployment logs directly to your terminal. Deployments are versioned by git hash, allowing easy rollback by running blog rollback <hash>. It cleans up the infrastructure with a blog destroy command.
It gives you the modern hosting experience of a Netlify or Vercel, but directly on AWS. Instead of pulling in a 144MB CDK library before I’ve written any templates, I now have around 250KB of code. No cascade of SDKs to depend on, just a primary dependency on incredibly stable APIs. A full GitHub Actions workflow run to deploy new content takes a minute, including downloading all dependencies and the Astro build.
I’m going to generalise it and open source it soon. It can only deploy static Astro sites for now, but it can easily be repurposed for other static site generators. Look out for a detailed follow-up post on the architecture when I open source it.
Using LLMs to write tools specific to your use case can unlock efficiency, and improve maintainability by cutting through the layers abstractions hide, removing the need for the abstractions at all. Long-term IaC frameworks as we know them will be irrelevant.