skip to main content

Reducing Workflow Load Facilitates Writing

published icon  |  category icon webdesign

Metadata stashed in Frontmatter, isn’t it great. A neat and simple way to add some context to your writing, be it tags, categories, or whatever. Don’t forget an appropriate subtitle. Or perhaps a featured image, akin to my fancy looking sound blaster posts. What I didn’t immediately realize, however, was that all that useless stuff that in my mind pleasures the reader does not pleasure me at all. Every time I have an idea for a blog post, I jot it down into my journal, but most of the time, it stays there.

Why? Because creating a new .md file where the text will live involves having to make up a subtitle or chasing after a fitting image. By then, my golden egg also known as the very fleeting thought will have lost its appeal. Still, I reasoned, a featured image is important, right? For the Twitter card and Open Graph metadata and all. Just look at how gorgeous a link share looks using the Twitter Card preview tool.

Automation to the rescue:

  • If there’s no subtitle (.Params.subtitle), take the summary an truncate it: {{ .Summary | truncate 50 }}
  • If there’s no featuerd image (.Params.image), take the first embedded image and treat it as such.

The first one was dead easy. RSS items do not have subtitles anyway. The second one turned out to be a bit more involving in Hugo:

  {{ $thumb := "some-default-logo.png" }}
  {{ if .Params.bigimg }}
    {{ $thumb = .Params.bigimg | absURL }}
  {{ else }}
      {{ $match := findRE `!\[(.*)\]\((.+).(jpg|png|gif)` .RawContent 1 }}
      {{ range $match }}
        {{ $relthumb := replaceRE `!\[(.*)\]\(` "" . }}
        {{ if hasPrefix $relthumb "/" }}
          {{ $thumb = printf "%s%s" .Site.BaseURL $relthumb }}
        {{ else }}
          {{ $thumb = printf "%s%s" .Permalink $relthumb }}
        {{ end }}
      {{ end }}
  {{ end }}
  <meta name="twitter:image" property="og:image" content="{{ $thumb }}" />

These tiny steps greatly reduce the hurdle I have to take every time I want to write something. In the same vein, I have removed the /notes section all together. Those few sentences, albeit also automatically generated via Mastodon, brought little new to the table, and I had to constantly watch out as to not overburden readers using RSS. It was also responsible for a convoluted subscribe page where visitors had to choose which feed to follow. Out it goes. I feel much relieved now.

Auto-generating game cards

Over at the sister blog Jefklak’s Retro Codex, the problem was even worse. For every game I wanted to write about, I had to fill in the following metadata:

  • Platform
  • Genre
  • Release year
  • Developer
  • How long to beat it
  • The box art image

This felt like driving around with your foot firmly placed on the break pedal. Genres were inconsistent and visitors could not click through to see other related games. But fetching the box art was the worst: going to DuckDuckGo/Google Images, deciding on a “good one”, converting, yaddayadda… I have written before on how I leverage the Npm package howlongtobeat to automatically grab the hours and howlong-ID. This metadata gets injected into the Frontmatter of the relevant posts: see jam-my-stack source. I simply extended that: it apparently came with an URL pointing to the box art! So, this was easy:

async function downloadThumbnail(url, id, dir) {
  if(url.startsWith('/')) {
    url = `${url}`
  console.log(`   --- downloading thumbnail ${url} of id ${id}...`)
  await pipeline(,

I’m not exactly stealing anything from Howlongtobeat here: the copyright holders are the game developers. Not all URLs are .jpg files though, but they’re all images, and for the moment I’m too lazy to check the extension, as now all I have to do in Hugo is:

  {{ if .Params.howlongtobeat_id }}
    {{ $thumb = printf "%s%d%s" "img/hltb/" .Params.howlongtobeat_id ".jpg" }}
  {{ end }}

Filling in the platform does not require a big cognitive load: I think I can manage to remember on which console I played the game. I used that metadata to generate a ribbon in the sidebar. Other metadata such as the release year and developer could be lifted from the Moby Games API, although for the moment it’s still manual labor. The end result doesn’t look too shabby:

The sidebar at Jefklak's Codex.

Now that I am writing this, another obvious one I almost missed becomes visible: including images. The above image is included using the following Markdown syntax: ![](../jefklakscodexsidebar.jpg "The sidebar at Jefklak's Codex."). It might not be immediate apparent, but the relative file path to a current blog post is Always And Forever ../. That is because I keep my directory structure in content and the static dir in sync. This blog post is committed under brainbaking/content/post/2021/07/. The image is committed under brainbaking/static/post/2021/07/. Having to fill in the date reminds one of the current year and month, so no problem there.

I also terminated my Gemini server and threw out all related source code. It was good fun—until the added complexity to the site codebase started to get on my nerves. I now fully understand why many people get rid of IndieWeb stuff. K.I.S.S.!

Reduce Complexity. Write more. That’s the message I want you to take away!

Update 4 July 2021: Peter e-mailed me mentioning his workflow that helped him up the writing ante: e-mail! He writes many blog posts on a smartphone by e-mailing it, and a script picks up the message, converts it to the appropriate format, and posts it onto his Drupal blog. Brilliant, although I wouldn’t dare to type more than a few sentences on a smartphone…

tags icon hugo blogging website writing

I'm Wouter Groeneveld, a Brain Baker, and I love the smell of freshly baked thoughts (and bread) in the morning. I sometimes convince others to bake their brain (and bread) too.

If you found this article amusing and/or helpful, you can support me via PayPal or Ko-Fi. I also like to hear your feedback via Mastodon or e-mail. Thanks!