Happy New Year
Happy 2026! Fun fact, the first commits to the Vanilla.sh codebase were made a few days after Christmas last year, which means that Vanilla.sh is now officially one year old! As I’ve stated in previous blog posts, I’ve finally found a writing cadence that feels comfortable to me, thanks to the tech stack of Vanilla.sh, which allows me to isolate content from design and doesn’t require managing persistent databases or maintaining proprietary text editors. Hugo has been a godsend, finally freeing me from the whims of bloated content management systems and incredibly expensive website builders.
But I’ll be honest: When I first made Vanilla.sh, I wasn’t sure it would last. I figured that, like many other times in the past, I might abandon the project entirely after a few weeks. For this reason, I definitely took some shortcuts when making Vanilla.sh - from a hastily created design, to archaic CSS sheets, to arbitrary tagging. Now that I’m sure Vanilla.sh is here to stay, I’d like to remediate these early mistakes.
What you’re looking at now is the redesign of Vanilla.sh. In this post, I want to contrast it with some of the previous design choices and explain my thought process going into the changes.
Book Reviews
The biggest addition to Vanilla.sh is a new section titled “Reviews”. Over the past couple of months, I have started reading more books, and for me, part of “closing the chapter” on a book (hehe) is to write down my thoughts on it afterwards. I’ve already started writing these reviews over the past couple of months, and you could technically find them on the website, but they were not directly linked from the template. Now, they’re here for everyone to see!
The new reviews page shows star ratings at a glance, as well as a succinct excerpt from the review summarizing my thoughts. Reviews follow a set structure consisting of a short (mostly spoiler-free, or at least spoiler-low) summary of the main ideas, my overall thoughts on the book, and finally, my rating and the reasoning behind it. I also designed a (in my opinion) pretty neat-looking header section for the reviewed books that showcases their cover and blurb.
Example of a book description found at the start of a reviewI’m not really expecting these reviews to go crazy in terms of page views or anything like that. It’s more something I do for myself. In fact, when I used to read scientific papers on my commute to work, I often wrote down summaries of those papers in my own private knowledge repository to strengthen my understanding of the concepts. Maybe, in the future, I’ll be looking to port these over to this website as well.
I’ve thought about reviewing other media, such as games or movies, as well, but currently, I just don’t have the time to keep up with writing that much content. In the future, I might be looking to tap into RSS feeds from other short-form review sites like Letterboxd to bring more of my opinions to Vanilla.sh.
No More Blinding Lights
I’m quite fond of simple website designs. I don’t need massive material design carousels, full-page banners or 3D frosted glass animations. The original Vanilla.sh design wasn’t bad, but it was one thing: bright. The entire page was built around a white background that I never bothered to change, and as a result, it would flashbang you every time you visited it after 8 pm. I also built a pretty cool visual timeline, but because I displayed it horizontally, I knew I would have problems extending it in the future.
I decided to redesign the website from scratch around a dark background. I started by defining some primary colours, including my signature “Vanilla Blue”, and redesigning the major CSS elements, then going from there. I knew I wanted something eye-catching on the front page, and quickly decided on my signature, around which I also designed a new logo suitable for the darker background.
I really like how the new design manifested. I feel like it has more soul to it, a bit more of a homely vibe - it’s more comfortable to read, colours are more unified, and it overall feels more like what I want to show off to the world.
Old Home Page Design
New Home Page DesignCSS: Utilitarianism
Styling was the big elephant in the room of the Vanilla.sh project. In fact, styling is the elephant in the room in a lot of my projects. I genuinely enjoy writing CSS, and over the years have become quite comfortable with different layouts and have acquired at least a high-level understanding of the typical components present in today’s web. Vanilla.sh’s theme, and my application of CSS overall, has always been a bit iffy, though, and I think it was due to my reliance on utility classes.
Recently, at work, I’ve started using Tailwind in our Svelte projects. Up until then, I was a
steadfast hater of Tailwind. I’ve used self-defined utility classes in the past, like m-3 for a 1.5 em margin, but I always
found a component fully styled with Tailwind to be cumbersome to parse - reading through dozens, if not hundreds, of style
tags on a single element to understand its different possible states.
So, I always used regular CSS (sometimes with mild SCSS preprocessing), where I defined a few utility classes, but also element-specific styles where a utility class made no sense. Vanilla.sh was the same. Raw CSS, a few utility classes, but mainly element-specific stylesheets.
I think when writing this redesign, I fell into a bit of a trap, but that trap finally made the CSS discussion “click” in my brain. I heavily expanded the use of utility classes through SCSS preprocessing (using loops to cut down on the verbosity of the stylesheet). This, however, left me with fewer and fewer class-specific styles and often very small class-specific stylesheets. So, I wrote even more utility classes to be able to get rid of these stylesheets, too. But a few elements, like the book summary component, have such a unique design compared to the rest of the page that writing utility classes for them doesn’t really make sense. For example, what’s the point of writing a “border-left” utility when only one element on the entire website uses it? What’s the point of making margin utilities loop up to size 20, if only 1-5 and 20 are in use? Tailwind solves this problem nicely by bundling an app-specific stylesheet that only serves the classes that are actually in use, but my SCSS preprocessing does no such thing. Effectively, I’d just invented a worse Tailwind. With my native replacement, another issue was the few elements I couldn’t describe in utility classes - when an element requires its own class, is it then better to forego using all matching utility classes to keep the CSS in one place, or is it better not to repeat yourself?
That’s when I understood what I’d been doing wrong with CSS - Utility classes, like those that Tailwind provides, really don’t make sense in a native HTML+CSS website. It’d have been much better to just define a single class for each type of element and define all styles within the corresponding stylesheet. On the contrary, in an application that defines and exports reusable components, like Svelte (or arguably even Hugo, with the use of partials and shortcodes), Tailwind can actually be very useful for rapid styling and keeping the definition of an element within a single file. Either way, I think it’s important to pick one approach or the other, rather than mixing and matching them, as I’ve been doing.
Vanilla.sh, after my redesign, relies 90% on utility classes. That’s not a terrible thing, I’d say. It’s just a bit unfortunate that Tailwind isn’t cutting down the resulting stylesheet size, and allowing me to get rid of those last 10% class-specific styles. This shouldn’t be a crazy amount of work, so it will probably be part of the next major update to the website.
Refined Metadata
Hugo has tags! Hugo loves tags, actually, and you specifically have to configure it to not serve pages for filtering by tags. Doesn’t make much sense to provide such pages at the start of a website’s lifetime, when there are only one or two articles on it. So, when I wrote my first few articles, I didn’t really give the tags I added much thought, since I wasn’t planning on using them for aggregation. With the redesign, though, I wanted to rectify this while the number of articles on Vanilla.sh was still low, so I can eventually add this functionality as the amount of content on the site grows.
Tags on blog posts now follow a predictable structure consisting of:
- The type of post (i.e. project update, sysadmin documentation, opinion piece)
- The main project or concept the blog post is about
- The main technology that drives the blog post
In case a tag category is not applicable for a given post, this category is skipped. Reviews are currently tagged by genre, and are additionally categorised on the backend by their medium, in case I ever come back to the idea of non-book reviews. I’ve both revamped the display of these tags and removed unnecessary styling from the content previews, so it should be much easier to get a better first impression of what a blog post is about.
Old Card Design
New Card Design
Review Card DesignStreamlined Local Deployment
Vanilla.sh is part of last year’s “VPS era” and ran on a cloud-hosted virtual machine. To deploy the website, a GitHub action would connect to the server via SSH and copy Hugo’s output directory directly to the web directory served by nginx. That process is not terrible per se, especially for a static website that can be deployed without external dependencies (other than the target directory being somehow reachable from the internet), but it’s also not ideal from a security standpoint, since it requires keeping SSH exposed with a deployment user that has full access to the public web directory. This user, at the very least, must be specified in GitHub secrets, giving the cloud runner access to said user and leading to possible security concerns regarding access key leakage.
I’ve decided to finally containerise Vanilla.sh, to streamline it with other applications I am currently self-hosting. This has a few advantages. First of all, the application is fully self-contained now and no longer relies on an external reverse proxy. Much more importantly, though, this inverts the dependency during deployment. Instead of directly pushing the application to the server, I can push it to a container registry and pull updates on my server automatically. This reduces the potential attack surface from full shell access to containerised arbitrary code execution. When you say it out loud like that, it doesn’t sound amazing, but I mean, I guess the worst-case scenario when having your deployment credentials exposed never does.
Vanilla.sh now runs on my homeserver behind a Cloudflared Tunnel guard, similar to the rest of the web services I currently self-host. Admittedly, for something as simple as a static website, Cloudflare’s stack may not be as useful as for a data-intensive or high-security application, but it’s free, and just in general a pretty neat service that streamlines the deployment with the rest of my server’s setup, so there’s really no reason not to.
Sometime in the future, self-hosting my code repositories on my “indestructible data” platform could further reduce the attack vectors, since deployment and corresponding credentials would stay inside the local network, but for now, this will suffice.
Most Importantly
I also added a favicon. It’s kind of a work in progress, though. Coming back to that one in another few months.