Moving to a CMS

Until this point, all the pages of this blog that you saw were painstakingly put together using only plain old HTML and CSS. I love working directly with HTML and CSS. It is a “back to the roots” therapeutical experience.

But unfortunately, whatever amount of money I save on shrink visits, I now spend on acetaminophen for the constant headache induced by keeping every pages in sync.

I thus decided to use a CMS. A CMS (or Content Management System) will allow me to reuse some part of the HTML, let me use Markdown articles without converting them to HTML first and will simplify the taxonomies (posts tags and categories) management.

But I am not willing to use just any CMS. I will not be satisfied with a Wordpress install or even a Drupal-based website. I have looked at many CMSes, both at work, and at home, thanks to my daily-keeping-up-with-tech-news routine. I have tried some of them and have been dissatisfied, like it is my habit, with the blatant complexity and sheer weight of most them.

Among this trove of performance hogs and UX labyrinth, I have found a nugget of hope: Hugo.

Note: To be clear, there are many other performant alternative CMSes, most of them being called “static sites generators”. Gatsby, Next.js, Vuepress and others are all perfectly fine. I found that I personally prefer Hugo. You can find many other static site generators on StaticGen.

Hugo is self-acclaimed as “The world’s fastest framework for building websites”. Whenever I hear such claims, I become very skeptical. When something seems too good to be true, it usually is.

So I set out to try Hugo to see whether its claims hold or are made out of pretentiousness (no offense to Hugo’s maintainers). Considering that Hugo is built with Go, it is already a good indication of the possible performance.

Aerial vue of a maze

I’d rather be spending time in that kind of maze. Nice edge-trimming, by the way!

Using Hugo

I will spare you the installation of Hugo. But here is a link to Hugo’s quick start guide if installing the CMS tickles your fancy.

This post will describe my experience moving this blog from plain HTML to Hugo.

Creating a new site

Creating un site with hugo is easy enough. hugo creates the directory structures that you need for your website, and a sample config.yaml file. The following command lets you create a new site.

hugo new site -f yaml my-site

The -f yaml flag is optional here. I just like reading and writing YAML files better than TOML files if I have the choice.

With that you get the following directory structure:

.
├── archetypes
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes

You can find here the purpose for each of these directories. For now, I would like us to focus on the config.yaml file, that contains the global configuration of our new website.

Editing config.yaml

This config.yaml file is the backbone of your hugo website. By default it contains only the following content:

baseURL: http://example.org/
languageCode: en-us
title: My New Hugo Site

These three options are straightforward. You can find a complete list of the supported options in this file here.

One vital configuration option for me though, that I could not find there, was pygmentsUseClasses: true. This option allows us to use a custom CSS file for hugo’s built-in syntax highlighting. (The default theme is Monokai. So if you do not mind this one, you do not need to bother writing custom CSS like I did.)

We will look at how to build the CSS for the syntax highlighter further down and there again, hugo will serve us well. Keep reading.

Live reload development server

One especially nice feature of hugo is its embedded development server. It is blazing fast. rebuild-a-whole-website-in-100-ms fast.

The development server compiles your content, and auto-reloads your browser in just enough time for you to blink and miss the change. I was very impressed when I saw this, having fiddled with webpack and other builders or task-runners at work, and having got a very different experience.

I have not been disappointed by it since. One thing I still need to figure out is how to reverse proxy the live-reload server, behind traefik, that I use as a local load-balancer to all of my projects. (I like to keep my computer clean, and I heavily dockerize all of my development environments to help with the tidiness.)

I will figure something out and let you know. It is not a dealbreaker though, because being a Go project, hugo has a binary for almost all major platforms and operating systems, and the installation is painless (think copying-a-file easy).

Archetypes

Another selling point of hugo for me is archetypes. Archetypes are simply configurable defaults for your content. hugo reads your archetype (in which you can even put logic), and generates a new content-type ready for you to fill in with your personal content. Very handy.

This is the kind of things you can do:

date: { { .Date } }
draft: true
resources:
  - name: picture
    src: picture.jpg
tags:
title: { { replace .Name "-" " " | title } }

I hate doing things repeatedly. So once again, hugo caters to my preferences.

Creating custom theme

Creating a custom theme is just as simple as creating a website. hugo gives you another command to scaffold a new theme.

hugo new theme my-theme

And that is it!

It creates a config.toml file, that by default contains the following:

# theme.toml template for a Hugo theme
# See https://github.com/gohugoio/hugoThemes#themetoml for an example

name = "Temp Theme"
license = "MIT"
licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
description = ""
homepage = "http://example.com/"
tags = []
features = []
min_version = "0.41.0"

[author]
  name = ""
  homepage = ""

# If porting an existing theme
[original]
  name = ""
  homepage = ""
  repo = ""

Again, quite strait-forward, but hugo simplifies the boilerplate you need to write yourself, and I already start to love him for it.

hugo also generates three directories. You might recognize them from somewhere else.

.
├── archetypes
├── theme.toml
├── layouts
└── static

A theme is basically some of your sites’ files move to a separate folder, that you may distribute as a theme when coupled with a manifest. Great! Simple, easy, not requiring you to learn a new structure. I just find that smart and kind to the people that will use the software.

See ladies and gentlemen, this is how you write quality software: by both looking at it from your user standpoint, and by valuing their time to an obsession. Plainly, if your software does not help me save time, I would rather stick to pen and paper.

Creating a custom shortcode

hugo has that idea of shortcodes that are like many other CMSes, a small configurable template that you can use directly in your content files.

On several pages of this blog, I have put a picture, followed by a caption. This kind of content does not exist in Markdown (except if you’re writing HTML in Markdown), but can be achieved with a shortcode like the following:

{{< figure src="./wheels.jpg" alt="Old wooden wheels"
           caption="These wheels look fine to me! _— (not) Nikola Tesla_" >}}

I needed to customize blockquotes, so I created my own custom shortcode. Creating a shortcode is easy. You create an HTML file in the layouts/shortcodes directory of either your theme or your website.

I called mine callout.html, and here is the content of the file:

<blockquote>
    <p{{ with (.Get "type") }} class="{{ . }}"{{ end }}>
        {{ .Inner | markdownify }}
    </p>
</blockquote>

And this is how I use it in my content files:

{{< callout type="info" >}}
**_Edit:_** _April 15th, 2020 –_ Well, I just added basic syntax highlight
and line numbers as a side effect of moving to Hugo apparently. Yay!
{{< /callout >}}

Once again, I find this feature elegant and simple. hugo keeps on winning.

Adding our custom syntax highlighting theme

Last, I would like to speak about syntax highlighting. hugo ships with chroma, a Pygments inspired syntax highlighter for Go.

With that, it allows you to highlight the sourcecode embedded in your content files. The default theme is Monokai, and even though I own a license to Monokai Pro and daily use it on my IDE, it felt out of place on this website.

I thus decided to create my own theme, keeping everything to the bare minimum. After all, some syntax highlighting is better than no highlighting.

hugo generates the CSS for you, from one of the available themes for chroma with the following command:

hugo gen chromastyles --style=dracula > syntax.css

Change a few color values in the generated CSS, and you are good to go. This is how I created the highlight theme that you see on this website.

Try first, trust later

I tend to not trust right away the new tools I encounter. But still, I keep considering myself an early adopter of sorts. In order to stay productive, I counteract my eagerness to try new things with my obsession to spend my time wisely (read: not fixing early-adopters bugs).

Adopting hugo has been a pleasant experience. This article is the first one that is rendered directly by it. This will allow me to focus on content, rather than writing HTML, even though I will always dearly love doing that.

Whatever you do, always try your tools first, extensively. Once you have determined that they are a good fit for you, only then, experiment, break them, fix them. If you fix something, contribute back to your tool, may it be some sentences in the documentation or a feature that you needed.

It will make you feel good, it will help the others, and it will contribute to your experience as a software engineer.

If you use some tools regularly or are writing one yourself, I would happily take a look at it. You can ping me on Twitter.

A handful of tools

“We become what we behold. We shape our tools, and thereafter our tools shape us.” ― Marshall McLuhan