michaelharley.net

Webmentions on my blog, Part 2: Outgoing

2 min read

This is part 2 of my little webmentions series. In part 1, I outlined my incoming webmentions setup. This one will be much shorter because outgoing is a much more straightforward process.

As with incoming, I prefer to avoid dependencies on any external, third-party services to send my webmentions. I either want to self-host or roll my own. For outgoing webmentions, I decided to just roll my own.

And again, in the interest of full disclosure, I did use Claude Code to help me develop this.

The stack #

  • Language: plain Node.js, CommonJS. One script, no framework.
  • fs / path: walk _site/ and read the built index.html files.
  • crypto: builds the content hash that flags a post as edited, so it re-sends.
  • fetch (native, Node 18+): endpoint discovery and the webmention POSTs. No axios or got.
  • jsdom: the one real dependency. Parses each page's HTML to pull the outgoing links and read the target's rel="webmention".
  • State: two flat JSON files, no database.

How it works #

So my homelab has a little build server that runs between 6 a.m. and 11 p.m. eastern. It checks every five minutes for new commits. If it finds none, it does nothing.

If it detects a new commit, it rebuilds the site, and for each recently built page, it hashes the content and its links, compares that to the last run's hash, and queues up a re-send of the webmentions for the links on that page.

Before we can send a webmention, we have to discover where to send it. So the system fetches the target page and finds the endpoint it advertises.

The discovery/send step has an SSRF (server-side request forgery) guard built into it. Just like with incoming webmentions, it's possible for a hostile actor to craft the webmentions link in such a way that would allow them to probe my servers and network.

Finally, it sends the webmention to the target and records the send: it stores the page's hash and the links it notified, so the next run can tell nothing changed and skip it.

One fun thing this has enabled is that I generate an RSS feed of successfully sent webmentions. I like to see how other people are displaying their webmentions so that's cool.

Conclusion #

And that's how my website receives and sends webmentions. What has your experience been with webmentions?

Signal

1 mention
0 votes on Bubbles

Join the conversation