đź’Ą From Hugo to Zola

Obligatory "I've moved to a different static-site-generator and want to tell everyone about it!" post.


#static-site-generator #rust

Why Are We Here Again?

While I outlined my earlier selection of Hugo as the static-site-generator of choice in a previous post, it's finally time to admit that Go and I aren't getting on. It's not you, it's me (except it's totally you.)

And it's more than a little Rust, to be honest.

So, having failed miserably to write anything actually worth publishing (which does sound like rather a grandious overestimation of my previous posts) in over eighteen months, it's time to do what we all do and change the underlying framework so I can hack around and then then write about it in a weird, meta fashion.

Zola, I Missed You (Sort of.)

Back to Zola! My initial choice first time around, before becoming inexplicably over-optimistic regarding Go, I've been toying with the shift for far too long so back we went…

It was a, shall we say, inauspicious start.

I followed the First Steps with Zola documentation to the letter, I swear.

I ran zola init…, created my first.md and second.md blog posts, populated my templates but…it didn't work.

Running zola serve span up the local webserver, rendering /blogs; visiting /blogs/first showed the contents of the relevant post perfectly well. But links to the latter were not appearing in the former.

Specifically, in this bit of the blog.html content:

  {% for page in section.pages %}
  <li><a href="{{ page.permalink | safe }}">{{ page.title }}</a></li>
  {% endfor %}

…the section.pages variable was empty. Displaying the contents with {{ section.pages }} gave nothing more than a disheartening [].

I'd love to say I got to the bottom of it but alas, no. After repeated copy-and-pastes of the documentation my list of blogs remained empty. I'll probably repeat the exercise and either log a bug or confirm my ineptitude when I'm done documenting the latter here.

“If at first you don’t succeed, try, try again. And then give up. There’s no sense being a damn fool about it.”

Taking a different approach and stripping back the metadata in each file, Zola thankfully started complaining about missing templates and the resulting errors largely hand-held me through the necessary additions.

The standard templates are documented in the relevant section of the documentation and, after adding those (rather than those described in the Overview documentation), voilĂ : our section began presenting the expected list of pages.

To implement a site structurally like its predecessor, the only templates specifically required were index.html (to cover the home-page; functionally this is a section page but as we've no other sections, the main page fulfils that role) and page.html (to cover the individual blog posts.)

To Theme or Not to Theme?

I will not use ZOLA.386; I will not use ZOLA.386…

I really want to use ZOLA.386.

I'll admit that the themes available for Zola aren't as many an multifarious as those of Hugo but they nevertheless cover most simple requirements.

That said, I opted to implement the templates from scratch manually using Bootstrap 5. More specifically, using one of the Bootswatch themes: Sketchy. Hopefully, that should be clear to anyone reading this. Unless I've gone and changed my mind again.

Partly, I was intrigued as to how simple it would be (spoilers: quite simple) and how quickly I could replace the existing site.

I've been discussing the possibility of replacing an existing Wordpress site elsewhere with a GitHub-hosted static site Ă  la this one and wanted a feel for the effort involved (spoilers: not a lot.)

The Actual Hard Work

Having decided to implement the templates and now being aware of the specific files required, the first step was to move the old blog posts into this directory structure and modify as necessary.

Beyond modifying the necessary metadata in each post's header, there wasn't actually much more required.

For instance, Hugo favours:

title: "🔓 Hack the Shed"
date: 2019-06-19T20:19:51+01:00
description: "Drink all the booze; hack all the things."
tags: ["security", "owasp"]
categories: ["security"]

…while the same file in Zola looks like:

title = "🔓 Hack the Shed"
date = 2019-06-19
description = "Drink all the booze; hack all the things."

tags = ["security", "owasp"]
categories = ["security"]

The [taxonomies] section is perhaps the biggest change: the tags and categories aren't used by default in Zola and instead need to be configured. They are, however, arguably more versatile.

They need to be explicitly added in the configuration file, config.toml:

taxonomies = [
    {name = "tags", rss = true},
    {name = "categories", rss = true},

As per Zola's documentation, they can largely be any grouping needed but the previous taxonomies were left for now (if it ain't broke…)

So we have:

That's actually it. Teething issues with Zola aside, the actual generation of the final site once the content was migrated and templates written (largely based on the numerous provided Bootstrap samples), was as simple as zola build.

Now just to put that newly-generated static content somewhere…

Fork It

The previous mechanism for deployment—and one I'd hoped to retain in this version—was via use of a Git submodule referencing an entirely separate, public GitHub repo. to which the static content can be pushed; the Zola code can therefore be isolated in a private repo. for tinkering.

Although Zola seemingly recommends submodules for themes it seems the developers are not fans for their use as part of the deployment process. The public folder wherein the generated content is created by default, is nuked on each zola build.

Arguably for familiarity's sake (and arguably to keep things progressing at a fair pace), I opted to create a fork and altered the cleanup stage of the site sub-crate to:

Thankfully Zola already makes use of walkdir so there were zero new dependencies. And it works.

And look at that, I even got a blog post out of it.