en no

Nocturne.no

Devblog
Python tutorial

Setting up a Blog - Part 3

A New Beginning

Since the last blog post, I have reconsiders several parts of my life. Perhaps not most importantly, but still most relevant for this post, was to stop home baking my blog setup and buy/steal one fresh off the shelf of someone who knew what they were doing.

Postmortem

Before I introduce the replacement for my exotic React-but-lazy-site setup, let me give it a few words in its memory.

I could have continued with it. I could have let it work as it did, as it was already proven to do the things I wanted. However, the site was quite janky, even in its prime. The language selection in particular never quite did what it should and looked more shady than modern web design allows for. Second, it was a rather slow solution. Checks out, since it downloaded the React library on every page, and bypassed all kinds of caching and optimizations that work out-of-the-box when the browser receives an HTML file directly.

The years of experience in software deveoplement since the site’s birth has made me realize that by making the site myself, I am solving problems that many people have solved before me, only they did it better. Nowadays I find it much more frustrating when my ideas are easy to formulate to humans, but hard to formulate to computers. Blogs are easy concepts to understand, but setting it up in practice using home-grown methods is annoyingly hard.

I don’t regret setting up the blog the way I did back then, I did learn a lot. However, I no longer want to learn how to set up a blog, but rather put out some useful(?) content on the Internet for all to see. And to that end, an exotic but clumsy blog experience is an obstacle.

With that said, enter

Hugo

Hugo is a static site generator for creating.. Static sites. As it happens, blogs are a prime example of static sites, and so it caught my attention. Hugo promises a lot, honestly more than I would need/want, but if you want bread with nothing but flour, water and oil, you may have to bake it yourself since all reasonable bakers will refuse. And I have already concluded that it’s not worth it.

The research leading up to the decision on framework was not very deep. It is free, open-source, has an active community and doesn’t seem like it’s trying to lure me into an ecosystem where the real features are paid (looking at you, Ghost).

The Good

  • Hugo has a large ecosystem with support for many different third-party features. Comments (woops, they didn’t survive the migration) and metrics is probably something I’ll pick up sooner or later
  • Translations work. I’ll say that it’s not as smooth for my purposes as I’d like (more on that later), but it does work, unlike my previous attempt
  • Markdown 👌 Writing HTML or React gives quite a lot of flexibility, but when 99% of what I write is standard English/Norwegian, it doesn’t give much of an advantage. It is mostly just a source of annoyance when I need italics, bold or preformatted text. Besides, Hugo supports HTML embedded in the Markdown, so there’s really not much to complain about
  • Static pages. They’re small, fast, reliable and plays nice with the browser. Simplicity, for I am but a simple man

The Bad

Now, nothing is perfect - and much of the following is outright unfair criticism against a general-purpose site generator like Hugo. But, as a simple man with his flour-, water- and oil-filled bread, things could always suit me more:

  • Translations can be finnicky - this can naturally be attributed to my eccentric needs (I want to display all posts, even if not available in the current language), but nevertheless something I struggled with to get right. I’ll give Hugo kudos for at least allowing me to nail down this use case, even if it seemingly wasn’t part of their plan.
  • Dynamic content (i.e. Javascript, NPM, canvases) are second-class. Very fair, “static site generator” doesn’t scream “we will whole-heartedly support all your desired dynamic content”. And also fair, I have not yet needed this in my toolkit for the content thus far. But there is always the nagging question “what if”? Maybe I want to post about WebGPU with examples? Maybe I want to indulge in criticism of society with an addictive game? Luckily, t’s by no means impossible, but it requires some manual plumbing.
  • The templating language. Which leads me to

The Ugly

Hugo gives a great flexibility through its templating capabilities, no question about that. Nevertheless, it feels like there could be many ways to do this better.

The templating language is based on the Go packages text/template and html/template, which has syntax akin to this:

{{ if expression }}
<h1>The expression evaluated to true</h1>
{{ else }}
<h1> The expression was not true</h1>
{{ end }}

For those who knows some programming, it may be self-evident what is going on here - and I can respect how simply the templating language is interleaved with the meaty HTML-code. The syntax is not what I would call elegant, but I won’t deny that it is well suited for simple cases like this.

Although I am a sucker for simplicity, I am even more of a sucker for control. And I will wrestle my way to the goal regardless of what is intended or practical. Just to illustrate, here is the code I ended up with for computing the list of posts, and finding out whether they have a language that matches the currently active one:

{{ $pageList := slice }}
{{ range hugo.Sites }}
  {{ range .Pages }}
    {{ $pageList = append . $pageList }}
  {{ end }}
{{ end }}

{{ $relevantPages := sort (where (where $pageList "Section" .section) "Kind" "page") "Weight" }}

{{ $list := slice }}

{{ range $relevantPages }}
{{ $allTranslations := .AllTranslations }}
  {{ $foundRelevantLanguage := false }}
  {{ range $allTranslations }}
    {{ if (eq .Language site.Language) }}
      {{ $foundRelevantLanguage = . }}
    {{ end }}
  {{ end }}
{{ if $foundRelevantLanguage }}
    {{ if (eq .Language site.Language) }}
{{ $list = append $foundRelevantLanguage $list }}
{{ end }}
  {{ else }}
    {{ if (eq . (index .AllTranslations 0) ) }}
      {{ $list = append . $list  }}
    {{ end }}
  {{ end }}
{{ end }}
{{ return $list }}

Without going into detail on how this works, it may be evident that this is neither what I would call elegant or practical at all.

I am no expert, so perhaps this could have been done in an easier way. Perhaps it’s also my fault for being too inflexible about my plans, but I am very much against the thought of giving up my ideas because of restrictions in my tools.

I will give props to Hugo for actually allowing me to work around this myself, but I really wish there was a selection of better suited-languages at disposal. This would likely be a third of the size, and a lot easier to understand, if I was allowed to use e.g. Python.

Ending Remarks

Above, I have put more emphasis on my negative impressions with Hugo, than the positive ones. But truth is that this site is in a better shape than ever before because of Hugo, and I do not intend to sound ungrateful - my use cases are just a little on the outside of Hugo’s intended scope, and I am a stubborn old man in all my work. The resistance against vendor lock-in also stands strong with me.

Despite all of that, I am still certain that I have made a good choice.


HÃ¥kon Flatval
Created with Hugo, theme based on nostyleplease.