From the dawn of times (when I started this blog) I was using Disqus solution for comments on pages. I had almost no complains towards it, but recently I learnt that one can use GitHub issues as a source of comments! That sounds just too cool not to try.

GitHub comments

This article will focus on adding GitHub comments to a Hugo-based blog, but actually you can add those anywhere you want, would it be a different blog-engine or something completely different altogether.

Why switch from Disqus

I actually cannot say anything bad about Disqus. It works just fine and it has a free basic subscription plan. My only issue so far is that when I try to use Disqus comments from mobile devices, every action requires several clicks till it finally reacts and also text editor is not too nice to work with.

Some people complain about ads, and I saw advertisement blocks integrated into Disqus comments sections on other sites. At the same time I don’t have any at mine, and as far as I understood personal blogs are not required to have any ads. Nevertheless, it’s a bit concerning issue as requirements might change, and I can end up with ads in my comments too (or with a costly subscription plan).

Others complain about performance. There are graphs showing enormous amount of network requests done by Disqus on people’s pages. I cannot confirm these complains because here’s what I see in my browser:

Disqus network performance

Which is not too bad. Perhaps Disqus improved this issue over the time, and it was nastier in past.

Finally, almost everyone complains about the tracking issue, that Disqus collects data and uses it in all the bad ways possible, which is most likely to be the truth. But then again, using a free subscription plan, I cannot really complain about it - that’s the usual price for the free stuff on the internet.

So, while I was more or less happy with Disqus, I decided to check out if there is anything better nowadays.

What’s the alternative

And rather often I see Commento being referenced as a better alternative to Disqus. They highlight no tracking, focus on privacy and other nice things. There is even a mechanism to import your Disqus comments.

I almost started using Commento, even though they don’t have a free subscription plan, but then it turned out that their “pay what you want” has a minimum of 3 USD per month - that’s just too expensive for me.

And then I discovered that once you added a bank card to your Commento account, it is not that easy to delete it:

Commento billing information

I also didn’t like this part:

Note that removing your payment information will remove all domains. I promise this isn’t a dark pattern…

Well, certainly looks like one. If not dark, then retarded at best.

Needless to say, I decided not to use Commento and continue looking. And from lots of other options, I discovered this beautiful idea of using GitHub issues.

Using comments from GitHub issues

I took most of the information from these two articles:

  1. GitHub hosted comments for GitHub hosted blogs - note that it was written back in 2011, so this functionality was available all these years;
  2. Replacing Disqus with Github Comments.

How it works

Every page you want to have comments on should have its own GitHub issue, which is just perfect in case your blog is hosted on GitHub pages. Why GitHub issues? Because they have great and open API.

And then every such page just calls this API to fetch the comments:

Fetching comments from GitHub issues

Simple and nice, but there are some obvious downsides:

  • one has to manually create a new GitHub issue every time there is a new post/page. Although, this can be automated too;
  • only people with GitHub accounts will be able to comment on your posts/pages. Which is the audience we mostly care about, innit. But jokes aside, that might be a serious issue as lots of people have no idea about what GitHub is, and some developers actually don’t like GitHub (especially now when it belongs to Microsoft).

Other than these two problems - what a splendid idea! Let’s see how to implement it.

How to add it to Hugo

Create the following partial (/layouts/partials/comments.html):

<script>
  var id = {{ .Params.GHissueID }};

  if (id)
  {
    let url = "https://github.com/YOUR-ACCOUNT/YOUR-REPOSITORY/issues/".concat(id);
    let api_url = "https://api.github.com/repos/YOUR-ACCOUNT/YOUR-REPOSITORY/issues/".concat(id, "/comments");
    
    var commentsDiv = document.getElementById("comments");

    let xhr = new XMLHttpRequest();
    xhr.responseType = "json";
    xhr.open("GET", api_url);
    xhr.setRequestHeader("Accept", "application/vnd.github.v3.html+json");
    xhr.send();

    xhr.onload = function()
    {
      if (xhr.status != 200)
      {
        let errorText = document.createElement("p");
        errorText.innerHTML = "<i>Comments for this post yet are not opened yet (or you have GitHub scripts disabled).</i>";
        commentsDiv.appendChild(errorText);
      }
      else
      {
        let comments = xhr.response;

        let mainHeader = document.createElement("h2");
        mainHeader.innerHTML = "Comments: ".concat(comments.length);
        commentsDiv.appendChild(mainHeader);

        let issueLink = document.createElement("p");
        issueLink.innerHTML = "<i>You can leave a comment using this <a href='".concat(url, "'>GitHub issue</a>.</i>");
        commentsDiv.appendChild(issueLink);
        
        comments.forEach(function(comment)
        {
            let commentContent = document.createElement("div");
            commentContent.setAttribute('class', 'gh-comment')
            commentContent.innerHTML = "".concat(
                "<div class='gh-header'>",
                  "<img src='", comment.user.avatar_url, "' />",
                  "<div style='margin:auto 0;'>",
                    "<b><a class='gh-username' href='", comment.user.html_url, "'>", comment.user.login, "</a></b>",
                    " commented at <em>", new Date(comment.created_at), "</em>",
                  "</div>",
                "</div>",
                "<div class='gh-body'>",
                  comment.body_html,
                "</div>"
            );
            commentsDiv.appendChild(commentContent);
        });
      }
    };

    xhr.onerror = function()
    {
      let errorText = document.createElement("p");
      errorText.innerHTML = "<i>Some error loading comments.</i>";
      commentsDiv.appendChild(errorText);
    };
  }
</script>

Maybe add some styles:

#comments {
    margin-top: 30px;
}

.gh-comment {
  border: 1px solid #d1d5da;
  margin-top: 15px;
}

.gh-header {
  display: flex;
  color: #586069;
  background-color: #f6f8fa;
  border-bottom: 1px solid #d1d5da;
  padding: 10px;
  font-size: 85%;
}

.gh-username {
  color: #586069;
}

.gh-body {
  padding: 10px 15px;
}

.gh-body code {
  font-size: 120%;
}
.gh-body > div.highlight > pre {
  padding: 10px;
  color: lime;
  font-size: 120%;
  background-color: #000;
  border-radius: 5px;
}

.gh-comment p {
  margin: 0px 0px 10px 0px;
}
.gh-comment p:last-child {
  margin: 0;
}

.gh-header > img {
  width: 24px;
  height: 24px;
  margin-right: 10px;
  vertical-align: middle;
}

And then edit the page layout (/themes/YOUR-THEME/layouts/_default/single.html):

...
<div id="comments">
{{ with .Params.GHissueID }}
  {{ partial "comments.html" $ }}
{{ else }}
  {{ template "_internal/disqus.html" . }}
{{ end }}
</div>
...

What’s convenient here is that if you (like me) already have some old comments in Disqus which you would like to keep, then you have a choice - when Hugo doesn’t find a GHissueID parameter on the page, it will fallback to Disqus.

But what is this GHissueID parameter? Oh, that’s just a GitHub issue ID which you need to put to the page’s front matter. For example, here’s how it looks like in this very post:

---
title: "GitHub comments for a Hugo-based blog"
date: 2019-04-19T12:57:21+02:00
tags: [hugo, web]
GHissueID: 2
---
...

Which means that comments for this page are collected in the GitHub issue with the ID 2. And if you delete this line from the front matter, then Disqus comments will be used instead.

Below you can see the GitHub comments for this page in action.