Website rewrite

August 25, 2018*

*Last modified 10-Nov-19

Tags: meta

I decided to redo my website using Hugo (before I was using Jekyll). Both are static site generators: you write in Markdown, a simple clean formatting language, and it generates HTML webpages following a consistent format. It’s great because the generation only has to occur once after the Markdown is written, and nothing active has to happen for each user of the website (unlike a so-called dynamic website). This reduces costs, increases reliability, and improves securitythe user needs very little access to the server hosting the webpages in a static site

. The problem I was having with Jekyll was that it was taking about 40 seconds to generate the site, which meant that if I wanted to make a small change and see how it looked, I had to wait for it to generate to see the result (like a long LaTeX compilation). Hugo is super fast; my site takes less than a second to generate fully now.

While you’re still reading, and before I get into the details of why I switched and how the site is setup now, one thing this means is I can use the very cool git info feature which gives me last modified dates taken from the git repository in which the blog lives. I put these dates all over the place, because

  1. I think it’s cool
  2. Occasionally one finds a page which they really want to know if it’s up-to-date, and it can be hard to tell.

These dates only change when content of the page changes, not the literal file you’re seeing. That’s useful, because the literal file could change for a bunch of other reasons:

So these last modified dates should be accurate and hopefully useful. Additionally, if the “official” date I type into the frontmatter of a blog post (which usually corresponds to when I start writing it, or when I post it) is different by at least a day from this “last modified” date, then my website code adds an asterisk and puts the last modified date too. So every older blog post will have this, because by adding them to the new site, I changed this “last modified” timestamp, which will thus differ from their original posting date. I’m ok with that, because I also did modify all of them; the way I typed math on the old site was via these terrible {% math %} commands, whereas now I just use $ like in LaTeX. So I at least had to change that, and often fixed up the wording or changed the content a bit as I was reading through them. So many of them were legitimately modified on the day that the asterisked “last modified” timestamp says.

Turning back to Hugo, while the main reason I wanted to change was generation speed, it turns out that it has a lot of nice features that make the things I was trying to do much simpler than with Jekyll. For example, the way I made HTML solutions for the example sheets for the QIT course was a little complicated; I wrote a single markdown file for the solutions, then wrote a script to split it into separate files for each exercise and solution, which I compiled to HTML using pandoc. Then the page for Example Sheet 3, for example, works by paginating over these separate files. Why not just have one file? Well, that ability to paginate for one. Also, separate files makes it easy to make the search index, and it relates to other ideas I want to explore about compartmentalizing information.

But to do this in Jekyll required making a new “category” for each example sheet, which requires a new top-level folder, a change in the site-wide configuration file, etc. In contrast, Hugo has “branch bundles” which allow one to do this easilyWell, once one gets the hang of how to do things in Hugo.

. These are a type of “page bundle” which allow you to keep resources associated to a page (like images, files, etc) in the same folder as the text of the page, which turns out to be pretty convenientIn my old blog, I had to use a top-level /static directory to put all the images, etc.

.

Moreover, at the time I originally made each different type of page, I was focussed on the immediate need and not the overall picture. Thus, a rewrite allowed me to think over more what kinds of things I really wanted and how to implement them.

I’ve found Hugo a bit strange at first. It works by a system of templatesAKA layouts

that override each other, kind of like CSS. Ignoring “taxonomies” for nowwhich I’m only using fairly minimally, for tags

, there are two types of pages: “sections” AKA “list pages”, and “pages” AKA “single pages.” The page /blog/ is a “list page”, and its purpose is to list the blog posts. Below that in the hierarchy are the individual blog posts, which are single pages. There’s a default file /layouts/_defaults/list.html which provides a template for list pages, but this can be overridden by layouts/blog/list.html which is for list pages under the blog heading. Likewise, there is a default “single page” template under /layouts/_defaults/single.html, but for blog posts, this can be overridden by layouts/blog/single.html. Moreover, in the frontmatter of a particular page, you can explicitly set the layout to something else, to have custom layouts for particular pages.

What’s the big deal about templates? The most obvious thing is that they provide a uniform template so all the blog posts look the same; for mine, they load in the right CSS to make the sidebar for the sidenotes, load KaTeX for parsing math, etc. But the other important thing is that in Hugo, the templatesand for the most part, not the actual pages themselves

have access to programmatic functions and variables. So a template for a list page has access to the equivalent of for loopsrange in Hugo

to loop over the pages and show an excerpt from them, etc.. This is exactly what I do for the example sheets: the page you see is secretly a list page, which is listing the “pages” below it, which are the individual problems and solutions. The way it lists them is it just spits out the full contents of the page.

So most the process of making of my website is just creating the right hierarchy of template pages under /layouts in order for each page of the website to grab the right template for its particular useand writing those templates of course

.

Hugo also has partials, which are just parts of templates abstracted out so you can reuse them in different templates, and views, which are basically alternate ways to present some of the content of a page. For example, my blog posts have a view which is just a bullet point with the date, title, and a brief description (taken from the frontmatter of the post itself), which is what the list page /blog/ renders to make its list.

I think Hugo has a really nice combination of flexibility (overriding templates, alternate views, etc), along with enough rigidity to help ensure it doesn’t become too much of a mess. What rigidity is that? Well, you only have access to programmatic tools in the templates and not in the text of the posts. As I understand it, this is meant to be a separation of the logici.e. code

of the website from the content, to encourage a uniformity in how the site operates despite varying content.

I’m happy with the new system, and think it will make adding new types of pages, along with more things like example sheets, much easier in the future.

Some more details for the curious: