Check out "Do you speak JavaScript?" - my latest video course on advanced JavaScript.
Language APIs, Popular Concepts, Design Patterns, Advanced Techniques In the Browser

Octomments - using GitHub as a comment plugin

Octomments - using GitHub as a comment plugin

87% of my readers are using Chrome on desktop. This means that I have the luxury to care less about performance. However I just recently found that this blog has 56 (out of 100) points on Google's pagespeed test. That's not good. The report says that my Disqus comments are blocking the main thread for ~900ms. I want comments on my blog but I also want my users to reach to content as quickly as possible. So, after so many years using Disqus I decided to break with it and use something else.

Using GitHub issues as a comment plugin

I started searching for alternatives of Disqus. Nothing really grabbed my attention. Either the solution was paid or it provided the same if not worst results. Then I found this article where Don Williamson suggests that we can use GitHub issues as a placeholder for comments. And indeed GitHub provides a nice API for reading and adding comments. So why not?

I found the idea interesting and checked if there is already a library providing such functionalities. And yes, there were couple of modules - Gitalk, Gitment, Utteranc. Not good enough though 👿 Some of them asked me to create a GitHub OAuth app and share publicly its client id and client secret. I scratched those immediately. Another one contained a bit more features than I needed and some sort of a bot that I didn't understand completely. Anyways, as I like to do very often, I decided to create my own library. I'm really really good at re-inventing the wheel so I started working on Octomments (https://ocs.now.sh).

The idea was simple - I will use the GitHub API to fetch an issue and its comments. Then ask the user for a comment and again using the same API post a new comment to the same issue.

Pros and cons

Here are couple of things which I found while developing the library. First the positive sides:

  • It's free 💰
  • No ads.
  • You get notification system out of the box. You, as owner of the GitHub repo, will receive emails for every comment.
  • No vendor locking, you own the repo, the issues and their comments.

Cons:

  • To post a comment the users need to have a GitHub account.
  • A little work upfront. Someone should create the issue on GitHub.
  • GitHub's API has request limits.

I spent two weeks tackling the problems and I believe Octomments solves them well.

How it works

Code wise I split Octomments in three parts - Core client, Renderer/UI and server. The core client communicates with GitHub's APIs and dispatches events. The renderer is picking those events and renders UI. The server contains two JavaScript lambdas. One for authentication and one for comments fetching. I documented how to deploy those to Zeit's infrastructure but I bet will be fairly easy with other providers too.

This separation allows complete customization. There could be a completely different UI or different GitHub app that the users grant access to. I put some useful docs here github.com/krasimir/octomments if someone wants to take this path.

The consumers of the library don't need to know all these details because there is ocs.min.js file that contains both core client and renderer. And the server is already deployed to https://ocs.now.sh. The client that comes as part of the ocs.min.js file is already pointing to that server. So all they have to do is to install Octomments app on their repo, loading a .js, .css file and run some JavaScript on the page.

I mentioned a couple of problems above and I want to tell here how Octomments addresses them.

Comments fetching

GitHub provides an endpoint for listing issue comments. A simple GET request returns the data. That's of course not happening without a price. It is still free but if we are not authenticated there is a limit of 60 requests per hour from one IP. After that the request fails. Initially the users are not authenticated and they may never be. Octomments first tries making the request to GitHub directly. If it fails it goes to the Octomments server deployed at ocs.now.sh. Then the lambda there makes an authenticated request to the same endpoint and for such request the limit is increased to 5000 requests per hour. This sounds good but it is not perfect because if there are many people using the library they will potentially share those 5000 requests. The solution for that is to spin up your own Octomments server. It's not a big deal. More about that here.

Posting a new comment

Again there is a GitHub endpoint for that. The challenge here is getting the user's token. The most convenient way to do that is via the Web application flow. That type of authorization requires us to create a GitHub OAuth app or a GitHub app. Yes, there is a difference between the too. I first decided to use GitHub OAuth app for fetching the token. This approach means no actions from the developer using the library. However, later I realized that using such app also means asking for public_repo permission access. That is the bare minimum scope to allow comment posting. public_repo is a bit too much because it includes read/write access to code, commit statuses, repository projects, collaborators, and deployment statuses for public repositories and organizations. Lots of stuff for posting a single comment on a public repo. So, I changed direction and chose GitHub app. I created one with only read/write issues access. The developer then has to install it on his repo. The users authorize it to post comments on their behalf. For the end user this step is hidden. They just authorize in front of GitHub.

Automatically creating GitHub issues

GitHub allows that too. Via a POST request. I however decided to not do this automatically. I tried but it made the library complex which I believe is not necessary. The Octomments server offers such endpoint which is protected and it is intended to be used in a machine-to-machine fashion. I personally initiate a request to my own private instance. The lambda there creates the issue for me and returns its number. I then associate my new article with that number.

Quick start with Octomments

Go here and install the Octomments app on the repo which you want to host your comments.

Then include the following two files onto your page:

<link rel="stylesheet" href="https://unpkg.com/octomments/build/ocs-ui.min.css" />
<script src="https://unpkg.com/octomments/build/ocs.min.js"></script>

In the end place the following code somewhere at the bottom of your page:

<div id="octomments"></div>
<script>
  Octomments({
    github: {
      owner: '<username>',
      repo: '<repo name>',
    },
    number: <issue number>,
    renderer: [OctommentsRenderer, '#octomments']
  }).init();
</script>

Of course you have to place your GitHub username, repo and issue number. The result could be seen on every page of this blog including this one. Just scroll to the bottom.

If you decide to go with your own UI or spin up your own server check the documentation.

If you want to make Octomments part of your single page app there is octomments npm package and octomments-renderer npm package.

The result

Here is how the report for this page looked like when I was using Disqus.

with disqus

Here is how it looks now:

without disqus

It definitely reduced the script evaluation time which was the reason for my bad score.


The official site of Octomments is https://ocs.now.sh. The documentation is posted on the GitHub's repo at https://github.com/krasimir/octomments. Give it a star if you think that this whole thing makes sense.

If you enjoy this post, share it on Twitter, Facebook or LinkedIn.