Hello from my blog

Blogging about setting up my blog: my experiences with the Hugo static site generator and the challenges that come from trying to minimize work/bloat sent to the client

September 12, 2018

It’s a static site

I ran a few WordPress sites back in high school and I was never very thrilled by the experience. The site was kind of slow, unless you installed one of those random “WordPress caching” plugins that usually did their job, but sometimes broke things. Every half a year or so, I’d update my WordPress installation (the alternative was facing exposure to unpatched exploits) and pray my plugins worked and the formatting didn’t break. I’d try to tweak the look of our site, but there was so much CSS and so many plugins that I had a hard time figuring out what files I needed to touch. And eventually one of my sites got hacked, probably due to some PHP/WordPress vulnerability.

I’m sure WordPress has gotten better since then, but when I decided to start a blog earlier this year, I knew I wanted to make it a static site. I simply didn’t want the additional features that server-side code offers; I had always preferred Git to a content management system, and leaving the problem of comments and comment spam to a third party (like Disqus) seemed like a good idea anyways. Plus, static sites are simple to host, fast, secure, and easy to configure.

So, my site is powered by the Hugo static site generator, and is hosted on GitHub pages. And not only is my site static; it’s also:

A zero-JavaScript site (for now)

I’m also proud to say that this site displays both \LaTeX and

1
2
import os
print("code")

despite using zero JavaScript. I guess this is maybe not so impressive considering modern HTML+CSS is turing complete but still, pretty neat. (No more waiting 10 seconds for MathJax to render!) I’ll probably add Google Analytics and Disqus in the near future, so the site will have some JavaScript, but even then, the entire site (minus comments) will render perfectly even on a browser with JavaScript disabled.

Here’s my experience with making this happen:

Code highlighting

This was the easy one; Hugo, out-of-the-box, runs Chroma during the build step. This turns markdown code blocks directly into properly styled HTML, obviating the need for something like highlight.js that runs client-side upon page load. I only encountered one minor inconvenience: the theme I chose (Cactus) included another implementation of code highlighting, done client-side, that both added bloat to the site and interfered with Chroma’s styling. It took me around half an hour to remove this “feature” from the theme.

LaTeX

Getting server-side LaTeX rendering was much more cumbersome, because the tools I needed were node.js-based and therefore didn’t play well with the Hugo ecosystem (which is basically a single executable written in Go). The mathjax-node-page package essentially emulates (on the server) the processing that would’ve been done client-side by the MathJax library, which is exactly what I needed. Unfortunately, I couldn’t find any post-build hook feature in Hugo, so I had no way of calling this library after Hugo was done with its part of the build. Currently I’m working around this with the following monstrosity of a Makefile:

1
2
3
build:
	hugo
	find public/ -name "*.html" | xargs -P 16 -I {} sh -c "npx mjpage < {} > {}.2; mv {}.2 {}"

Where the second line finds all HTML files from the Hugo output and runs mathjax-node-page on them…highly inefficient. Thankfully it parallelizes well (note the -P 16 flag passed to xargs) so what would’ve taken 20 seconds serially now only takes around 2. Meanwhile the hugo step currently takes around 40ms, so it’s about 2% of the overall build time…definitely not taking advantage of Hugo’s fast builds right now. Someday I might try to write a fancier Makefile that only runs mathjax-node-page on HTML files that have been changed, but for now I think a 2 second build is fine.