Replacing Disqus with Mastodon Comments

I replaced Disqus with Mastodon-powered comments on this blog. No tracking scripts, no ads injected into my pages, no third-party account required to leave a comment.

The idea came from Mike Perham’s post earlier this year. Write a blog post, publish a toot announcing it, drop the toot ID in the frontmatter, and the comments section pulls replies from the Mastodon API.

How it works

When someone replies to the toot on Mastodon, those replies show up as comments. Readers who want to comment need a Mastodon account, but given my audience, that’s not a problem.

The implementation is a web component based on Daniel Pecos Martinez’s mastodon-comments. The core logic (fetching the toot’s context from the Mastodon API, rendering replies, showing boosts and favorites) is his. I adapted the markup and class names to match my blog’s structure and styling. No JavaScript framework. No cookie banner. No disqus.com in the network tab.

The setup

1. Add the web component to your assets and load it in <head>:

<script src="{{ "js/mastodon-comments.js" | relURL }}" defer></script>

2. Configure the Mastodon account in config.yml:

Params:
  mastodon:
    host: "ruby.social"
    user: "jweslley"

3. Replace the comments partial. The old comments.html called Hugo’s built-in Disqus template. Now it renders the web component when a tootId is present in frontmatter:

<section id="comments" class="comments">
  {{- with .Params.tootId -}}
    <mastodon-comments
      host="{{ $.Site.Params.mastodon.host }}"
      user="{{ $.Site.Params.mastodon.user }}"
      tootId="{{ . }}">
    </mastodon-comments>
  {{- end -}}
</section>

4. Add tootId to the blog archetype, commented out by default:

# tootId:

When I publish a post, I toot about it, then fill in the ID.

5. Remove Disqus from config.yml:

# Before
services:
  disqus:
    shortname: "jweslley"

# After: gone

The workflow

  1. Write and publish the post
  2. Post a toot linking to it
  3. Copy the toot ID from the URL (https://ruby.social/@jweslley/<tootId>)
  4. Add it to the post frontmatter and redeploy

Replies to that toot become the comments section. Boosts and favorites show up as stats in the header.

The one downside: all existing Disqus comments are gone. I didn’t have many, so it wasn’t a big loss.