While working on my blog I discovered that some of the image and link sources in different posts had become broken without me noticing. Outside of “hugo says OK” I don’t have any other validation running on my blog so I decided to look for something that could lint the rendered output for dead links and other issues.

I tried a number of different tools but ended up using htmltest. It runs after hugo renders the static output of my blog in a public/ directory in the project root.

It is configured via a .htmltest file in your project root. Mine is two lines:

DirectoryPath: "public/"
CheckExternal: false

The first line tells htmltest to run over the public/ directory. The second tells it to ignore any external links, which it will otherwise crawl to see if they still work. I’m interested only in validating my own site’s output so this is disabled for now.

What a successful run looks like:

~/code/blog (patrickod/htmltest) » htmltest                                                                                                       patrickod@Marceline
htmltest started at 11:37:48 on public/
========================================================================
✔✔✔ passed in 41.374375ms
tested 200 documents

When I introduce a broken link, here a bad <img> on my about page, it reports the error.

~/code/blog (patrickod/htmltest*) » htmltest                                                                                                  2 ↵ patrickod@Marceline
htmltest started at 11:38:58 on public/
========================================================================
about/index.html
  target does not exist --- about/index.html --> /images/about/me-2022.jpg
========================================================================
✘✘✘ failed in 44.708333ms
1 errors in 203 documents
---------------------------

as a Github Action

Wrapping all up as a Github action to run on any new branches with posts.

name: htmltest

permissions:
  contents: read # (default) needed for the actions/checkout task

on:
  push:

jobs:
  test:
    name: htmltest
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
          lfs: true

      # configure hugo & build
      - uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: "0.107.0"
          extended: true
      - run: hugo --minify --enableGitInfo

      # run tests
      - name: Run htmltest
        uses: wjdp/htmltest-action@master
        with:
          config: .htmltest.yml