Sending my first webmention from scratch
Series: Joining the Fediverse
Hello, is this mic on?
Sending a Webmention
This page is written purely to test out whether I can send out Webmentions.
Following @aaronpk’s awesome tutorial, I put toghether the Webmention below as a test to verify whether I can send out Webmentions.
To send a Webmention, it actually suffices to have a link to a site that supports receiving Webmentions.
However, using some microformatting with h-entry and h-card, you can add context to them.
In this case the Webmention is formatted as a reply but it could just as well be formatted as a like or a repost.
Hugo Shortcode
To make my future life easier, I created a Hugo shortcode as well.
The Webmention above is then constructed as follows:
{{ < webmention type="reply" href="https://aaronparecki.com/2018/06/30/11/your-first-webmention" name="@aaronpk" > }}
Testing my very first webmention. Thank you @aaronpk for your tutorial!
{{ < /webmention > }}
Note:
I had to add spaces between {{ < and > }} to prevent Hugo from rendering the shortcode.
So make sure you remove them if you’re copy/pasting my example.
<!-- /layouts/shortcodes/webmention.html -->
<div class="webmention h-entry">
{{ $author := lower (or ($.Page.Params.author) ($.Site.Params.author.name)) }}
{{ with index $.Site.Data.authors $author }}
{{ $name := .name }}
<div class="wm-author u-author h-card">
{{- with .avatar -}}
{{ with resources.Get . }}
{{ with .Resize "40x webp" }}
<img src="{{ .RelPermalink }}" alt="Avatar of {{ $name }}" class="wm-photo u-photo" />
{{ end }}
{{ end }}
{{- end -}}
<a href="{{ $.Site.BaseURL }}" class="wm-name u-url p-name">{{ $name }}</a>
</div>
{{ end }}
{{ if .Get "type" }}
{{ $type := .Get "type" }}
{{ $href := .Get "href" }}
{{ $name := .Get "name" }}
<span class="wm-response">
<span class="wi wi-{{ $type }}">{{ partial "svg" $type }}</span>
{{ if eq $type "reply" }}
<a class="u-in-reply-to" href="{{ $href }}" title="In reply to {{ $name }}">{{ $name }}</a>
{{ else if eq $type "like" }}
<a class="u-like-of" href="{{ $href }}" title="Liking {{ $name }}">{{ $name }}</a>
{{ else if eq $type "repost" }}
<a class="u-repost-of" href="{{ $href }}" title="Repost of {{ $name }}">{{ $name }}</a>
{{ else if eq $type "rsvp" }}
{{ $rsvp := .Get "rsvp" }}
<data class="p-rsvp" value="{{ $rsvp }}">
<a href="{{ $href }}" title="RSVP to {{ $name }}">{{ $rsvp }}</a>
</data>
{{ end }}
</span>
{{ end }}
<p class="wm-content e-content">
{{- .Inner -}}
</p>
<p>
<a href="{{ $.Page.Permalink }}" class="wm-timestamp u-url">
<time class="dt-published" datetime="{{ $.Page.Params.Date | time.Format "2006-01-02T15:04:05Z0700" }}">{{ $.Page.Params.Date | time.Format ":date_medium" }}</time>
</a>
</p>
</div>
Notice how I’m referencing $.Site.Data.authors in the shortcode.
This is using a JSON data file, which looks like this:
// /data/authors.json
{
"dezestijn": {
"name": "DezeStijn",
"avatar": "/img/avatars/dezestijn.png"
}
}
Note:
Don’t forget to add the avatar image to the /assets/img/avatars folder.
In the shortcode, I’m also referencing a partial named svg.
This partial makes it easier to include inline SVGs.
To use it, store the SVGs you want in /assets/icons/.
{{ $svg := . }}
{{ return ((printf "/assets/icons/%s.svg" $svg | readFile) | safeHTML) }}
You can then use the following template to include /assets/icons/reply.svg:
{{ partial "svg" "reply" }}
Automated sending
To then actually notify other sites of the fact that I’m mentioning them, I’m using the @remy/webmention package in a GitHub workflow:
---
name: Notify
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
# Wait for the build&deploy workflow to finish
workflow_run:
workflows: ["build-deploy"]
branches: [main]
types:
- completed
workflow_dispatch: {}
jobs:
publish:
runs-on: ubuntu-latest
# Only run if build&deploy was successful
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache node modules
uses: ./.github/actions/cache
with:
path: |
~/.npm
node_modules
hash: ${{ hashFiles('*package-lock.json') }}
name: cache-node-modules-v1
- name: Setup NodeJS
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Node.js dependencies
run: npm install
- name: Send WebMentions
run: npm run wm:send
{
"name": "sequr.be",
// ...
"engines": {
"node": "20.x"
},
"dependencies": {
"@remy/webmention": "^1.5.0",
"npx": "^10.2.2"
},
"scripts": {
// Take last item from Atom feed and send webmentions
"wm:send": "npx webmention public/atom.xml --limit 1 --send"
}
}
And if all goes well, this post should now be listed as a reply/comment on Aaron’s blog post.