Now, I'm in IndieWeb?

Since I saw the concept of IndieWeb last year, I’ve been wanting to support it on my Zola blog. Before that my blog had never had a commenting system, and this time with Webmention I was finally able to get a static blog to display responses to articles on the web in plain html. I will document how I did it in this article.

The IndieWeb IndieWeb is a community of independent & personal websites connected by simple standards, based on the principles of: owning your domain & using it as your primary identity, publishing on your own site (optionally syndicating elsewhere), and owning your data.

1. Support IndieWeb Auth🔗

IndieAuth is a federated login protocol for Web sign-in, so by enabling this, we can use our own domain to sign in to other sites and services which support IndieAuth. Learn more about why IndieAuth and how to IndieAuth, here’s how I enabled it:

  1. By editing my index template file, add this to the head:
<link rel="me" href="" />
<link rel="me" href="" />
<link rel="me" href="" />
  1. Editing Twitter/GitHub profile bio, add my website URL

  2. Test it at

2. Add Profile Info🔗

When you sign in with IndieAuth or using web mention, some sites will try to get your profile info, like name, image, and bio. So we can add this to our homepage, you can learn more about h-card here. Here’s how I added it:

By editing my index template file, add this in the aside (Cause I don’t want this to affect the layout of my site, so use css display: none to hide it for human, but the bot will see it):

<div class="display-none h-card pt">
  <img class="u-photo icon" alt="Owen"
  src="{{get_url(path="site/images/favicon-96x96.png",cachebust=true)}}" />
  <a class="p-name u-url" href="{{ config.base_url }}"
    >{{ }}</a
  <p class="p-note">{{ }}</p>

3. Joining IndieWeb Webring🔗

A webring (or web ring) is a collection of websites linked together in a circular structure, and usually organized around a specific theme, often educational or social. They were popular in the 1990s and early 2000s, particularly among amateur websites.

Now, IndieWeb has one IndieWeb Webring! by adding webring in our sites, so people can find (and be found by) other folks with IndieWeb building blocks on their sites!

So, I’m in it! By joining this, my blog has been listed in the IndieWeb Webring Directory, you can see I already have a profile there.

It’s easy to join the webring, just click the link, and login with my domain, then I can get my webring code, my webring code like this:

<a href=""
An IndieWeb Webring 🕸💍
<a href="">→</a>

Then, I add this code to my homepage aside, you can see it on the aside footer

4. Adding Webmention Response to articles🔗

Webmention is a web standard for mentions and conversations across the web, a powerful building block that is used for a growing federated network of comments, likes, reposts, and other rich interactions across the decentralized social web.

“An @ mention that works across websites; so that you don’t feel immovable from Twitter or Fb.” — Rony Ngala

Learn more about Webmention and How to support webmention

Basically, I use to collect all webmentions about this blog, and then I use Denoflow to cache them to my blog repo, and then I use Zola load_data function to load them, and render them.

  1. First, go and create a new account with my domain, then I can get my webmention endpoint, and I connected my twitter and github account to the service.

  2. Second, let other services know your webmention endpoint. Add this to the head:

  1. Use Denoflow to cache all webmentions to my blog repo

Workflow file(workflows/fetch-webmention.yml):

Fetch webmention API to get updates, then save to webmentions directory.

  - use: fetch
    run: return ctx.result.json()
    itemsPath: children
    key: "wm-id"
  run: |
    const {ensureDir} = await import("");
    const { dirname } = await import("");
    for(const item of ctx.items){
      const id = item["wm-id"];
      const target = new URL(item["wm-target"]);
      const pathname = target.pathname;
      const filename = pathname.slice(1).replace(/\/$/, "");
      const filepath = "webmentions/"+filename+".json";
      await ensureDir(dirname(filepath));
      let webmentionData = {};
      try {
        const dataString = await Deno.readTextFile(filepath);
        webmentionData = JSON.parse(dataString);
      } catch (_e) {
        // ignore
      webmentionData[id] = item;
      console.log("write file:", filepath);
      await Deno.writeTextFile(filepath, JSON.stringify(webmentionData,null,2));

Github Workflow file(.github/workflows/denoflow.yml):

Run denoflow every day at midnight, if there are any new updates, it will create a new pull request.

name: Denoflow
  # push:
  #   branches:
  #     - main
    - cron: "1 0 * * *"
    runs-on: ubuntu-latest
    concurrency: denoflow
      - name: Check out repository code
        uses: actions/checkout@v2
      - uses: denoland/setup-deno@v1
          deno-version: v1.x
      - run: make webmention
        continue-on-error: true
      - name: chown
        run: sudo chown -R $USER:$USER ./
      - name: git config
        run: git config --global "github-actions[bot]" && git config --global
      - name: git add
        run: git add data && git add webmentions
      - run: git status
      - id: isChanged
        run: git diff-index --cached --quiet HEAD || echo '::set-output name=changed::true'
      - name: Create pull request
        uses: peter-evans/create-pull-request@v3
        if: ${{ steps.isChanged.outputs.changed == 'true' }}
          token: ${{ secrets.PERSONAL_TOKEN }}
          labels: automerge
          add-paths: data,webmentions
          commit-message: "chore: new item"
          committer: "github-actions[bot] <>"
          author: "github-actions[bot] <>"
          branch: new-item
          delete-branch: true
          title: New item update

Github auto merge workflow file(.github/workflows/auto-merge.yml):

When a pull request is created, the workflow will automatically merge it if the pull request is from the same author

name: Auto merge
    runs-on: ubuntu-latest
      - name: Merge
        if: ('theowenyoung') && (startsWith(github.head_ref,'new-item'))
        uses: "pascalgn/automerge-action@v0.14.3"
          GITHUB_TOKEN: "${{ secrets.PERSONAL_TOKEN }}"
          MERGE_DELETE_BRANCH: true
          MERGE_LABELS: ""
  1. Add response block to page tempalte

This part may take a while to finish, here is the main page template code, I’ll only show the main part.

Use Zola load_data function to load the webmention data JSON file.

{% set current_webmention_file_name = current_path | trim_end_matches(pat="/")
%} {% set webmention_data =

Show response:

{% if webmention_data %} {% set_global mentions = [] %} {% for ignored, item in
webmention_data %} {% set_global mentions = mentions | concat(with=item) %} {%
endfor %}
<p class="muted text-sm">
  {{trans(key="label_response_description",lang=lang)| markdown(inline=true) |
{% for type, items in mentions | group_by(attribute="wm-property") %}
  {{trans(key="label_"~type,lang=lang)}} ({{items | length}})<a
{% if type == 'like-of' or type == "repost-of" or type == "bookmark-of" or type
== "follow-of" %}
<ul class="list-none flex items-center flex-wrap">
  {% for item in items %} {{ macro::webmention(type=type, item=item) }} {%
  endfor %}
{% else %}
<ul class="list-none">
  {% for item in items %} {{ macro::webmention(type=type, item=item) }} {%
  endfor %}
{% endif %} {% endfor %} {% endif %}

Then, I add a webmention form, so if people want to submit their mentions, they can directly submit it.

  <div class="flex items-center flex-wrap pb">
    <input type="url" name="source" class="flex-3 mr-sm w-full py-sm px-sm" />
    <input type="submit" class="px py-sm" value="Send Webmention" />
  <input type="hidden" name="target" value="{{current_url}}" />

Optional: I also added an activity page for aggregating all response, the activity template page is here

Cause I don’t have too many mentions, so I use sebastiandedeyne’s mention data as this article’s webmention data.

5. Send webmention when you publish a new article🔗

When we publish a new article, we want to send a webmention to the mentioned links. We can do this by using Denoflow and the API. can check all the mentioned links in the new article and send all webmentions to them. Before can recognize the mentioned links, we need to add some extra microformats2 to our article html. Basically, it’s some html tag class names. These took me quite a few time to update my templates, so now I have supported h-card, h-entry and h-feed. It looks like this:

<article class="h-entry">
  <h1 class="p-name">Microformats are amazing</h1>
    Published by
    <a class="p-author h-card" href="">W. Developer</a> on
    <time class="dt-published" datetime="2013-06-13 12:00:00"
      >13<sup>th</sup> June 2013</time
  <p class="p-summary">In which I extoll the virtues of using microformats.</p>
  <div class="e-content">
    <p>Blah blah blah</p>

I have updated page.html, index.html, taxonomy_single.html and section.html to support these new microformats. I have to say this is the most demanding job, good luck!

Once finished, I went to indiewebify to test if it can recognize my new microformats. It works!

Next, I went to to apply for a token. Then I can add a denoflow workflow file to fetch it’s service every day.

Here is the workflow file(workflows/send-webmention.yml):

  - from:
  - from:
  - use: fetch
      - method: GET
          Content-Type: application/json
    run: |
      const json = await ctx.result.json();

Don’t forget to add enviroment variables WEBMENTION_APP_TOKEN to your denoflow workflow file(.github/workflows/denoflow.yml).

- run: deno run -A run


I really like the concept of IndieWeb and their API design philosophy, it took some time but I still think it was worth it. It gave me renewed confidence in the Internet.

You can find the all source code of this blog on Github


Category: Random 
Published:   📝 Edit this page


Have you written a response to this? Let me know the article or tweet URL (Article or tweet content needs to include the URL of this article, learn more about webmention here).

Or, you can simply reply to this tweet:

用推特回复作为静态博客的评论系统,既可以过滤spam,又可以增加推特互动, 也支持抓取推特的响应,然后每天自动同步一次webmention的数据到repo里就能显示了,和我之前的indieweb完美结合。刚给我博客加了一个仿推特的卡片,博客本身依然是静态的!…

— Owen on 2022.07.25   Reply

The response will be automatically collected by bot, and another bot will automatically post it here within 24 hours, I wrote an article about how to achieve this. You can also send your response via mail or Twitter DM

Replies (19)🔗

Likes (40)🔗

Reposts (9)🔗

Mentions (23)🔗

  • 🔗 Adding webmentions to my blog…

  • ‘Adding webmentions to my blog’…

  • <script>alert(0)</script>…

  • Añadiendo webmentions a mi blog… vía @sebdedeyne

  • Adding webmentions to my blog… #php

  • I finally had a chance to style the webmentions on my website 🎉 Thanks to @sebdedeyne’s blog post (…) and @TylerLeonhardt for showing me. Check it out 🤖…

  • Adding webmentions to my blog — Sebastian De Deyne…

  • I've been interested in the IndieWeb since my colleague, Chris R, hosted the first London IndieWeb meetup years ago and at various points I've played with a few bits of it on my website, e.g. OpenID and IndieAuth. As part of my efforts to move away from Twitter and Facebook, I recently joined the very friendly Mastodon instance and I noticed quite a lot of toots about the IndieWeb including one which mentioned the website which walks you through various levels of IndieWeb "compliance". I've been interested in finding out more about Webmentions for a while and this gave me the motivation I needed to give them a try.

    It turns out I had already become a citizen of the IndieWeb, i.e. Level 1 compliance, back in June 2013 and amazingly (to me anyway) that functionality was still working. Level 2 compliance is about publishing on the IndieWeb and Level 3 compliance is about federating IndieWeb conversations.

    Publishing on the IndieWeb

    For level 2, the first step was to markup my home page using the h-card microformat, not to be confused with the older hCard microformat. I started doing this by creating separate hidden markup, but I was unhappy with the amount of duplication. And so, after faffing about with middleman for a while and discovering its nested layouts, I managed to markup some of the existing content to reduce the amount of duplication: h-card & p-name, p-org, p-job-title, p-locality & p-country-name and u-photo, p-note, u-uid & u-url. The validator suggested that it was working OK. So far, so good.

    h-card validation success

    The next step was to markup my blog posts with the h-entry microformat. This was relatively straightforward to implement now that I had a separate blog layout and the validator suggested that it was working OK.

    h-entry validation success

    At this point, I should have added the ability to send Webmentions to other IndieWeb sites, but it's not completely obvious to me how to do this for a static site. I think I could do it by hooking the webmention gem into my GitHub Action-based build, but I decided to skip this step for now given that it's relatively easy to send a Webmention manually using curl and it's not as if I currently blog that frequently!

    Federating IndieWeb conversations

    I also decided to skip the steps about posting replies to other people's posts and adding reply contexts to my own site until I actually want to reply to something someone has written.

    However, I did configure my site to receive Webmentions using the excellent hosted service. This was very easy.

    I then added some very basic code to display Webmentions at the bottom of each blog post closely based on Sebastian De Deyne's implementation. For the moment, I'm using JavaScript running on the client-side, but I can see how in time this might lead to putting an unfair load on

    A better solution might be to incorporate fetching the latest Webmentions and rendering them in HTML into the automated build, perhaps enhancing them with the latest Webmentions using JavaScript. I think this might be how the Jekyll plugin works, but that's a job for another day.

    I checked that my website is receiving Webmentions OK by commenting on a blog post using 🎉🎉

    comment added using

    Clearly I haven't yet fully achieved even level 2 IndieWeb compliance, but I'm pleased with what I've done so far and, more to the point, what I've learnt in doing it. I should also mention that I found lots of useful advice in the following articles:

  • Trying to wrap my mind around WebMentions and how I could implement them without resorting to a third-party provider… I wonder if a link such as this one would receive a webmention/pingback if I just write about it using Hugo.

  • This is a very brief note for my own benefit - if you are even slightly interested I recommend following the links to find other authors who have done a much better job of explaining this!

    I had previously displayed WebMentions on posts via a script that ran on each pageview, queried for mentions relevant to that page and rendered them - entriely based on the original approach documented by Sebastian de Dyne.

    In the most recent iteration of changes I have:

    • adapted the processing of inbound webmentions so they are pulled periodically into data files in the repo by Github actions, then processed when the site is built so they are baked into the rendered static pages
    • added a Netlify build plugin to push outgoing webmentions from my site to the sites I link to

    Processing inbound web mentions

    Key elements:

    • a Github action that runs every thirty minutes and calls a retrieval script
    • the retrieval script which pulls webmentions from and stores them as data files in the source repo for the site
    • a processing script that is run each time the site is built - this reads the raw webmentions and processes them into a form suitable for Hugo to digest
    • changes to page layouts to render a webmentions section

    For all of this I am indebted to Rowan Manning’s approach.

    Sending web mentions when the site is built

    This is the other side of the coin. There are a range of approaches, but I decided to go with a Netlify build plugin configured to only run on production builds.

    All the examples I could find work by processing the RSS feed for the site, and most take the approach of posting webmentions for any remote sites linked from the last (or a configurable last number of) posts. This will fall down if you ever create more than one post in between publishes - rare but not impossible.

    I then found the approach documented by Mark Everitt which compares the RSS feed before and after the build and pushes webmentions for all new items, and have adapted his code.

    Other things

    A note to myself - new functionality based on code developed by others, I need to spend some time to make the repo for this site openable, then make it public. now done - here

  • I’ve added Webmention support to the posts on this blog.

    Webmentions are a method for websites to know that they’ve been linked to (or mentioned) from elsewhere on the web.

    Webmention is a web standard for mentions and conversations across the web, a powerful building block that is used for a growing federated network of comments, likes, reposts, and other rich interactions across the decentralized social web.

    When you link to a website, you can send it a Webmention to notify it. If it supports Webmentions, then that website may display your post as a comment, like, or other response, and presto, you’re having a conversation from one site to another!

    It depends on a couple of things being in place for it all to work, but I’ve implemented the basics to fetch and display any mentions that have been detected by the service.

    I have already been using Github Issues-powered commenting for the past couple of years, so I took the time to consolidate comments and Webmentions in to a single chunk of “interactions” functionality to fetch, cache, and render any comments or Webmentions. This is all done with native JS and could probably be improved further with a framework like Vue.js, but it works fine for now.

    I’m using to recieve Webmentions from Twitter and Reddit interactions via — this will mean that if somebody shares/likes/retweets a link to one of my blog posts on either platform it will display that here below the post.

    I’m using and IFTTT to automatically try and send webmentions to sites I link to from within my posts.

    As you can see it’s a bit complicated, and it feels like it’s held together with duct tape in places, but for now it works!

    Lots of others have written about how they’ve implemented Webmentions on their sites, and these write-ups were really useful when arriving at my own implementation.

    So to share the love, here are some links to those posts:

    And that’s about it really. I’ll be tweeting a link to this post once it’s published and then any replies or likes will hopefully appear at the bottom of the page.

  • 用推特回复作为静态博客的评论系统,既可以过滤spam,又可以增加推特互动, 也支持抓取推特的响应,然后每天自动同步一次webmention的数据到repo里就能显示了,和我之前的indieweb完美结合。刚给我博客加了一个仿推特的卡片,博客本身依然是静态的!…

  • 用推特回复作为静态博客的评论系统,既可以过滤spam,又可以增加推特互动, 也支持抓取推特的响应,然后每天自动同步一次webmention的数据到repo里就能显示了,和我之前的indieweb完美结合。刚给我博客加了一个仿推特的卡片,博客本身依然是静态的!…

  • Webmention looks interesting…

  • 这个idea 挺好的

  • 主动聚合 👍

  • Recently I came across Now, I'm in IndieWeb? and learned about webmentions. I found the concept very interesting and decided to join the webmentions community for my blog.

    What are webmentions

    Webmentions are a way for websites to communicate with each other and notify each other when they link to each other's content. This allows for a more interactive and connected online community, where websites can engage with each other and their users in real-time.

    How do I join the webmentions community?

    To join the webmentions community and start receiving notifications when other websites link to your content, you need to take the following steps:

    1. Register your website with a webmention service, such as This will allow your website to receive webmentions from other sites and also enable you to send webmentions to other sites when you link to them. To do this, you can add the following HTML code to your website:

      link rel="webmention" href="" />
      link rel="pingback" href="" />
    2. Make sure your website follows the microformats2 standard. This may require some effort, but it is important for ensuring that your website can properly send and receive webmentions. You can use a tool like IndieWebify.Me to check if your website is using microformats2 correctly. You may also want to use a tool like ngrok or cloudflare tunnel to debug your website locally, which can save you time.

    3. Start sending and receiving webmentions on your website. Once your website is registered with a webmention service and you have tested your implementation, you can start using webmentions on your site. Whenever you link to another website, you can send a webmention to notify them of your link. And whenever someone else links to your website, you can receive a webmention notification and display that link on your site.

    4. Consider using tools like Github actions and JavaScript scripts to automate the process of sending and receiving webmentions. This is particularly useful for static websites. For example, you can store your webmentions in a webmentions branch on Github, and use a workflow file like this to fetch webmentions and send your webmentions, you also can check my implement for this blog:

      name: Fetch Webmentions
          - cron: "0 0 * * *"
          runs-on: ubuntu-latest
          - uses: actions/[email protected]
              ref: webmentions
          - name: Fetch Webmentions
              run: node pipeline/webmentions.js
          - name: Send Webmetnions 
              run: node pipeline/send-webmentions.js

    By following these steps, you can join the webmentions community and start enjoying the benefits of more interactive and engaging communication with other websites and their users.

    Why join the webmentions community?

    There are many potential benefits to joining the webmentions community and implementing webmentions on your website. Some of the potential benefits include:

    • Increased engagement and connectivity with other websites and theirusers. By receiving notifications when other websites link to your content and being able to notify other websites when you link to them, you can foster a more interactive and connected online community. This can lead to increased traffic and potentially even more opportunities for collaboration and engagement.

    • Improved communication and collaboration with other websites. Webmentions allow for real-time communication between websites, which can be helpful for coordinating efforts and staying up-to-date with the latest developments in the webmentions community.

    • The ability to participate in the evolving web ecosystem. Webmentions are a form of "web 3.0" where websites are more interconnected and interactive than in the past. By joining the webmention community, you can be part of this evolving web ecosystem and potentially benefit from new opportunities and connections that arise.

    Of course, joining the webmention community does require some effort and resources, so it may not be the right decision for everyone. But for many website owners, the potential benefits of joining the webmention community may outweigh the challenges, making it a worthwhile investment.


    In this beginner's guide, we've covered the steps involved in joining the webmentions community and implementing webmentions on your website. By following these steps, you can join the webmentions community and start enjoying the benefits of more interactive and engaging communication with other websites and their users. While there are some challenges and resources required to join the webmention community, the potential benefits may outweigh the challenges for many website owners.

  • 本文通过 DeepL 翻译自 Joining the Webmentions Community: A Beginner's Guide

    最近我看到了 Now, I'm in IndieWeb?,了解到了 Webmentions。我发现这个概念非常有趣,于是决定加入我的博客的 Webmentions 社区。

    什么是 Webmentions

    Webmentions 是一种网站相互交流的方式,当它们链接到对方的内容时,可以通知对方。这使得网络社区的互动性更强,联系更紧密,网站可以与对方和用户实时互动。

    我如何加入 Webmentions 社区?

    要加入 Webmentions 社区,并开始接收其他网站链接到你的内容时的通知,你需要采取以下步骤。

    1. 在 Webmentions 服务中注册你的网站,比如。这将使你的网站能够接收来自其他网站的网络提示,也使你能够在链接到其他网站时向它们发送网络提示。要做到这一点,你可以在你的网站上添加以下 HTML 代码。

      link rel="webmention" href="" />
      link rel="pingback" href="" />
    2. 确保你的网站遵循 microformats2标准。这可能需要一些努力,但这对于确保你的网站能够正确地发送和接收 Webmentions 是很重要的。你可以使用 IndieWebify.Me这样的工具来检查你的网站是否正确使用 microformats2。你也可以使用像ngrokcloudflare tunnel这样的工具,在本地调试你的网站,这样可以节省时间。

    3. 开始在你的网站上发送和接收 Webmentions。一旦你的网站在 Webmentions 服务中注册,并且你已经测试了你的实施,你就可以开始在你的网站上使用 Webmentions 来通知他们你的链接。而每当别人链接到你的网站时,你可以收到 webmention 通知,并在你的网站上显示该链接。

    4. 考虑使用 Github 行动和 JavaScript 脚本等工具来自动发送和接收 Webmentions 的过程。这对静态网站特别有用。例如,你可以在 Github 上的webmentions分支中存储你的 Webmentions,并使用像这样的工作流文件来获取 Webmentions 和发送你的 Webmentions,你也可以查看我的 实现这个博客的。

      name: Fetch Webmentions
          - cron: "0 0 * * *"
          runs-on: ubuntu-latest
          - uses: actions/[email protected]
              ref: webmentions
          - name: Fetch Webmentions
              run: node pipeline/webmentions.js
          - name: Send Webmetnions
              run: node pipeline/send-webmentions.js

    按照这些步骤,你可以加入 Webmentions 社区,并开始享受与其他网站及其用户进行更多互动和参与性交流的好处。

    为什么要加入 Webmentions 社区?

    加入 Webmentions 社区并在您的网站上实施 Webmentions 有许多潜在的好处。一些潜在的好处包括。

    • 增加与其他网站及其用户的接触和联系。通过在其他网站链接到你的内容时收到通知,并在你链接到其他网站时能够通知其他网站,你可以培养一个更加互动和连接的在线社区。这可以带来更多的流量,甚至有可能带来更多的合作和参与机会。

    • 改善与其他网站的沟通和协作。 Webmentions 允许网站之间进行实时沟通,这对协调工作和保持 Webmentions 社区的最新发展很有帮助。

    • 参与不断发展的网络生态系统的能力。 Webmentions 是 "Web 3.0 "的一种形式,与过去相比,网站之间的相互联系和互动更多。通过加入 Webmentions 社区,你可以成为这个不断发展的网络生态系统的一部分,并有可能从出现的新机会和联系中受益。

    当然,加入 Webmentions 社区确实需要一些努力和资源,所以它不一定是每个人的正确决定。但对许多网站所有者来说,加入 Webmentions 社区的潜在好处可能会超过挑战,使其成为一项值得的投资。


    在这个初学者指南中,我们已经介绍了加入 Webmentions 社区和在网站上实施 Webmentions 的步骤。按照这些步骤,你可以加入 Webmentions 社区,并开始享受与其他网站及其用户进行更多互动和参与性交流的好处。虽然加入 Webmentions 社区需要一些挑战和资源,但对许多网站所有者来说,潜在的好处可能超过了挑战。