go /

How this site works

.md | permalink | Published on November 10, 2019

Like lots of folk on the internet, I have a website that's powered by a static site generator and hosted somewhere on the GitHub.

This post serves two functions:

  1. Actually getting something that's text onto the internet.

  2. Some self documentation on how this works, because as I've gone back to this over the past few months to add some polish, or just, make any kind of changes, I've been surprised by things that I've done for myself in the past.

Here are some immediately relevant links:

Branches, or the-details vs master

Unlike the default github's repo-specific pages, you cannot use a gh-pages branch to host a site for a user. You end up having to create a repository called <you>.github.io, and whatever is on the master branch will end up getting served to the world. (source)

Luckily, we can set a default branch for the actual editing of the code and content, and for some reason, I decided to call it the-details. Possibly because naming is hard.


A consequence here is that the README.md cannot, by default sit in the master branch, explaining that you can't edit any content in that branch itself.

I have a workaround set up that symlinks the file from the static/ directory to ./, which means that it will always get deployed to master (and the site) as I push changes to it.

Update as of November 14th: This is also being used to keep track of the CNAME file that GitHub looks for when setting up your own personal hosting.

$ cd static && ls -l
lrwxr-xr-x   1 stanistan  staff     8B Nov 14 09:33 CNAME@ -> ../CNAME
lrwxr-xr-x   1 stanistan  staff    12B Nov 14 09:33 README.md@ -> ../README.md

This was something that gave me piece of mind as I set this up, and later on was a pleasant surprise... I was worried about keeping the READMEs in sync across branches and learned that past Stan had already had that panic.

A lof of the setup for this static site is so I'm not suprised by things that are easy to forget. I expect to change this rarely and would rather it break meaningfully and with context on my laptop than suprisingly and live on the internet.


There are two config files:

  • config.toml - the prod config
  • config.dev.toml - the dev config

As of now, the only difference between the two is that I print out the {{ __tera_context }} at the bottom of each template in dev so that it's easy to see what data is currently available while I'm futzing with the templates.


Besides the configuration difference in the toml files, there is a structural difference between dev and prod for this site.

By default, zola ships both the serve and build to the same public/ directory. I've over-ridden these in the Makefile so that one does not clobber the other.

public/ is in .gitignore, and remains the path for watching live updates. These can be triggered by running make serve-{dev,prod}.

  • make serve-dev - uses the dev config and shows draft posts
  • make serve-prod - serves exactly what would be built and deployed
  • make build - runs zola build but all output is in ./dist instead of ./public

Content structure

Zola keeps all posts in the ./content directory, which allows for arbitrary static pages. I figured I didn't want everything to be a blog post (what about projects?), and I also don't super like the term blog, even thouth that's what this is.

content/writes is where all of the blog-ish content goes, and all of the posts in it should be organized by date, in a writes/<YYYY>/<MM>/<DD>/<slug>/ format.

Zola doesn't have anything to help with autogenerating folder structures, so I made my own bash script to help. (see below)

Everything else (as of now) is a free for all.

$ find content -not -type d
content/writes/2019/11/09/how-this-blog-works.md    <-- THIS POST
content/writes/2019/11/09/_index.md                 <-- autogenerated
content/writes/2019/11/_index.md                    <-- autogenerated
content/writes/2019/_index.md                       <-- autogenerated
content/writes/_index.md                            <-- redirects to /
content/_index.md                                   <-- / the home page

Each of these autogenerated _index.md files are linked to symlinked from templates/writes_section, so that when I want to change 'em, I can do so easily.

Yes, this is all over-engineered, but also, kind of fun.

The Scripts

I've already covered make serve-{dev,prod} and make build which are wrappers around their respective zola commands. These are a few of the other scripts that make (pun somewhat intended), managing this easier.

  • bin/verify-content-dates - (source)

    This script looks for all non _index.md files in content/writes and places them in the correct dates subdirectories. It also cleans up any directories/files left-over with no posts once that's done.

    It keeps it all neat.

    aka: make date-dirs

  • bin/ship - (source)

    This script plublishes the dist directory to the master branch using git subtree split. There was a bit of a gotcha with overriding the entire master branch using this because it has to have a CNAME file and record in it to correctly publish to stanistan.com, it is now being symlinked and copied over via the static/ directory, same as the README.md.

    aka: make deploy

For all of the scripts in bin/* I'm using shellcheck, which is amazing, and helps me get better at writing bash.

The Theme

I'm using my own theme, which is being developed JIT, its primary colors come from the inspired-github syntax highlight theme included in Zola.

  • TODO (maybe): Extract into an actual theme.

Domain & Hosting

The domain is on dreamhost, which I've used for a loooong time, with DNS records pointed to GitHub as per these docs.