How to Liveblog on a Static Site, Or: A Thoughtless Kludge

technical detailswebsite designprogramminggetzola

Okay, so I recently decided to make a blog post that automatically updated. This turns out to be super, super easy to do with my current setup, which uses the Zola toolkit to generate a static website from templates and markdown files, as well as Netlify, which automatically redeploys my site whenever I push a change to the git repo.

My approach took me five minutes to write, and it definitely works. It is completely lightweight and nice on my end. It is not completely lightweight and nice on my webhost's end, and I would recommend using it extremely sparingly, if at all.

Quick refresher on my hosting setup

My website is built using a static website generator called Zola. It's a CLI tool that takes directories of templates and content and builds a website.

My webhost is a service called Zola, which automatically updates my site with a Zola build every time there is a change in the main branch of a git repository.

My approach to liveblogging was to:

  1. Get the webpage to automatically refresh at a set interval.
  2. Get the website to automatically update at a set interval if I had changed the post.
  3. Hope the above two things line up relatively well.

I'll quickly run through steps 1 and 2, and leave you to contemplate where the problems might lie. :)

Getting the page to automatically refresh

There are a few methods that can be used to get a browser to reload a page. Javascript is one, but it is inefficient and frowned upon if you're refreshing an entire page rather than a portion of it (or a DOM object.)

The most accepted way to refresh a whole webpage at a set interval is to add a specific meta element to the head element on the webpage:

For example:

<meta http-equiv="refresh" content="180">

will refresh the page at a 60 second interval.

I obviously don't want this to be the behavior for every page on my website, but I need to insert this tag into "head" which is present in my template for index.html. On the zola side, the html template refernces variables in the header of the markdown, so I can just add something there to switch this behavior on.

{% if page.extra.refresh %}
  <meta http-equiv="refresh" content="{{page.extra.refresh}}">
{% endif %}

In this case, I assume page.extra.refresh is an integer, representing the interval at which this page should refresh.

In Zola's header in my markdown files, all I need to do is add an [extra] section with refresh = a number and the page shall refresh. Otherwise, this element is not inserted into head, and normal behavior prevails.

Getting my laptop to automatically push changes.

I love writing bash scripts, so I wrote one to update my website.

The algorithm is pretty simple. Let's write it out:

  • Until the user terminates the script (while true)
    • Make a copy of the post we are live updating.
    • Sleep for a certain interval
    • Check if the post has new, saved changes... if so:
      • Add the new version to our git
      • Make a commit
      • Push

A simpler approach would be to just automatically add, commit, and push at every interval, but as I am billed if I exceed a certain number of build minutes, this seems like an easy way to waste compute resources.

Here's my actual script:

set -euo pipefail

CACHED_POST="/tmp/$(basename $POST).old"

while [[ true ]]; do
	echo "Sleeping"
	sleep "$REFRESH_RATE"s
	echo "Checking"
	if [[ "$(diff $POST $CACHED_POST)" != "" ]]; then
		git add $POST
		git commit -m "Automatically committed changes to \"$POST\""
		git push

With those two things in combo, you get a live post.

...but at what cost?

I think I probably spelled out the issue pretty clearly when I outlined my approach.

I am updating a single page of content, but on the server side, I am regenerating the entire website.

From what I can tell happens on the Netlify side of things, every time I push to my git repo, it enters a queue. A virtual machine is deployed, runs the Zola CLI over my files, and generates the website. Their servers then provide this new version to the user.

Regenerating my entire website to add a paragraph to a blogpost is absurdly inefficient.

And, though everything is lightweight and nice on my side, on the server side, I wound up with multiple builds in the queue, and burned through a decent chunk of compute quota.

So, next time, please think of a better solution, Steve.