Skip to content Skip to footer

Indieweb and webmentions for my static site

A brief analysis on how I have implemented Indieweb principles and webmentions on my static Jekyll-based website, using the laziest method available.

Simone Silvestroni's avatar

The first time I’ve found about webmentions was when Silvia suggested an article by Chris Aldrich on A List Apart1. It also made me discover the Indieweb, and the concept of a small web free from the corporate vision. It perfectly matched the way I saw the internet and communication in general.

A couple of years later, after I’d decided to leave social media2 and turn my WordPress blog into a static website, I chose not to implement a third-party commenting system. Instead, I went back to consider webmentions. A W3C recommendation, it’s a decentralised way to interact with other websites’ posts, enabling replies, likes, reposts and more.

A Webmention is a notification that one URL links to another. For example, Alice writes an interesting post on her blog. Bob then writes a response to her post on his own site, linking back to Alice’s original post. Bob’s publishing software sends a Webmention to Alice notifying that her article was replied to, and Alice’s software can show that reply as a comment on the original post.

A list of tools and people who are using webmentions can be found on the IndieWeb wiki.

Implementation

I first tried a once popular Jekyll plug-in, which never worked properly, likely because the author has stopped any maintenance. The process to implementing webmentions manually was not straightforward.

Of course, now that it works I see what I was doing wrong, but it still got me thinking. I suppose it’s because I have issues with how sometimes hardcore developers document their code. I was totally in love with the concept, yet the information was scattered all over the place, with very little consistency, which I found confusing and off-putting.

For transparency, I’m not criticizing the people who made this possible, but I believe that the less tech-savvy would be excluded by using webmentions because of the technical barrier3 — unless they use some ready-made system such as WordPress, and can therefore install a plug-in.

It might be time for IndieWeb to rethink principles and priorities. The current list might appeal to developers […] but it doesn’t necessarily talk to the ones looking to satisfy the call of creativity, or those disillusioned of social media itself. Peter Molnar

The following step-by-step process works on a Jekyll-based website. For Hugo users check out this alternative.

Webmention.io and IndieAuth

Webmention.io is a free service created by Aaron Parecki. To log in I chose IndieAuth, which provides authentication for personal websites using existing social accounts, and is part of the IndieWeb effort to take back control of your online identity:

Instead of logging in to websites as “you on Twitter” or “you on Facebook”, you should be able to log in as just “you”. We should not be relying on Twitter or Facebook to provide our authenticated identities, we should be able to use our own domain names to log in to sites everywhere.

IndieAuth required my domain to either have a link to providers such as Github, or a working GPG key. I chose the latter:

<!-- In the <head> section -->
<link rel="pgpkey" href="/assets/files/key.pub">

Note: to use GitHub, it’s necessary to add a <link rel="me"> with the profile URL in the <head> section, which also would result invisible in the page. It’s required for the GitHub account to have a link back to the homepage URL in the profile settings.

IndieAuth login screenshot showing a working PGP key has been found IndieAuth login screenshot showing a working PGP key has been found

After clicking the green button, I signed the provided encrypted text with my private GPG key, which logged me in as me. This needed to be done once, or whenever I’m logged out from IndieAuth. Webmention.io dashboard was now up and running. Time to copy the code required to start accepting webmentions.

The following code is included in the default layout:

<link rel="webmention" href="https://webmention.io/minutestomidnight.co.uk/webmention">
<link rel="pingback" href="https://webmention.io/minutestomidnight.co.uk/xmlrpc">

Microformats

To properly send and receive webmentions it’s necessary to markup the content using microformats2.

Other humans can already understand your profile information and the things you post on your site. By adding a few simple class names to your HTML, other people’s software can understand it and use it for things like reply contexts, cross-site comments, event RSVPs, and more.

h-card

An h-card is for marking up people and organizations, often used on home pages and individual blog posts. It has to be contained within a DOM element with a class h-entry. The following is the h-card I have on pages:

<span class="p-author h-card">
  <img class="u-photo" src="{{ site.url }}/assets/images/favicons/favicon.svg" alt="Minutes to Midnight's avatar" width="24" height="24">
  <a class="p-name" href="{{ site.url }}/about/" rel="author">Simone Silvestroni ({{ site.title }})</a>
  <span class="p-note">{{ site.description }}</span>
  <a rel="me" class="u-url u-uid" href="{{ site.url }}{{ page.url }}">Permalink</a>
</span>

Briefly:

  • h-card contains all the author information, with data pulled from Jekyll’s config.yml.
  • p-author signals that’s me who’s writing the content.
  • p-name is the equivalent of a heading, in this case it’s also the name of the person or organization.
  • u-photo marks my avatar.
  • u-url is the current page’s permalink.

The h-card used in posts is slightly different, as it also contains information about the publish date (class dt-published), and it’s placed in the article header section:

<header>
  <h1 class="p-name">{{ page.title }}</h1>
  <time class="dt-published dim" datetime="{{ page.date | date_to_xmlschema }}" itemprop="dateCreated">{{ page.date | date: "%-d %B %Y" }}</time>&nbsp;&middot;&nbsp;<span class="p-author h-card">By <img class="u-photo" src="{{ site.url }}/assets/images/simonesilvestroni-uphoto.png" alt="Simone Silvestroni's avatar" width="28" height="28"> <a class="p-name" href="{{ site.url }}/about/" rel="author">Simone Silvestroni</a></span>&nbsp;&middot;&nbsp;<a rel="me" class="u-url u-uid" href="{{ site.url }}{{ page.url }}">Permalink</a>
</header>

h-entry

The h-card, as well as all the other necessary microformats-tagged markup, must be enclosed in a block with class h-entry.

h-entry is the microformats2 vocabulary for marking up blog posts on web sites. It can also be used to mark-up any other episodic or time series based content.

Content sections that needed microformats tags:

  • p-category for categories and tags
  • p-summary for the post excerpt
  • e-content wraps the main content of the post
  • u-syndication for links to other websites, if I cross-post
  • u-in-reply-to for reply types of webmentions
  • u-like-of for like types of webmentions

There are other types of webmention: repost, RSVP, bookmark, follow — but I don’t use them.

Indiewebify.me

Indiewebify is a useful service that allows anyone to test IndieAuth implementations and validate h-card and h-entry before starting to send webmentions. Had I discovered it earlier, it would have saved me a few hours of debugging.

Without indiewebify I don’t think I would have been able to even get started implementing any of this stuff. David Yates

The following is a screenshot — cut to shorten the content — of a blog post parsed and validated by Indiewebify.

Indiewebify validation for a blog post

Notes to comment, reply and like

The Indieweb doesn’t enforce a specific set of behaviours, so I chose to only support webmentions in the form of replies and likes, and avoid turning my personal website into a social media feed. It’s okay for whomever does that: I initially wanted to achieve the same goal, only to realize later that’s too much noise for me. I left centralised silos for several reasons and the cluttered unreadable interface was one of them.

Even though I could have used my blog posts to reply or like other people’s entries, I’ve recently decided to employ a second type of layout: notes. A common format in the Indieweb, this is how it’s defined:

A note is a post that is typically short unstructured plain text, written and posted quickly, that has its own permalink page.

My note layout is a shrinked version of the post layout. Since I’ve added the fundamental class h-entry to the body, notes only features an <article> element containing the same <header> section as mentioned earlier. Inside the article I have a Liquid logic condition to check the post’s Front Matter for the presence of either a replyto or a likeof.

{%- if page.replyto %}
<div class="e-content"><span class="p-name">{{ content }}</span></div>
{% elsif page.likeof %}
<p class="e-content"><a href="{{ page.likeof }}" class="u-like-of">{{ page.likeoftitle }}</a> by <code>{{ page.likeofuser }}</code></p>
{% endif -%}

This type of layout allows me to quickly create a note, fill-in the required data, such as the post’s original URL and the name of the person I’m interacting with.

If I’m replying and/or commenting, everything I write in the note .md file will replace the {{ content }} block featured in the layout.

Advantages of using a note to send a reply webmention:

  • Fast to write.
  • Set as a Jekyll collection, and excluded from both sitemap and navigation, it feels like a separate entity — which is how I perceive comments on the web.
  • Short. Since the block tagged with e-content is what’s going to be fetched and printed on someone’s comment section, I like it to be straight to the point and as brief as possible. When I see webmentions that are basically complete long posts, I feel like they miss the point altogether.

Threads (sort of)

In case I’m responding to someone who mentioned me from their blog, I also quote my original post, so that my comment would also appear on my site as a reply to the previous mention. It doesn’t feature indentations or anything fancy, but so far it’s been manageable.

Send webmentions

Even though I could automaticall send a webmention using a Netlify plug-in after each deploy, I prefer to do it manually. Telegraph is another free service built by Aaron Parecki, which does a great job.

Logging into Telegraph works the same as the other Indieweb services, it only needs my website to be correctly configured for IndieAuth. The dashboard has two tabs: one for finding links with potential webmention endpoints in a post, another for sending webmentions if I know both the source and the target URLs.

Telegraph dashboard showing the two tabs Find Links and Send Webmention

Pull webmentions

To receive webmentions I’ve implemented the popular webmentions.js by Fluffy. It pulls data from webmention.io, adding the results in a section of my website. The minified Javascript file is conditionally loaded in posts where webmentions can be received.

I have an included file where my comments code resides: <div id="webmentions"></div> at the bottom gets populated by the script in case webmentions are received.

Even though I did for a while, I stopped collecting backfeed reactions and comments as webmentions from Mastodon, due to privacy concerns.

Notifications

I monitor incoming webmentions using an RSS feed provided by webmention.io. The Mentions Feed section has two links. The one at the bottom, complete with my token, is an Atom feed URL which I added to my RSS reader.

I tried other venues to get webmention notifications, but I needed Max Glenister to show me the simplest solution.

Future improvements

I’d like to stop relying on a third-party service and especially Javascript, because it’s making comments not accessible if scripts are disabled and this makes me cringe. An alternative could be writing something in Ruby or trying Netlify functions.



Related topics
INTERNET
SOFTWARE
WEB DEVELOPMENT

Syndication
IndieNews
Mastodon