The previous post detailed how I came to choose Hugo as a static CMS for my personal website.
Nine months in, how’s Hugo travelling?
Surprisingly well in fact. Lots to learn along the way. But no roadblocks so far. That’s a big plus and somewhat unusual for a CMS. Hugo is proving a remarkably flexible and deep piece of work.
The following are some of Hugo’s features I’ve found particularly useful.
Overridable Blocks in baseof.html
Object-oriented programming languages introduced the idea of inheritance, whereby a more generalised piece of code can be selectively overridden by a more specific piece of code. This is achieved through the mechanism of a hierarchy of “classes” which contain small pieces of functionality called “methods” or “functions”. The idea is that you can write code to solve a problem in a general way and then you or someone else can override parts of that code specific to a particular need, without changing the more generalised code.
We are familiar with this idea in programming languages, but not with markup languages.
The facility to decompose a complex html template into smaller pieces, often called “partials”, is found in most web application frameworks. But the ability to “reach inside” a template and replace or override various pieces of the template in different ways for different pages is generally not possible.
One brilliant invention that explores the possibilities of this idea in great depth is the DRYML markup language, about which I will write some more in another post.
Here we are discussing Hugo and we find that the Go Templating Language used by Hugo does allow a simple form of such overriding:
You can enclose any part of the baseof.html template in a named BLOCK declaration.
Blocks can be nested inside other blocks.
Subtemplates can override the content of any of these blocks to suit the needs of a particular kind of page (e.g. pages in a blog might require slightly different structure from a standard page).
There are limitations. Subtemplates can override only one level deep — i.e you can’t have arbitrarily deep hierarchies of subtemplates overriding pieces of their ancestor templates. One level only.
Despite the simplicity and limitations of this particular implementation of view inheritance, it is difficult to convey the power of this concept and how much it reduces the proliferation of duplicate view code which so often occurs.
Hugo includes support for user-defined groupings of content called taxonomies. Taxonomies are classifications of logical relationships between content.
A familiar example of a taxonomy is the “tags” associated with blog posts. In Hugo you use a taxonomy to implement tags for a blog. Hugo will automatically create a page listing all the taxonomy terms (i.e. all the tags used in the blog) and individual pages with lists of blog posts associated with each term. And remember, this is all being done in a statically rendered website, so these taxonomy pages are not created dynamically as they would be in a dynamic CMS.
I found Hugo’s taxonomies made sense after some experimentation and I’ve now added tags to all my blogs.
Using Code in Templates to Avoid Proliferation of Templates
I mentioned how you can use blocks to override parts of a base template. That’s one form of customisation of a generic template for a specific context.
Another useful form of customisation the inclusion of code in a template. The Go Templating Language is quite rich and Hugo builds on it with an extensive library of variables and functions which you can reference in a template to insert page-specific data or to conditionally include or exclude content.
In this way you can make a generic template fulfil the needs of a variety of contexts and thus eliminate the need to proliferate separate templates for each context which differ only in minor details.
Another way Hugo makes your task easier.
Very, Very Fast Site Rendering
Go is a compiled language which executes quickly. Hugo can rapidly render a site into a set of html pages. For a site of a few dozen pages, rendering time on my Macbook Pro is an astonishingly low 0.3 seconds or less. In that time Hugo is building all the pages, computing view overrides, executing view code, translating Markdown to HTML, and writing output files, including copying of all static resource files (images, css, etc). Wow!
Built-In Local http Server for Testing
As icing on the cake, Hugo has a built-in local http development server which you can fire up with the command
hugo server. This server renders pages dynamically (i.e. in response to a browser request) and includes code which forces a browser refresh whenever the page being viewed or any of its dependencies is modified. Brilliant.
It’s hard to find anything nasty to say about Hugo. It’s one of those tools which you look forward to using and working with. In fact creating a website in Hugo is fun. What more can I say.