Website redesign

Having a tech-adjacent blog means that blog maintenance becomes a topic in itself…

Domain switch, redirects

I have thought of getting an own domain and becoming independent from GitHub Pages hosting for a while. Purchasing the domain and the most basic webhosting (more than enough for a static website) was pretty much a non-story. Gracefully shutting down the old website gave me a bit to think about.

I could have just removed the old content, replaced the homepage with a short notice, and updated links in all my bios. I doubt the blog sees many visitors, if any, so the address change should not matter. However, I like the idea of information persistence 1. Since at least some of the things I wrote might have some value as a reference, and links could theoretically exist somewhere, pulling the plug entirely did not seem right.

Redirects are a standard solution to the problem. The most standard way would be a 301 Moved Permanently HTTP response, however, it needs to be set in the server configuration, which is not possible with GitHub pages. The second best solution is a meta refresh redirect, i.e. setting the following in the HTML head:

  <meta http-equiv="refresh" content="0; url=https://example.com/">

This would require the old page to be loaded first, but it would then cause an instant reload, from the new URL. Although this kind of a redirect is a strong signal that the site moved, it also seems advisable (or at least won't hurt) to set a canonical URL for each page, giving search engines an additional hint:

  <link rel="canonical" href="http://example.com">

To preserve the links for all posts, the above needs to be done for each page. Thankfully, with static site generators like Hugo this requires minimal intervention. It is enough to override the theme's template containing the header. Something like the following should take care of all the posts and the homepage (it can be applied to other pages, allowing some flexibility if sections are removed after use):

  {{- if eq .Type "posts"}}
  <meta http-equiv="refresh" content="0; URL='https://example.com{{ .RelPermalink }}'" />
  <link rel="canonical" href="https://example.com{{ .RelPermalink }}" />
  {{- else if eq .RelPermalink "/"}}
  <meta http-equiv="refresh" content="0; URL='https://example.com'" />
  <link rel="canonical" href="https://example.com" />
  {{- end -}}

Based on:

Hugo themes

Hermit

One of the things which drew me to Hugo was the quality of the available themes. I started with Hermit. However, Hugo moves at a rather rapid pace, and my page with the now-unmaintained theme stopped building at some point 2. There is a maintained fork, Hermit - V2, but it isn't fully plug-and-play (some configuration options are changed). This encouraged me to look further and consider a redesign…

Complexity increases

For something as "simple" (in its purpose) as a static site generator, Hugo does evolve at speed. I found out that the recommended way of installing themes is now through Hugo modules, which seem to be a wrapper for Git submodules combined with Go package / dependency management (don't quote me on this, I only gave the docs a cursory read). Thankfully, plain Git submodules still work (and so does symlinking).

Unfortunately, I feel that there is some bloat in the theming space. Some themes require an additional installation of JavaScript libraries with npm, some ship with rather heavy assets – which is not what I want. Although, in fairness, there are also many which boast minimalism.

Risotto in the meantime

One of the themes which caught my eye was risotto. Terminal aesthetics, plain HTML + CSS, and a really nice system of built-in base16 color schemes are its definite strong points in my eyes. It became my chosen theme for a few weeks.

There were, however, a few things which I didn't fully enjoy, like the lack of extra line spacing under headings. I looked under the hood and the theme seemed nicely tweakable, but instead of making tweaks it seemed more fun to try and start from scratch…

Writing my own

I had been thinking about writing my own Hugo theme from scratch, and while making all the changes above the time seemed better than ever. I wanted to be able to control typography and color scheme, and I also wanted to take a closer look at Hugo internals. Thankfully, Hugo docs are rather good, and I was able to hack together something which met my vision:

  • Restrained design.
  • Catppuccin colors.
  • Vollkorn (serif), Anonymous Pro (monospace) fonts.
  • Minimal technology: pure HTML + (s)CSS, no JavaScript.
  • Self-hosting: fonts and icons are bundled (OFL / CC-BY / MIT license), no CDNs and Google Fonts.
  • Works-for-me project: not covering all of Hugo possibilities.

I do not have a repository to share since I am currently rethinking my relationship with GitHub (The world’s leading AI-powered developer platform), but I will try to remember to update the post with a link when I settle on something.

Finding Hugo limitations

Org mode and Hugo

Another thing which I really like about Hugo is that it supports Org mode out of the box. Well, mostly. It has worked for me for a long time and still does, but recently I ran into a few limitations.

While Org mode is well documented, its reference implementation is in Emacs Lisp. Hugo does not implement its own parser; instead, it relies on a third-party library go-org, which aims to implement a subset of Org mode according to the 80/20 rule, and is not being particularly tailored for Hugo (which is a perfectly reasonable approach from its developer).

This meant, however, that on one unlucky day I discovered two unsupported features. First, it is not possible to toggle line numbers for a code block, as switches are not interpreted (Org native example, with starting line number set: #+BEGIN_SRC emacs-lisp -n 20). Second, .webp images were not being recognized as such (images are inserted as regular links, and the parser decides what to do with them based on file extensions). The latter has now been fixed.

Interestingly, there is Org-hugo, an Emacs package providing an export backend which translates Org to Hugo Markdown. However, going Org → Markdown → HTML seems like an overly complicated process (at least when compared to just calling Hugo).

To be clear, I consider these limitations minor, and I will continue using Org mode with Hugo, but learning about these limitations was interesting.

Org, Beyond Hugo?

While exploring the topic, I was reminded how good the plain Org HTML export (C-c C-e h h) looks, with its black-on-white, 60 em wide, nicely spaced content. It can also provide code block syntax coloring, but the default behaviour is to use colors from the Emacs theme – which looks terrible when using a dark editor theme and keeping the default white HTML background.

The CSS markup is documented, so I believe it should be possible to style the output at will (I also found at least one alternate stylesheet), but that seems like a bit of work. I had a brief look, but the code blocks seemed to be the biggest obstacle (I think it is either theme colors, or external processors 3).

And even if I could see myself exporting each page manually (my website is simple after all), Hugo does bring more features on top. Generating a list of posts is the obvious one, but Hugo also generates lists of tags with its taxonomies feature. Really neat, and it requires very little work to template for.

The list of Org-specific site generators is sadly filled with "unmaintained". The most interesting project is probably lazyblorg (generator behind https://karl-voit.at/ which I already linked to in one of the footnotes), but it seems to be tailored to a workflow slightly different than mine.

Finally, I came upon hakyll, written in Haskell (that would make for a double niche combination), interesting in that it delegates format conversion to pandoc ("write your content in whatever format you prefer"). Pandoc is solid, but I was always a bit hesitant to go into pandoc templating.

Interesting possibilities, but I will be staying with Hugo for a while now – changing a framework could be a fun exercise, but not a small one.


1

I also share the feeling that the blogosphere can currently provide much better persistence than online forums. Karl Voit expresses the idea at length: Don't Contribute Anything Relevant in Web Forums Like Reddit.

2

Somewhere between Hugo versions 0.111 and 0.121 (keeping the website in Git helps keep track). I use Debian (at work) and Fedora (privately). New and deprecated Hugo features can lead to funny situations when one theme is too old to work on Fedora and another is too modern to work on Debian…

3

Maybe this is the way to do it, with temporary files and an external process called from an Emacs Lisp function? https://linevi.ch/en/org-pygments.html