How this site works

This post describes how I set up this site and some of the pitfalls along the way.

attempted workflow runs while getting the site working

to err is human, or: make sure your CI/CD stages respect git submodules

The Short Version

This site is created using the Hugo static site generator, with the minimalist Etch theme by Lukas Joswiak. The website itself is hosted on GitHub Pages and I manage the domain through Google Domains. A private GitHub repository contains the markdown, config, and static resources, while a GitHub Actions workflow automatically builds and deploys the site to a public repo whenever I push to main.

The Long Version

I knew I wanted to use a static site generator and not be bogged down by some complicated CMS. In all honesty, I chose Hugo because it seemed easy to use, is markdown-based, and I only needed the bare minimum to support a blog. (Okay, maybe also because I’ve seen some cool blogs rocking the Terminal theme.) In the future I’ll likely explore more themes to support things like tags and post categories.

With the choice of site generator out of the way, I needed somewhere to host it. I do enough server administration at my day job, and while I could have gone to the trouble of putting this on a VPS, I also was curious about more modern options like Netlify or Heroku. In the end, to keep things simple I opted to take the path of least resistance and let GitHub Pages do it for me. This keeps everything under one service and the usage limits are quite reasonable.

I had already gotten far enough locally with the initial site configuration, including adding the theme and using shortcodes for things like embedding images, so it was time to find a good process for deploying the site. I first looked at this post which also uses a .dev domain, but decided against giving Forestry.io access to my GitHub account (nothing against them, it just seemed like there might be a better way). I soon found this fantastic guide and had my GitHub Actions workflow running in no time.

Just one hiccup: while everything seemed to be working fine from the workflow perspective (err, after I errantly changed the version of actions-gh-pages but not the with/env section), when I looked at the public site repo, there was no index.html or indeed any HTML file output, only XML (along with favicons1 and images). Thus the troubleshooting process began.

Inspecting the output of the “Build and deploy” workflow in GitHub Actions, it didn’t take long to see that something was breaking during the Build stage, with Hugo emitting a series of warnings about layout files:

Run hugo
Start building sites … 
WARN 2021/09/22 03:46:41 found no layout file for "HTML" for kind "page": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN 2021/09/22 03:46:41 found no layout file for "HTML" for kind "page": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN 2021/09/22 03:46:41 found no layout file for "HTML" for kind "home": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN 2021/09/22 03:46:41 found no layout file for "HTML" for kind "section": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN 2021/09/22 03:46:41 found no layout file for "HTML" for kind "taxonomy": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN 2021/09/22 03:46:41 found no layout file for "HTML" for kind "taxonomy": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.

I stumbled around a few posts mentioning the error, which all seemed to suggest consulting the layout lookup rules. In particular, one suggested creating the missing templates but leaving them empty aside from a comment. So I did. And it made HTML files! Alas, they were empty, because the templates I had just created were empty. The fact that it worked when running the local Hugo server on my machine was a big hint that I was missing something in my build/deploy workflow. Then I realized that the theme I was using should include the layouts (which, of course, it does).

Clearly something was wrong with how I was using the theme, which, as is typically recommended for Hugo, leveraged git submodules. After learning how to remove a submodule and re-adding it, the problem persisted. Finally, after inspecting the checkout step of the workflow, I realized that the theme was not being included at all, because the checkout command did not include a flag to also include submodules. A one-line change to the my .github/workflows/deploy.yml workflow definition later, and it finally worked! Since I made a number of changes from the originally recommened deploy.yml file, I’ve reproduced my final version below:

name: Build and deploy

on:
  push:
    branches:
    - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v1
      with:
        submodules: 'recursive'
    - name: Setup Hugo
      uses: peaceiris/actions-hugo@v2
      with:
        hugo-version: '0.79.1'
    - name: Build
      run: hugo
    - name: Deploy
      uses: peaceiris/actions-gh-pages@v3
      with:
        deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
        external_repository: austinnorris/austinnorris.github.io
        publish_branch: main
        publish_dir: ./public
        cname: acn.dev

Conveniently, the final deploy step also includes a cname parameter that automatically creates the CNAME file required to use an apex domain for the site on Pages.

For about an hour of effort, not a bad result! This was my first time using GitHub Actions (being more familiar with GitLab CI/CD from work) or deploying a SSG-based website in such a manner, but I learned a lot along the way.


  1. I used this helpful tool to generate a simple favicon for multiple platforms. ↩︎