98 lines
7.3 KiB
Markdown
98 lines
7.3 KiB
Markdown
---
|
|
title: Host your own webmention receiver
|
|
subtitle: Beyond webmention.io and static site integration
|
|
date: 2021-05-16
|
|
tags:
|
|
- indieweb
|
|
- webmentions
|
|
- hugo
|
|
categories:
|
|
- webdesign
|
|
---
|
|
|
|
Yesterday's "Webmentions Beyond Webmention.io" [IndieWeb event](https://events.indieweb.org/2021/05/webmentions-beyond-webmention-io-zG4JpHhZShVA) ([see notes](https://indieweb.org/2021/Pop-ups/Webmentions_Beyond_Webmention.io)) exposed a problem: many bloggers exploring the IndieWeb and Webmention world simply make use of [webmention.io](https://webmention.io/), a hosted solution that handles receiving mentions, enabling you to treat the whole system as a black box. Aaron wondered: _"why are so many people using webmention.io?"_ - and the answer is quite obvious: because it's easy. Just add `<link rel="webmention href="https://webmention.io/something">` to your HTML header after signing up and you're done.
|
|
|
|
The IndieWeb community sometimes forgets that the community mostly consists of tech enthusiasts who know how to program and configure stuff, while many bloggers just want a way to interact with other blogs. They discover the Webmention system, read somewhere it's a contemporary and maybe better alternative to Pingbacks (although [I contested that](/post/2021/03/the-indieweb-mixed-bag/)), and just want to "make use" of it, without losing hours and hours of fiddling with scary code.
|
|
|
|
So, is there a decent alternative? No. But their are alternatives which allow you to host your own receiver. Again, these are very much geared towards techies...
|
|
|
|
## Enabling Webmentions on Hugo
|
|
|
|
Another sore point seemed to be the lack of decent guides for people to follow when trying to enable Webmentions - beyond the WM.io "standard" - on their static sites. Since I wrote a Jamstack/webmention microservice called [go-jamming](https://git.brainbaking.com/wgroeneveld/go-jamming) which is used on my blogs, I'd like to take this opportunity to show you how easy it is to do it yourself.
|
|
|
|
### Step 1: Running go-jamming yourself
|
|
|
|
The service is a single binary that is super easy to run anywhere. An amd64 version binary is available in the [GitHub releases page](https://git.brainbaking.com/wgroeneveld/go-jamming/releases). Follow the [INSTALL.md instructions](https://git.brainbaking.com/wgroeneveld/go-jamming/src/branch/master/INSTALL.md) if you'd like to install it as a Linux service or set up a reverse proxy through Nginx. If all goes according to plan, you'll end up with a `https://jam.yourdomain.com/webmention` and pingback endpiont others can POST to. There!
|
|
|
|
Go-jamming _should_ be an easy drop-in replacement for Webmention.io. However, since I wrote it with my mainly own needs taken into consideration, and nobody else as far as I know is running it, it could be that you require a missing feature or so. Ping me, fork the code, ... and we'll work it out.
|
|
|
|
### Step 2: Retrieve mentions and store locally
|
|
|
|
There are simple GET endpoints available that allow you to fetch mentions from the go-jamming service. I store these under `data/webmentions.json`, enabling the Hugo template engine to access this data. We'll get to that in a minute. How to retrieve? Issue a simple GET request.
|
|
|
|
The question is, how to fit this into a typical Hugo/Jamstack build? I have a single JS file in the root of my website that fetches this data using [jam-my-stack](https://git.brainbaking.com/wgroeneveld/jam-my-stack), a few simple wrappers around services such as Lunr and go-jamming:
|
|
|
|
```js
|
|
const mentions = await webmention.getWebmentions("brainbaking.com")
|
|
const json = JSON.stringify(mentions, null, 4)
|
|
await fsp.writeFile(`${__dirname}/data/webmentions.json`, json, 'utf-8')
|
|
```
|
|
|
|
There is zero magic involved in `getWebmentions()`: see `webmention.get.js` source, if you do not want to depend on jam-my-stack.
|
|
|
|
What triggers this JS script? A GitHub actions workflow (Addendum 07/2022: I no longer rely on GitHub's workflows). It also automatically checks in any changes! This is a great way to get notified of new mentions. `git pull` tells me if new entries are added into the JSON file. This saves me from implementing a stupid mail function in the service.
|
|
|
|
### Step 3: Integrate webmentions in your Hugo template
|
|
|
|
Now that we have a local JSON file, things are dead simple:
|
|
|
|
```
|
|
{{ $mentions := (where .Site.Data.webmentions "relativeTarget" "==" $.RelPermalink) }}
|
|
{{ range $mentions }}
|
|
<p class="p-content p-name">
|
|
{{ .content | safeHTML }}
|
|
</p>
|
|
etc!
|
|
{{ end }}
|
|
```
|
|
|
|
See [my full template file](https://git.brainbaking.com/wgroeneveld/brainbaking/src/branch/master/themes/brainbaking-minimal/layouts/partials/single-webmentions.html) for a complete example. How do you know which properties to use? Well, a go-jamming mention looks like this:
|
|
|
|
```js
|
|
{
|
|
"author": {
|
|
"name": "Wouter Groeneveld",
|
|
"picture": "/pictures/brainbaking.com"
|
|
},
|
|
"name": "",
|
|
"content": "More nineties collecting nostalgia. After I wrote about it at https://brainbaking.com/post/2021/05/nineties-collecting-nostalgia/ my wife dug up a shoebox full of… well… judge for yourself. From left to right:Kinder Surprise figurines, Polly Pock...",
|
|
"published": "2021-05-13T15:20:00+00:00",
|
|
"url": "https://brainbaking.com/notes/2021/05/13h15m20s00/",
|
|
"type": "mention",
|
|
"source": "https://brainbaking.com/notes/2021/05/13h15m20s00/",
|
|
"target": "https://brainbaking.com/post/2021/05/nineties-collecting-nostalgia/",
|
|
"relativeTarget": "/post/2021/05/nineties-collecting-nostalgia/"
|
|
},
|
|
```
|
|
|
|
See the [go-jamming documentation](https://git.brainbaking.com/wgroeneveld/go-jamming) for more information.
|
|
|
|
### Step 4: Sending out webmentions
|
|
|
|
You can also leverage go-jamming's built-in ability to scan your RSS to periodically send out webmentions. Again, if you use jam-my-stack, it's as easy as writing `await webmention.send("brainbaking.com")` that is also triggered using the same GitHub build action.
|
|
|
|
Go-jamming does all the rest, such as:
|
|
|
|
1. Checking whether there's a new article in your `/index.xml` feed;
|
|
2. Collecting links to send out;
|
|
3. Checking if the links have a webmention or pingback endpoint;
|
|
4. Sending out the mentions accordingly.
|
|
|
|
It remembers the last processed post as not to overwhelm other endpoints, so you can call `send()` as many times as you'd like. If you do not like jam-my-stack as a dependency, just write your own: it's simply a PUT request (see `send.js` in jam-my-stack)!
|
|
|
|
## Does this solve the issue?
|
|
|
|
Well, yes and no. There _are_ webmention.io alternatives, such as the one I've written myself, but these do assume a certain level of technical proficiency. Go-jamming makes it possible to service multiple websites: in fact, my endpoint takes care of this site, jefklakscodex.com and redzuurdesem.be. But I do not want to host mentions of others, that kind of defeats the purpose of "owning your data".
|
|
|
|
There was also talk about writing "plugins" for static site generators in the meeting yesterday. However, I don't think a plug-and-play version of something like this is likely to ever exist: templates are inherently personal. In my opinion, the method explained in this post is as good as it gets. I do not want to conform API contracts or input/output of go-jamming to yet another (IndieWeb or otherwise) standard that eases drop-ins of webmention servers but puts more burden on the developers of those services...
|