Written by Herman Groenbroek – 4 January 2026
How I redesigned my website using Django and Wagtail.
I love to design things, but I haven't studied for web development. I do Artificial Intelligence and I'm mostly focused on either delivering cloud solutions or advising organisations how to best utilise AI. However, I also really just like to nerd about. Previously, this website was hosted only partially using Django (which I had very little experience with), in part vibe-coded, and I couldn't figure out how to host my blog in Django as well. So I did what I knew best: I turned the blog into a Docker container running Wordpress, all with a very similar CSS style under the hood so that users would hopefully never notice the difference.
Enter the Christmas holidays of 2025. I figured, if I'm going to do something, I should learn to do it right. So I went back to the Django drawing board. I had given myself two weeks off, all to figure out how to develop my own blog in my favourite programming language—Python (and to hang out with loved ones, of course!). I am, after all, mainly a Python developer (if only there was one-syntax-for-all). On the other hand, planning the backend redesign, I did have one sad realisation: if I did the transfer from Wordpress to Django perfectly... users would not notice a thing. Except faster load times, perhaps. "So I probably should change something to the front-end as well", I figured.
What's the end goal?
When I tackle a sizeable project, I try and structure the requirements as TODOs. I love making lists after all. So I made a big TODO list, continuously updating subtasks, mainly focusing on:
- Moving the entirety of greenpants.net from my home server (where everything was running previously) to a Virtual Private Server (VPS) hosted in Europe. I opted for Hetzner; they offer the cheapest options, as far as I could tell. And I like to challenge myself to make everything run efficiently.
- Remove Docker and other unnecessary overhead, and make sure the server is runnable with minimal overhead for the best performance on the relatively affordable VPS. This means developing everything via Django and with a single Gunicorn socket.
- Get a full-fledged Content Management System (CMS) so I can create drafts and posts in a visually appealing editor (with my backup idea being: directly displaying posts written in Markdown, which would have brought forth its own inconveniences).
- Fully redesign the front-end with a more modern approach, and using best-practices. Without Wordpress I had to switch out PHP blocks for Jinja templating anyway. The previous blog posts themselves weren't really pleasing to the eyes in terms of font sizes and margins.
- One of the random quotes you can see on the main blog page talks about how "an x-percentage of all statistics are completely made up". I wanted to be able to use simple Python to randomize this percentage, just because :-).
Hard lessons: what was particularly difficult?
As great as developing everything youself is, you can probably imagine that having to develop everything yourself takes a lot of time. Time that could be spent creating photobooks, editing videos and learning to play violin. But hey, if you put my mind to it, you can accomplish anything, so I wasn't going to back down.
Although LLMs nowadays are great for learning something new, unfortunately, Wagtail is not one of those subjects that LLMs know everything about. It's not common enough in its training data, despite Django/Wagtail not being uncommon either. ChatGPT's premium model may know its way around it, but the local GLM-4.5 Air (106b) LLM, or ChatGPT's cheaper, unlimited models, frequently hallucinate packages and make erroneous assumptions about my codebase. There are so many ways to set up Wagtail with Django with Gunicorn and Nginx, that I completely understand that providing full context all the time can be a hassle. This is also why I don't think we're there yet with Agentic AI—in fact, far from it. You still get hallucations galore, unless you provide a very efficient summary of exactly the relevant lines of code from every place where a bug can originate from. And if you know what context to provide, don't you already have a good guess where your bug comes from? As you can see, you need knowledge to gain more knowledge.
I've also learned that, in URLs, there is apparently a huge difference that a trailing slash can make. I'm hosting my blog on greenpants.net/blog, but also using the subdomain blog.greenpants.net. I've had lots of trouble making Wagtail not add /blog/ between the base URL and each blog post slug. I noticed that a final trailing slash was all I needed to solve one of the bugs of erroneous redirects. All while all LLMs I asked—including the premium ChatGPT model—kept making me change my Nginx configs as well as Wagtail setup. You can imagine the frustration if you don't know what you're doing. Luckily, I knew it had to be Wagtail serving a different URL due to my blog mainly being on greenpants.net/blog, and the main page actually containing /blog/.
Whatever. Show me the end result!
The fact that you're reading this blog post is a testament to its success. Everything you see here was hand-crafted by yours truly. I don't do typical vibe-coding; I try to understand what LLMs suggest, and I always ask for best-practices, in order to learn more about the underlying technology stack. Funnily enough, this was written in the evening on the very last day of my two-week Christmas vacation.
The fact that this server runs in tandem with a Paper Minecraft server on the cheapest VPS that Hetzner provides—2 vCPUs, 4GB RAM and 40GB ROM for €3.62 a month—really shows what you can accomplish when you try to be mindful of virtual resources.
I willl probably have to scale up in the future, but I can easily add more Gunicorn workers if need be.
Anything still on your wishlist?
Of course! If only I had the time to implement...
AnRSS Feed—RSS isn't dead!✅- Auto-generated Table of Contents when a post has at least three subsections.
- Proper code blocks (which probably requires a JS plugin)
- Backlinks for external references to this blog. Would be great to keep the conversations going.
- Analytics akin to Umami—something that lets me analyze traffic without compromising visitors' privacy.
- Semantic vector search! I have to; I'm an AI Engineer. But first, more blog posts to make it actually worthwhile.
- Even more randomized quotes on the blog's frontpage; suggestions are welcome!
The great thing about Django? You can build practically anything you like! The more popular this blog gets, the more I can convince myself to spend even more time to improve the UX :)