I’ve been peripherally aware of the IndieWeb movement for a few years now – mostly because they seem to like RSS almost as much as I do – but I’ve only recently dug into it. In a nutshell, IndieWeb is about using the World Wide Web itself as a social network, through a set of open standards for communication and identification of content and people. These things can be used instead of modern social networks (Facebook, Twitter, etc…) or in a way that incorporates these networks as a complementary channel. The movement has three main pillars, expressed as sequential levels: identity, publishing and federation.1
As part of the research for this post, I’ve implemented aspects of all three on this very website.
# Level 1: Identity
Your homepage, hosted on your domain, is your profile page and your identity online. IndieAuth provides an authentication protocol that works by tying your homepage to an email address or social login provider like Twitter or Github. You do this by adding rel="me"
links to your website’s homepage similar to the below:
<head>
<!-- Who I am on other sites -->
<link rel="me" href="https://twitter.com/davidyat_es" />
<link rel="me" href="https://github.com/dmyates" />
<link rel="me" href="mailto:d@vidyat.es" />
<!-- The service I use for authentication -->
<link rel="authorization_endpoint" href="https://indieauth.com/auth" />
<link rel="token_endpoint" href="https://tokens.indieauth.com/token" />
</head>
Then, for any IndieWeb site that uses IndieAuth, you just enter your website URL and then choose which provider to OAuth through (or click a link in an email). Your URL is sort of like a username, and the OAuth/email sort of like a password.
Social media analogue: Making an account and logging in.
# Level 2: Publishing
Once your identity’s set up, the next step is to create posts, which involves marking up content with microformats and sending webmentions.
Microformats are a framework for marking up websites to make them readable to machines. They are used in IndieWeb circles to mark arbitrary pieces of HTML as analogous to things in social media. All you have to do is add a few classes to some page elements, and you’re all microformatted up – it took me a few minutes to mark up most of this website.
An h-card
is a set of identifying information about a person or organisation, like a Twitter bio; an h-entry
is a piece of datestamped content, like a tweet or a blogpost; an h-feed
is a feed of h-entry
s. All of these building blocks have a set of mostly optional standard attributes, so your h-card
can be as simple as a name and a website, or it can include your home address and date of birth down to second.
<!-- An h-card representing me -->
<p class="h-card">
<a class="p-name u-url" href="https://davidyat.es">David Yates</a>
</p>
<!-- An h-entry representing this post -->
<article class="h-entry">
<a class="p-name u-url" href="/2019/06/16/indieweb/">Untangling the IndieWeb</a>
<time datetime="2019-06-16" class="post-date dt-published">16 June 2019</time>
<ul class="tags">
<li><a href="/tags/x">#<span class="p-category">x</span></a></li>
<li><a href="/tags/y">#<span class="p-category">y</span></a></li>
</ul>
<div class="e-content">
...
</div>
</article>
<!-- An h-feed of my recent posts -->
<ul class="h-feed">
<li class="h-entry">
<a class="p-name u-url" href="/2019/06/16/indieweb/">Untangling the IndieWeb</a>
<time datetime="2019-06-16" class="post-date dt-published">16 June 2019</time>
</li>
<li class="h-entry">
<a class="p-name u-url" href="/2019/05/05/site-redesign/">Site redesign</a>
<time datetime="2019-05-05" class="dt-published">5 May 2019</time>
</li>
...
</ul>
An interesting implication of h-feed
s and h-entry
s is that, if implemented properly, these simple bits of metadata are enough to turn a human-readable HTML site into a machine-readable feed equivalent to RSS/Atom. Using Aperture to subscribe to feeds and Monocle to read them, you can replicate an RSS reader experience without RSS.
Webmentions are how you let other people know you’re linking to them. They’re similar to pingbacks, but involve a lot less XML. The principle is very simple: a webmention is a message containing two URLs, a source and a destination. The source links to the target, and this link is marked up with microformats to indicate the nature of the link.
<!-- An h-entry reply to a post on another website -->
<div class="h-entry">
<p>in reply to: <a class="u-in-reply-to" href="https://bob.example.com/my-first-post/">Bob</a></p>
<p class="e-content">Hi Bob!</p>
</div>
This reply can then be sent to a webmention endpoint using a cURL command like this (some blog software will send these automatically):
curl -i -d "source=https://alice.example.com/hi-bob/&target=https://bob.example.com/my-first-post/" https://webmentionlistener.com/bob-example
The endpoint then has to verify that the source page contains a link to the target page, and then it can use that page’s microformats parse out an interaction with the target page.
Social media analogue: Posting updates.
# Level 3: Federation
I alluded before to marking webmentions up with microformats. Webmentions are comments, likes, reposts, replies, and so on, generalised to the web. Alice posts an interesting blog post, Bob creates a page that links to it and sends a webmention to Alice, and then Alice shows a message at the bottom of the post saying “Bob reposted this at https://bob.example.com/interesting-post/
.” You can see this in action at the bottom of this very page and some of my more recent posts.2
Now, not everyone has a dedicated website (or necessarily wants to use it to comment on things). Webmentions are an open standard, intended for use by anything that implements them. In an ideal world, social networks would do this, but in the absence of that there’s glue layers like brid.gy.
Social media analogue: Likes and comments.
# Going further
Besides all that I’ve mentioned above, there are specifications for posting and RSVPing to events ala Facebook, which I have no use for on this site, and then things get extremely federated.
Micropub is a spec for web-based publishing, i.e. creating, editing and deleting posts on your website through application(s) that implement it. Or raw HTTP, conceivably. Webactions are a way to implement like/repost/reply buttons on your site that, when clicked, will cause the appropriate actions to happen on a user’s site, i.e. create a microformatted source page and send a webmention to the target. That’s all kind of cool, but not really worth it for me, at least for now.
# Implementation pain points
Though I love the theory of using human-readable pages as subscribable feeds, I didn’t love it enough to change my site design. Most readers I tried seemed to expect each entry to have an embedded p-author
element despite indications that a single p-author
h-card
on the same page would work fine. This forced me to use invisible metadata to add myself as the p-author
for each post. Some webmentions I received for this site show up with null authors for what I assume are similar reasons.
The wiki feels a bit disorganised sometimes, with a number of clearly draft-level pages.3 I also think it sometimes focus on examples to the detriment of explanatory content. Without this additional site I don’t think I would have been able to even get started implementing any of this stuff.
# Conclusion
The big IndieWeb idea is to have your website host original versions of your articles, Twitter-type microposts, replies to other people, liked and reposted things, bookmarks, events and so on. If you need to post to other sites, that should be done automatically through webmentions and APIs. Your website should also host its own webmention endpoint (which I’m not doing for expediency) and reader, which you use to subscribe to notifications from said webmention endpoint and to the websites of other people you know, like or admire. Private webmentions can be used for some of this stuff too, or maybe all of it. In the end, you have a combination of Facebook, Twitter and Google Reader, without the algorithms or data mining. But the only people you interact with are other programmers who’ve also managed to implement all this stuff.
Open standards are important for freedom and interoperability, but there’s a reason closed platforms are so popular. While at least two blogging platforms support most IndieWeb stuff out of the box and there are plugins for things like Wordpress, we’re a long way from a world in which something like this is a substantial part of the social media landscape. Websites like Twitter and Facebook could implement interoperability with these features, but it would be against their interests to do so – in the wake of Cambridge Analytica, Facebook can even spin that it would be a danger to their users’ privacy to do so.
But could there be a social network that packages these technologies in a friendly, usable way for the non-tech-savvy? One that registers an actual domain name for each user and spins up a base site with all these integrations: micropub for posting, microsub for reading, with webactions and webmentions to glue it all together. I’m not sure. It probably wouldn’t be free.
-
This page provides a more complex view of the interconnected components. ↩︎
-
I’ve long intended to add comments to this blog, but I could never find a plugin I liked (Staticman came the closest). I made an attempt at rolling my own, but got stuck trying to come up low-effort ways to enable comment moderation.5 Implementing webmentions, on the other hand, took me a weekend, and let me incorporate existing Twitter interactions. It also gave me the chance to test-drive Vue.js, which is slowly melting my hostility to JS frameworks. ↩︎
-
This is something that bothers me about OWASP too – I don’t know why tech people are so far behind Terraria fans and pop-culture nerds on the wiki front! ↩︎
-
Or rather, having your own blog on the site is not free. You can still sign up and interact with the community if you use your own site to do so, as I’ve done. ↩︎
-
One of my stranger ideas was to have every comment send a secret deletion link to the administrator in a PGP-encrypted email. I got pretty far along in implementation before I thought about what a pain it would be to actually use. ↩︎