Part of project: zssg

Introduction to zssg

What I want from a static site generator

Posted on May 05 2026

This site is written with Jekyll as its static site generator. It works well enough but there are aspects of it that I wish were different. I’d like to make my own that prioritises the things I care about, and this project will document that effort.

History of this website

This website wasn’t always written in Jekyll. When I started this site I didn’t even know about static site generators. The thought of ‘compiling’ a HTML page didn’t cross my mind. I assumed the only option besides manually authoring each page was to do something completely dynamic. It’s for this reason that I started this site on top of Wordpress.

Wordpress was functional. I liked being able to write posts in the browser, but it was never a must have feature for me. Eventually I got fed up with the continuous stream of security patches that had to be applied and decided to rebuild the site.

At this point I still didn’t know about static site generators so I decided to build my only dynamic site generator. It was a few PHP scripts and a few snippets of HTML. It didn’t really work well. I never even tried making an in browser editor for posts. Turns out my attempt was just as insecure as Wordpress, so I gave up on it after a while.

The I discovered GitHub Pages and Jekyll. It was eye-opening. I hadn’t considered adding a build step and then just serving static files. I threw away the existing themes and jumped right into custom layouts to make sites that worked how I wanted. I eventually applied what I had learnt to this site, though I never did write very much for it.

Recently I had a look at Amos Wenger’s dodeca static site generator. He generally does really good work so I was expecting it to be pretty smooth to build a new site with it. It was anything but. The templating engine seems completely unable to express basic conditionals like ‘if the [extra] section of this post’s front matter has a particular key defined, render this section’. Instead I would get errors telling me the key wasn’t defined in the very condition where I was trying to check if it was. I promptly gave up and decided to build a new site but still in Jekyll.

This time I did more work with custom plugins to let me group certain posts into projects and have a nice navigation experience. I also spent more effort on how the site looks but that could have been done in any competent SSG.

My Priorities for a Static Site Generator

Beyond the fundamentals of a permissive templating engine, my single highest priority is plugins. Plugins make it possible to customise the SSG beyond what can be done within the templating language. I’ve already mentioned how I use a custom plugin to support grouping posts into projects, but I also use it for the recommendations at the end of blog posts. Each post has a list of tags in its front matter, and it just looks for other posts with lots of tags in common. I couldn’t come up with a way to do it in liquid, but it was all of about 30 lines of Ruby.

Dodeca doesn’t have plugins (at least not at the time of writing). It does have ‘Build Steps’ but, as far as I can tell, they’re just a nice way to hook a command to be run at build time and reference the output from your templates. It can’t transform posts between parsing and rendering, or inject synthetic posts.

I did also look at Cobalt after the bad experience with Dodeca, but it too doesn’t offer a plugin system, and at this point I consider one a need-to-have.

Building a static site generator where the plugin system is the headline feature

What might a static site generator look like if it were built around its plugin system. I think it ought to be fairly agnostic over the language used for the plugins. I managed to use Ruby for the plugins I needed to write for Jekyll, but it was complicated by me never having used the language before. I don’t have any interest in Ruby as a language so if Jekyll gave me more options I probably would have chosen something else.

If plugins are a first-class feature, it should be easy to bring in 3rd party plugins. Part of making it easy is not having to worry about malware pretending to be just the plugin you need. So plugins should be isolated from the host so they can’t steal all of your browser’s cookies and saved passwords or encrypt and ransom your files. Isolating the plugins means a plugin will have to bring its dependencies with it, but that’s probably for the best since it will improve compatibility.

On the topic of compatibility, ARM CPUs are becoming more common (and RISC V might get there eventually too) so plugins should be agnostic of host CPU architecture.

This all points to running the plugins in some kind of thin architecture-agnostic virtual machine that can be targeted by many languages. Web Assembly is a thin architecture-agnostic virtual machine that can be targeted by many languages. I’m hardly the first to imagine using Web Assembly for this purpose; the Extism project looks perfect for this. Looking more closely at if it can handle fine-grained isolation, I’m not sure it can so I can’t just use it as-is but I can at least use it as a guide.

A good way to make sure that the plugin system is sufficiently powerful might be to actually make every part of it beyond the plugin runtime itself a plugin. It’ll end up being very modular, like a build-your-own-SSG toolkit.

The rest of this project will document building such a static site generator and hopefully by the end of it I’ll have a tool worth rewriting my site in yet again.

Webmentions

Mentioned this post on your website? Enter the link below and I'll add it to this section.