Why I wrote my own Static Site Generator

Published on Friday, 02. April 2021

In the last few months I took some time to build my own static site generator (SSG). If you don't know what an SSG is, it's a tool to build websites. Unlike Wordpress that comes with an online editor, a static site generator takes a bunch of text files as input and converts them to HTML. Then you manually upload the generated files to a web server and voilà, there's your website. There are already a plethora of SSGs out there, Hugo probably being the most popular right now. Having all these options, why the fuck did I decide to build yet another one?

The build-it-yourself disease revisited

In a post from last year, I used the label build-it-yourself disease to describe the habitual inclination of building my own solution for every software I use. Using this definition for disease ("a condition [...] that impairs normal functioning [...]"), you could take this label almost literally.
If you define "normal functioning" to mean getting things that matter done, building my own SSG was as much an impairment as I can think of. Because while building it, I mostly stopped writing. So in this sense, building it didn't do anything for my blog.

There is nothing quite so useless as doing efficiently that which should not be done at all.

Peter Drucker

If anyone would ask me how to start their own blog, I would suggest to setup an instance of WordPress or Hugo and start writing within less than 30min. Getting started writing is the most important thing. Everything else is a distraction you can come back to later. Publishing your first post, is much more intimidating than fiddling with the design of your website (at least it was for me), So it's important to focus on your writing. Yeah, you won't like how your website looks, but that's alright. You can fix it later.

I think I had the desire to build my own SSG even before I started my blog (not that surprising, is it?), and it came up on a regular basis. So last december, I finally gave in. I don't think the idea of building something yourself is wrong in itself, but you should be careful about what you want to build. At the basis of this decision lies a trade-off between your perfect solution (whatever that means) and the resources needed to build it. Writing my SSG took me about 2.5 months, multiple refactorings, and a complete rewrite in a new language (granted, my planning of the project was horrible to non-existent). And I'm only at a first version that is kinda usable. There are many features I would like to add, and some bugs and constraints make it completely unusable to everybody but me (starting with a hard-coded website name for url generation). The question I'm now asking myself is, was it worth it? Why did I decide to build my own SSG in the first place?

One aspect I have to mention is procrastination. While I want to do more writing, it's also much more of a chore than programming. I don't think I'm that great of a programmer, but once I get started with a new project, it's hard to stop myself from working on it. For writing, on the other hand, I have to force myself each day anew. Part of this is that I've been programming much longer than I have been writing, so I'm much more comfortable doing it. But I think the most important difference between the two is that writing is much more personal.

When I'm working on a private programming project, in a context where I don't have to care about code quality (feel free to look at my code to see what I mean), it is much more obvious what I'm trying to do. While there are some problems to solve on the way, it is clear where I'm going. Writing is different. When I start to write about a topic, it starts to evolve. I never really know where I will end up, what the result will look like. This can be exciting, but also intimidating. Especially when I'm writing about something that is important to me, it becomes a much more intimate and emotional process than programming ever will be. So I get much more self-conscious about writing, feel much more insecure about it. Building my own SSG definitely was – at least in part – an enjoyable distraction from this. But it was more than that.

From an high-level perspective, programming simply is the automation of many small decisions that you don't care about in order to focus on what you actually care about. If you are writing a post in WordPress, you don't really care about how the text is transformed into a website. You don't care about how the server is set up in the background, or how the files for your posts are called, or even how they are stored. If everything works, you're all fine. Developing an application is full of those small decisions. And sometimes, it makes sense to make these decisions yourself. But because building an application takes a lot of time, you should only do it in areas you care about. I don't care much about email, so I won't build my own email client. But I care about writing. And building my own SSG was a way to revisit all these small decisions other people made and to make them in a way I want them to be.

Design Considerations

In the end, my SSG ended up being quite comparable to (a small subset of) Hugo and only differed in small to mid-range adjustments to my writing process. This isn't that much surprising. Most of what I implemented is the groundwork needed for HTML generation and reading the input files. The exciting stuff would come later. For now, most of the things I did could probably be done by trudging through Hugo's documentation.

Native support for org-mode

I'm writing my blog in Emacs. I'm not really married to Emacs (otherwise I would have written the SSG in Elisp, which I haven't), but I think it's great to use the same application for everything that is related to typing. The main reason I'm using Emacs for my blog is org-mode, which, for the purpose of writing, is a slightly more powerful version of markdown with a great interface. And before you say anything, yes, it can be used with Hugo as well. But all attempts using it ended up only kinda working. I had to do some compromises like writing links filled with macros instead of using the links in org-mode, and add boilerplate config to each post I wrote. This alone probably isn't a reason to start building my own software, but I used the opportunity to write something that matched my preferences.

Building a tool for my writing system

I'm lazy. Extremely lazy. It doesn't matter what goals I set myself, when I'm actually working on it, I instinctively look for an easy way out. Sometimes I take them very literally to construe them to mean something else than originally intended. At other times, I outright ignore them. I found two ways around this. First, set very specific goals you know you are able to accomplish. Second, design your environment. Make the good things easy and the bad things hard. When you want to stop watching Youtube on your Smartphone first thing in the morning, don't charge it on your bedside table. If you want to eat healthier, precook healthy dishes and don't buy any sweets. The same ideas are relevant for software design.

As I already mentioned, software engineering is just a bunch of automated decisions. Most of them influence how the user interacts with the software by making some things harder than others (Have you ever tried to cancel your Amazon Prime account?). These things are not necessarily hard on an absolute scale. But sometimes, it's enough if they are just a little bit harder than an actually worse alternative. And this is at the core of why I started to build my own SSG. I wanted to revisit all those micro decisions and to make them in a way that actually serves what I want to do with my blog.

Custom theme

When I started my blog with WordPress, I picked the first theme I didn't find just awful. I still didn't like it, and set the task to change it sometime soon (which, of course, I didn't). It was something I could perfectly ignore, even if I really wanted to change it. When I switched to Hugo, I found a theme I liked much better. It still wasn't perfect, but it was something to work with. But again, I didn't customize it. I just couldn't motivate myself to learn about creating themes in Hugo when all I wanted was to create a few minimalist HTML templates with a single CSS file. Writing my own SSG forced me to write the theme from scratch. I basically copied the theme I used with Hugo, simplifying it and ending up with something I like much more.

Required summaries

If you take a look at my blog index, you'll notice a subtitle for each post. This in itself isn't worth mentioning. You can do the same with every blogging software. In Wordpress, this is controlled by writing the extract, an optional field for each post. If you don't anything for the extract, it is automatically filled with the first few sentences of your post. Hugo behaves similarly. I prefer having a summary, but it happened quite often that I realized after having finished a post that I forgot to write it. But because I just wanted to get the post out, and it was easy to skip the extract, I just did that and never looked at the post again. For my own SSG, I changed this. When I try to publish a post with a missing summary now, the application returns an error.

Obviously, this is only a small thing, but with a bigger principle behind it. The idea is to adjust the software I'm using to my desired writing process. Just as I'm forcing myself to write a summary, I could force me to execute a spellcheck before I'm able to publish it, or run any other metrics. It also means I had to take a bit of time to add summaries for all previous posts after having them written about a year or so ago. Something, I wanted to do when switching from WordPress to Hugo, but ignored because it felt so tedious. In the end, it took me maybe 15min.

Projects instead of categories

The SSG is not just about setting constraints for myself and forcing me to uphold them. It's also about creating a software that reflects how I think about writing. One example where this is relevant are categories.

Using Categories to organize a blog by topics makes only sense if they are pairwise disjoint, meaning that a post belonging to category A doesn't belong to any other category. So far, so good. I could create a category for fiction (called stories) and one for nonfiction (blog). Because I'm using an SSG, the categories are modeled by creating a folder for each, thereby enforcing the disjointness. This is where things starts to get messy.

Last november I started a "Writing Fiction" project that I wanted to use to, well, learn about writing fiction (Hence the name). Because it was quite ill-defined and I have an attention span o... "Oh, look there's another fun thing I could do", I abandoned it relatively quickly. But here's the problem I had.

Because it was one project, I wanted to have all files in one folder. The question is, which category does this project belong to?
It couldn't be stories, because the plan was to also write some non-fiction posts about the things I learned and to report on my progress. Using the category blog defeated the purpose of having the stories category in the first place. In other words, on a project basis, a disjoint topic organization falls flat. Of course, I could use symlinks to have all files in the same folder and in separate categories. But first, I only had this idea when writing this paragraph, and second, this is the definition of messy and more a hack than a real solution. Instead, my idea was to organize my blog around projects.

Much like a category, a project is a collection of posts. Unlike a category that tries to capture as many posts as possible under the hood of one rough topic or the medium of it's posts (i.e. if you use the category "podcast"), a project is organized around a single goal that is as specific as possible, but large enough to justify more than one blog post. The goals don't necessarily have to be time constrained. For example the blog could be a project with the goal to "Write one post per week about anything you want". What is important that each project is connected to one actionable goal, instead of a rough topic idea that basically anything can go with. This makes categorization much easier. It's also a handy framing device.

When I'm writing a post, its topics change while I'm working on it. In the end I'm almost always somewhere else from where I anticipated to be. When using a post-writing topic categorization system, I had difficulty deciding in which category I wanted to put a post. With a project based view, It is clear from the start to which project a post belongs and what it will be about (at least roughly).
And then, if I still want to do some topic organization, I can still use tags for this. A graph-based system is much better to organize topic clusters than trees can ever be anyway.

Technically, projects are very similar to categories. So much so in fact, that they could be implemented in Hugo or WordPress by just using categories differently. Furthermore, in my current SSG, they aren't even implemented. Still, writing my own SSG helped me to think from first principles what I wanted to get from categories.

Conclusion

My SSG is a crap piece of software. It has bugs and limitations that make it unusable for everyone but me. But that's ok. I never intended it to be used by anybody else than me. Yet, while reflecting on why I wrote the generator in this post, I regularly had the feeling that I build it for the wrong reasons. Sure, I had fun doing it, and I learned a new programming language (two, actually) during this process. Implementing it was great to think about my blog from first principles. But to do this, it isn't really necessary to write your own software. And all in all, I don't think what I wrote is that useful.

If I look at each feature in isolation, I feel like it would have been really stupid if I build my SSG only for the feature alone. A lot of the problems I addressed could be solved in Hugo, or by just planning ahead a bit and using checklists. Putting the same thoughts into a system for Hugo, as I put into what I build here would have been much more effective. But when I started the project, I lost the view of the big picture. I think I started with the primary desire of wanting to learn a new programming language and used this to justify the idea of building an SSG. And so far, it didn't make me a more productive writer. If I had to start another website I would probably use Hugo again, and stick with it.