đź’Ą From Hugo to Zola
Obligatory "I've moved to a different static-site-generator and want to tell everyone about it!" post.
2021-06-12
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.
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."
[taxonomies]
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:
- a handful of HTML templates files, using Bootstrap.
- the previous blog posts from the old site.
- errrr…profit?
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:
- retain the root (i.e.
public
) folder. - ignore hidden files (i.e. the
.git
folder.) - delete all other folders therein as per existing behaviour.
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.