Note: This is Part 3 of a five-part series about how you can set up webmentions in Web sites built by three different static site generators: Eleventy (the subject of Part 2), Hugo (the subject of this part), and Gatsby (covered in detail in Part 4). In the conclusion, you’ll find a bibliography of the best articles I found on the subject of this series. All of the articles link (even if only through tiny GitHub logos) to their authors’ code. They were invaluable to this effort, and I encourage you to take particular notice of them and their authors.
In the introduction to this five-part series, I gave you a quick run-through about the IndieWeb and the general setup of webmentions. In Part 2, the subject was how you implement webmentions specifically in the Eleventy SSG. Now, here in Part 3, we’ll talk about implementing them in the Hugo SSG.
Or so I thought.
Hugo: Fetching webmentions
There’s plenty of data-massaging capability built into Hugo, so I wasn’t so worried about how I’d handle that end of the process. My concern was how I’d go out to webmention.io and grab the data in the first place.
/assets/js/webmentions.js which was based mostly on Paul Kinlan’s work but also, to a limited extent, on the code by Max Böck and Sia Karamalegos that I used in the Eleventy repo.
Kinlan’s code took a different approach: rather than fetching and then aggregating all the site’s currently available webmentions into one JSON file, it downloaded into
/data/ a separate JSON file of webmentions for each page that had received them. To keep the files straight, the code applied MD5 hashing to the URL for each page with webmentions, then gave that page’s JSON file the same hashed name.
Or, at least it would if it could fetch the webmentions from webmention.io. And therein lay the biggest problem I faced with the Hugo repo.
You see, one thing you have to “present” to webmention.io to “prove” that your site “deserves” to grab the webmentions is an authentication token. In the Eleventy site, you can easily handle this by creating a file,
/.env, for storing such so-called environment variables out of sight (don’t source-control such a file; instead, add it to your
.gitignore) but exposing them to other code through generic names such as
WEBMENTION_IO_TOKEN. In an SSG like Eleventy or Gatsby that uses Node JS, that works because of a widely used npm package called
For a while, it looked as if the only working method would require including the token in plain sight in a
GET-style query string: e.g., something like
https://webmention.io/api/mentions.jf2?domain=brycewray.com&token=1234567890123. Not a good idea, as you can imagine.
Finally, after hours of sifting through similar issues reports from Hugo users, I found the answer: setting up the appropriate
/package.json-based scripts to run
/assets/js/webmention.js after a command that would first run
dotenv and, thus, “force-feed” it the environment variable! For example, the
/package.json line for fetching webmentions in development mode was:
"dev:wmFetch": "node -r dotenv/config assets/js/webmentions.js"
Note: If you deploy a repo like this through Netlify, that
/.env file is irrelevant in production, since the proper procedure is to let Netlify handle sending an environment variable at the appropriate time. Other than during development, I use that file only for executing “production” builds on my local setup in the testing process through the
testbuild script in
Hugo: Displaying webmentions
After that, the only major thing left was creating a Hugo “partial”—
/layouts/partials/webmentions.html—which would make the data presentable. I relied heavily on the Eleventy
/_data/webmentions.js as my guide for writing the Go-flavor Hugo code to make this happen.
I expected the biggest hassle in that final part of the “webmention-izing Hugo” project would be getting Hugo to recognize the MD5-hashed URLs of the respective JSON files. Not so. Fortunately, Hugo has built-in support for MD5. And, in the end, I actually appreciated the whole approach because it simplified the process of identifying which set of webmentions went with each respective Web page.
That left only:
Putting a call to that partial in the
/layouts/default/baseof.html, the site’s simplest but most important template, so that it would call to that webmentions-savvy footer partial on every page except for any pages within the paginated posts list.
As with the Eleventy repo, making appropriate edits to the webmentions.css file—in this case,
/assets/css/webmentions.css. In fact, the CSS was the same, so that was just a matter of copying the file from one repo’s appropriate location to the other’s.
Next up: Gatsby
So, it was on to the Gatsby repo, which I naïvely believed would be a relative piece of cake. All I’d have to do was make a few changes to the JS from my Eleventy repo (see Part 2 of this series). Right? Hmm?
Ahhh, not exactly, Space Cadet. Follow me to Part 4—if you have the stomach for witnessing a bloody struggle.