Why I Wrote yet Another Static Site Generator

oz, 2018-03-16

Once a while somebody wants to write a blog post...

Previously my website and blog hosted on GitHub were statically generated using Hugo. Even before Hugo I tried Jekyll, Pelican and was checking out any site generator, that had at least some two-digit star count. Jekyll seemed too bloated and heavy-weight for my use case and the last time I looked into Pelican it had a license that I could not fully assess.

Hugo certainly is a nice tool, but keeping track of updates and dependencies is annoying. Even if I use a popular Hugo theme, I need to track updates of both Hugo and the theme. Updates usually involve messing around in the configuration file as well. Configuration files are almost always not compatible between different themes. The same applies to the folder structure and canonical links.

My Requirements

I did not find a single SSG fulfilling my personal requirements:

Leverage free GitHub infrastructure
GitHub Pages is a real asset for me. Anything static, anything just running in someone's browser, I want to deploy using GitHub. Authentication is set up for development work already. Everything is free as in "tea". The behavior is really transparent:
  • GitHub Pages maps my repos nicely to its github.io subdomain. A SSG should be able to leverage the repository/directory structure!
  • README.md files are rendered nicely on GitHub and can be edited there as well. So the SSG should support rendering README.md files as index.html files for the repository/directory the file is located in!

If you want to view the markdown file "as is" on GitHub, links to own assets/posts are usually broken in most SSGs due to templated links. GitHub Pages has Jekyll support included, but it is not as transparent as running Jekyll and deploying the result on your own.

Responsive design and pleasant typography
Despite the mass of themes and free resources, this is still not a baseline. My website/blog should be nice to read everywhere and fonts should not strain the eye!
Markdown support
Life is too short to manually write plenty of markup. It was surprisingly hard to find a suitable markdown conversion tool/library, because there are so many dialects/extensions that lack proper implementation. I now decided for Python Markdown and its extensions.
Suitable not just for blog posts, but also for other content pages
Some static site generators and themes are limited to specific use cases, I do not want to be restricted here.
Twitter Card, Open Graph support
This is covered by most themes, but it is again theme-dependent and if you develop your own theme, you need to take care of this also.
Portability
Unix tools, bash, git, Python and some common apt packages are available even for my preferred terminal emulator on Android. The tool should work in this environment.

Further there are lots of things solved by multiple SSGs that are no requirements for me. An excerpt:

Fast, incremental generation
With my blogging frequency this might become an issue when the sun turns red...
Big theme selection
I just need one working theme. SSG themes are seldomly ranked, so it is hard to choose one to commit to.
Template engine, theme development option
See above, I just want something working to focus on writing content.

Why don't you just contribute to some project or develop your own theme?

I attempted to develop my own Hugo theme in the past, but I estimated the effort understanding all concepts and writing the archetypes, snippets and templates greater than just developing my own SSG. For the same reason contribution to another SSG project was out of question: Too much effort catching up, esp. since most general purpose generators emphasize different features, that I do not need (see above).

So instead of investing time into things that might not yield the desired result, I decided to go my own path.

My Solution

This blog and website are now generated by gg.py, a single Python3 file inspired by bashblog.

Initially, I picked Milligram as CSS baseline. It provides nice defaults without the need to put classes on every HTML element. This is especially handy, since I do not want to post-process the HTML generated from the Markdown input. Further dependencies included Google Fonts, Font Awesome and highlight.js. In the meantime (update 2022-03-06), I removed most CSS/JS dependencies and went with minimal, sane defaults inspired by http://bettermotherfuckingwebsite.com/ (no HTTPS, care!)

Open Graph meta data is rendered. The Python configuration file enables future preprocessing steps.

The mapping of GitHub repositories to (sub-)pages works nicely. Previous my website and blog were in the single repository ooz.github.io. Now the blog has its own repository which fits in with the GitHub Pages of some personal projects (e.g. ggpy, handshake and lifetime-clock). The new repository/page tree now looks like this:

ooz.github.io      # GitHub user page
├── index.html
├── blog
│   ├── index.html # Autogenerated from all blog posts
│   ├── 2018
│   │   ├── why-i-wrote-yet-another-static-site-gen.html
│   │   └── why-i-wrote-yet-another-static-site-gen.md
...
├── ggpy           # A normal repository page
├── handshake
├── lifetime-clock

Open Ends

Obviously, the 12-hour-hack solution is not feature complete and has some rough edges. Things I am still looking forward to:

I thought about supporting Disqus as well, but I will probably rather include a "web 1.0" notice about using Twitter, GitHub issues or email to comment/contact me. This also reduces the attack vector of some German/EU bogus laws.

Generate it up!

All in all I am pleased with the result so far. The CSS framework, Markdown library and font selection were the biggest pain points costing a lot of development time. Writing gg.py was still a nice exercise: I learned about Twitter cards, Open Graph meta data formats and (re-)discovered some nice bash quirks in the source of bashblog!