Keyboard Playing’s Technological Stack

Hope you don’t get a jolt from the static…
  FR
 8 min. to read
 chop
 No comment yet
  (last mod.: 2023-03-05)

Last week, Tony asked me about the technological stack behind my website. It’s a subject I wanted to write about once the website was stable, but I keep tinkering with it. As such, it’s far from finished and I still have many ideas, but let’s talk about it now nonetheless.

Basically, the objective I set myself upon beginning the new design of the website was to make as much of it static as possible. And I discovered Hugo, which seemed to meet my requirements.

The Stack for the Impatient #

If you don’t want to go through all the history that led to this stack, here are the essentials:

  • Hugo generates static pages:
    • It turns Markdown files into web pages.
    • It generates several sizes of the images that I include for display.
    • It compiles my SCSS into stylesheets and relies on PostCSS to apply a bunch of rules of my choice.
  • Rollup bundles all my JavaScript fragments into coherent scripts.
  • NPM drives all that.
  • Staticman transforms post comment into commits.
  • GitLab CI/CD automates the build and deployment of all that.
  • Matomo will be used for analytics that respect privacy.

From the Drawing Board… #

If you’re more curious, or just happen to have a bit more time, you may wonder how I came up with these choices. I’m deeply convinced there’s no silver bullet when it comes to building a stack, and building out of habit does not give optimal solutions. Before choosing the latest fashionable technology, I needed to know what I was building.

Functional Requirements #

Basically, I wanted a platform to publish. Posts, short stories, IT projects… I drew on my previous CMS experiences with Dotclear and WordPress to add some additional requirements. First, I wanted the possibility to publish in both English and French, with links between equivalent posts. I also liked taxonomies in the past, even though they may seem accessory. Finally, the ability to comment was non-negotiable.

It’s also commonplace for people to use Github Pages as a blogging platform. I like that anyone can submit a merge request to correct mistakes or suggest enhancements.

Finally, I’d like the ability to get some analytics to know what interests readers. I’d like, however, to avoid cookies or other tracking technologies to respect their privacy.

Non-Functional Requirements #

Features is not all, you have to think of the non-functional constraints.

Since I babble about sustainable IT and ecodesign, I also wished to use the occasion to apply this to my dev and demonstrate how just a bit of thought can have an impact while remaining usable.

I talked about habits. If I had asked anyone on the base of the functional requirements, I’d probably have heard, “Get yourself a WordPress!” The thing is, with (most) CMS, the page is computed each time a reader accesses it, while there’s very little chance it has changed since it was last accessed. That’s why I’d rather deploy static content if possible.

I also longed for sobriety: use as few external resources as possible, avoid external scripts, stylesheets… In other words, I aimed at reducing the number of HTTP requests required to load a page.

One more wish I had was to rely as much as possible on open source solutions.

To Sum Up #

  • Publication platform with localization and taxonomies support
  • Commenting capabilities
  • Edit suggestion capabilities
  • Privacy-conscious analytics
  • Static
  • Sober/bandwidth conscious
  • Open source

… To a Technological Stack #

Choosing a Static Website Engine #

Both Github Pages and GitLab Pages do what I wish: create static pages based on structured data you provide and a template you choose. In the past, I looked at how the former worked and gave Jekyll a look. At that time, however, I never found the “quick start” guide and quickly gave up.

For Keyboard Playing, I had a quick tour around search engines and Hugo quickly appeared. I quickly selected it without much of a comparison, because I found integrations with other tools I wished to use, and because it was written in Go. See, I have a colleague/mentor who has a tendency to focus on anything built with Go, mainly because its mascot and its multiple variations amuse him. This has somehow bled onto me, and I’ve not been disappointed so far.

Go's gopher, wearing a superhero cape and mask.

Hugo’s version of Go’s gopher

Hugo supports taxonomies and most other common blog features. It transforms Markdown files—with the CommonMark specification—into static web pages.

It’s flexible: though you can choose from many themes, you can create your own and customize it to go as far as your imagination can lead you. I did so, to be sure to include only what I needed (sobriety, remember?) and for instance designed the cover image mechanism (okay, maybe not that sober…).

It’s blazing fast. I just built the website to give you a figure, and it took less than 3 seconds on a little laptop. This build includes generating the stylesheet, as well as providing several sizes of most images from posts—I’ll come back to that later. I tried—and succeeded—using AsciiDoctor instead of Markdown, but the performances took such a hit that I gave up. Still, Markdown is not an obligation.

Hugo also handles internationalization pretty well. It generates one website per language—and the dev server has one URL per language too, so that you can see how things work quite faithfully.

And now, I can host the source files on an open-source platform, such as GitLab. The sources are publicly available and anyone can fork and submit a merge request, while I can rely on GitLab CI/CD to make the heavy lifting and repetitive tasks of deploying all that.

  • Publication platform with localization and taxonomies support: OK
  • Edit suggestion capabilities: OK
  • Static: OK

Enabling commenting #

Since the pages are generated from static files, there’s no database to save comments. The closest thing is my GitLab repo.

Of course, I could rely on add-ons such as Disqus to handle comments, but that wouldn’t be really sober now. Disqus loads many scripts. By the way, it also allows you “turn engagement into revenue,” meaning incorporating an ad service and possibly tracking… Well, that goes against my privacy objective too.

I imagined creating a service that would take a comment data and turn it into a commit that it would push to my repo. That’s an interesting project, actually, but I didn’t get to do it because Staticman already exists and does just that.

  • Commenting capabilities: OK

Generating JavaScript and Stylesheets #

I discovered Webpack a few years back. It allows you to write your scripts and styles in separate, logical files and bundles them into a set of static assets. This brings clarity and separation of concerns to your development.

The principle of resource bundling as exposed on Webpack’s website

The principle of resource bundling as exposed on Webpack’s website

From the start, I knew I wanted to forget all trendy libs and frameworks that save time. I love Bootstrap and Foundation, but using them often implies importing much more than you actually need, except if you’re really careful. I also wanted a bundler to optimize, polyfill, minify that code.

Luckily for me, Netlify published Victor Hugo, a template that helps you building a website with Hugo and Webpack, using NPM’s well-known mechanisms to drive it. This was a great start for this website. I had to adapt it a bit (Victor Hugo was not designed for multilingual websites), but it saved me some time and allowed me to learn yet a bit more about NPM.

In the end, I replaced Webpack with Rollup. Quick tests had shown me that this simple substitution saved 7 kB on the generated JavaScript. This in turn led me more recently to entrust the stylesheet generation to Hugo, as I discovered some issues with the handling of stylesheets through several bundles.

  • Sober/bandwidth conscious: OK

Optimizing bandwidth and CPU #

In my try-to-be-sustainable approach, I also wished to optimize bandwidth, because it saves on your data bill and because it’s good for the planet.

  • Icons are saved in a single SVG sprite. IE doesn’t support external SVG sprites, but I favored the possibility for your browser to cache across pages. Icons shouldn’t be essential to the understanding of a page, anyway.
  • Images are served in several sizes and lazily loaded. Preparing the responsive images took me some time1 but I’m quite satisfied with the result.
  • Resources are gzipped before being served rather than being compressed on the fly. I read that it’s not a CPU-intensive operation, but this felt like a right thing to do.
  • Sober/bandwidth conscious: OK

Analyzing the Audience #

Whenever using a web server, the requests being made are logged. I thought those would be an effective way to see what’s being visited without being intrusive. Turns out, Matomo (ex-Piwiq) thought of this use case. Matomo is open source and I can host it on my machine, thus being sure of what happens with the data.

The log import process also anonymizes the IP, so I have a general idea from the visitor location but can never find them back. This was a great deal for me! Now, I still need to build a Docker compose file to use this with the logs I’ve been saving until now. Help is welcome.

  • Privacy-conscious analytics: OK

The Result #

You are browsing it right now. I’m not much of a designer, so you’re allowed to think it looks bad. I won’t be hurt—that much.

And, as you may have noticed, every brick of the stack is open source!

  • Open source: OK

If you’re interested about knowing more about any of the topics I spoke about here, please leave a comment!


  1. I actually discovered a bug and fixed it while writing this post. ↩︎