Hey, i have not implemented it in any hugo sites before, but i’ve dealt with indieweb (<3) before so i’ll be happy to help if you have questions. @kaushalmodi, i ended up writing a sort of super brief/dense tutorial on basic indieweb stuff, because i figured you wouldn’t be the only one in the community struggling to find their way around so many wikis and standards. It’s really just a draft. What do you think?
So if you have your rel=me links in place, you are setup to use indieauth, i.e. trust external web services to authenticate you elsewhere. ⁽¹⁾ That is not what webmention is about: this is the identity management side of the indieweb. This will be useful, for instance, to authenticate you on the webmention.io service.
So if you intend to use webmentions as a replacement for Disqus (amazing quest!), you need to:
- add semantics to your templates (microformats2)
- use/write an endpoint to interact with other websites (webmention)
- integrate this external content in your site (two methods)
So to integrate the data from your webmention endpoint into your website, there are two possibilities:
- update your templates to fetch data from this endpoint (using
getJSON
for instance) - let the endpoint or an intermediary script directly write to your website data folder
Add semantics to your templates
Interactions on the indieweb are interpreted by parsing class fields in the page. So you need to add semantic classes throughout your templates to let other websites understand your content. That allows someone to share an article of yours on their site, or to ‘like’ it, for instance. It also allows them to publish an article or a note in reply to your article by letting a link point to your URL with the class u-in-reply-to
.
For instance, I could just publish on my site something along the lines of:
<article class="h-entry">
<p>In reply to <a href="https://scripter.co/hugo-leaf-and-branch-bundles/">@kaushalmodi</a>'s <a href="https://scripter.co/hugo-leaf-and-branch-bundles/" class="u-in-reply-to">Hugo: Leaf and Branch Bundles</a></p>
<p class="e-content p-summary">Thanks for the recap on resource bundles! I feel enlightened :)</p>
</article>
That would be interpreted as a comment on your website. Your webmention endpoint processing this reply would then look up my h-card to establish a profile on me, that could be then displayed on your website alongside my comment.
There’s many examples of how to use microformats2 on the microformats wiki. You should take a look The basics of it is:
A collection of content is called should have class h-feed
. An individual content is either a h-entry
or h-event
, h-card
(for persons). Any of these content may have a p-name
class around its title and a u-url
class on its permalink. Typically only articles (blog posts) have a p-name, a simple note doesn’t. An image associated with a content is u-image
and the date is dt-published
.
Webmentions
A webmention is basically a web ping. It informs a website that one of its URLs was mentioned by another URL. A webmention typically looks like this (taken from W3C recommendation):
POST /webmention-endpoint HTTP/1.1
Host: aaronpk.example
Content-Type: application/x-www-form-urlencoded
source=https://waterpigs.example/post-by-barnaby&
target=https://aaronpk.example/post-by-aaron
HTTP/1.1 202 Accepted
Upon receiving a webmention, your website should parse the remote URL and figure out from its microformats2 markup what the interaction means.
Receiving
Your webmention endpoint is usually declared in your to indicate to other websites how to let you know about stuff:
<link href="http://aaronpk.example/webmention-endpoint" rel="webmention" />
So if to get started you would like to use the webmention.io endpoint, just login on there using indieauth (authentication through one your rel=me accounts), and then add the following snippet to your head:
<link rel="pingback" href="https://webmention.io/username/xmlrpc" />
<link rel="webmention" href="https://webmention.io/username/webmention" />
From here on websites trying to contact you will talk to webmention.io. So then we’ll need to integrate all this data we’ll receive with hugo.
Hugo integration
So now, we need is to add to our leaf and branch templates something to fetch the interactions (webmentions) to the content we’re building. Let’s go for the simplest for the moment, and simply fetch this data using {{ getJSON (printf "https://webmention.io/api/mentions?target=%s" .Permalink | urlize) }}
You can however request it by type (like, comment, reshare…). If you’re parsing some content and you’re not sure what kind of content it is, just take a look at post-type discovery.
So from there you just need to do some basic templating with the JSON fetched from webmention.io. A comment should be a h-cite
within your h-entry
. And you’re basically all done on the receiving end!
So why would we want to use an external script and go through the data folder to handle this? Because in this case here we don’t have any moderation, while a script exporting the webmentions (fetched from webmention.io) to your data folder through git would let you do basic moderation within Github/Gitlab using pull requests.
Conclusion
Sorry, that was a bit long (and it’s not over just yet). I hope it helps. Don’t hesitate to point out unclear parts. Maybe I’ll talk about sending webmentions next time!
Also, please note all this indieweb stuff might slowly be deprecated by the emergence of ActivityPub, the new federation protocol for the social web that’s basically a PubSub infrastructure built on the web with ActivityStreams2.0 as JSON vocabulary to represent the interactions. ActivityPub is already supported by forward-thinking platforms like Mastodon and Peertube (and many more coming).
So if you need to structure your content with a section by type (eg /note/ /like/ /article/), you should consider using ActivityStreams2.0 vocab because it’s more complete than microformats2.
⁽¹⁾ So if you wouldn’t like some service to authenticate you, you shouldn’t add the rel=me link to your profile on that site (that’s imo the main weakness of the indieauth spec).