Adding comments to blog posts in Jekyll using Staticman

8 minute read

Note : I’ve disabled the comments for now from all of my pages. I’m facing wierd spam bots adding lot of comments so till I fix it, it won’t be available on this blog site.

This article will be about integrating comments feature to a Jekyll static site using Staticman V2/V3. We will be going through all the steps without going in deep into why a particular step is needed. If you want to know in detail how the whole integration works, you can refer to this blog post by Travis Downs.

Staticman is a Node.js application that receives user-generated content and uploads it as a data files into GitHub/GitLab repository. This allows us to have dynamic content in a fully static website, if the site is built automatically after each push to GitHub/GitLab. Alternatively if you are hosting your website in a different place, then you will have to use some kind of trigger like GitHub actions to rebuild and deploy yout application.

The way staticman works is, we have an instance of staticman running in cloud (Heroku, etc) and that instance has access to another GitHub user, and the GitHub user is added as a collaborator for your blog repository. Whenever a new comment is available, the JavaScript in the static page makes a REST call to our staticman instance (API Bridge) and the staticman will raise a PR into your blog repository with the contents of the comment. If automerge is enabled, then the PR is merged and a new version of your static site is built by GitHub and changes reflects. Ideally it takes around 5-10 sec for a comment to appear, but may vary depending on the size of your website.

Using existing Staticman Instance

It is not necessary to host your own own instance of staticman. You can use an already hosted instance, like my instance (https://staticman-for-girish.herokuapp.com/). To use an existing instance, first add the bot account (staticman-for-girish in my case) to your blog repository as a collaborator, and after sending the invite, call the staticman hosted url to accept the invitation in the following format :

https://<hosted instance name>.herokuapp.com/v2/connect/<your github username>/<your blog repo>

Ex: If the GitHub username is johnsmith and repository name is johnsmithblogsite then the above url, for calling my hosted instance will be https://staticman-for-girish.herokuapp.com/v2/connect/johnsmith/johnsmithblogsite. If the response is OK!, then the staticman instance’s bot account is added as collaborator. Now you can skip next two sections and check configuring the staticman instance in your code. If not you can proceed below to setup your own staticman instance, by first creating a github bot account, then deploying the staticman instance.

Setting up Github Bot Account

Here we will be creating a new bot account to set up a new staticman instance. If you have used the above method of using existing hosted staticman instance, then skip this and next section and go to configuring staticman into your blog site.

First thing what we need to do is create an account in GitHub which the staticman instance will use to submit pull requests to your blog repository. You can use your own existing account, but I woudn’t recommend it and instead suggest to create a throwaway account. Lets call our bot staticman-bot for this tutorial. To create a github account, you would need a new email id which is not yet registered in GitHub. But the best part is you can still use your existing Gmail ID if you want to. We will have to make a small alteration into the email address. If your existing email id is [email protected], then you will have to add +staticman-bot to the address before @gmail.com. While this change won’t create a new account but refer to existing account, and the part after + is ignored whenever a mail is sent to [email protected], it is actually being sent to [email protected]. But for GitHub, this is a new email id so it allows us to create a new GitHub account with [email protected].

After creating a new GitHub account, lets call it bot account, we will need to add this new account as a collaborator to your blog repository, which you can do by going to your blog repository > Settings > Manage access > Add the GitHub bot account as a collaborator, then login into your bot account and accept the invite. This will allow your bot account to contribute to your blog repository without having access to other repositories in your account.

Next step is to generate a GitHub personal access token for your bot account. For this, login into your bot account, then click on your profile and go to Settings > Developer Settings > Personal access token > Generate new token. Give your token a descriptive name, like GitHub PAS for Staticman Instance. New select all of repo and user access in scopes, then generate the token. Copy the token and keep in a safe place, you won’t be able to copy it later. You can refer this GitHub Docs for more information on creating a GitHub PAS.

Deploying Staticman Instance in Heroku

While we are using Heroku, one can use any other cloud provider. There is a detailed tutorial on how to deploy your own staticman instance in Heroku by Willy McAllister, but here we will be covering the same without the detailed explanations.

First thing what we need to do is fork this GitHub repository of Staticman by Eduardo Bouças. We will be using this code to setup our own staticman instance.

Then setup a free account at Heroku. Once you have logged in into the account, you can manually create an app and setup the git repository. There is an easier way to do it, by clicking on Deploy to Heroku button in readme of repository. This is the suggested method. If you want to set it up manually, then first create an app in heroku, give it a name and region. Then go inside the created app, to deploy submenu and select the git repository., then select the dyno and deploy your code. You can either select your forked repository or the main repository.

Next you will have to add the config variables. Staticman uses two variables, GITHUB_TOKEN for authenticating to GitHub to create PR, and RSA_PRIVATE_KEY which is a private key of RSA Key Pair. The key pair is used to encrypt secrets which will be available in your static site like reCAPTCHA, etc. The secrets will be encrypted with the public half of the key pair, and decrypted in the staticman instance.

Use the following code on your local to generate the pair:

ssh-keygen -m PEM -t rsa -b 4096 -C "staticman key" -f ~/.ssh/staticman_key

You can access this ssh keys from ~/.ssh/ folder. There will be two keys generated, staticman_key and staticman_key.pub, the latter being the public key and former being the private key. Alternatively, you can get a key pair online. Below are a sample of key pairs:

RSA Public Key:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+PR4b6xUBd+AiSkxCnmX0RHDUsN70rzOfhFhaN2Be7Aml0WD5AmMxVDVF6ld0cwyDdaQlcUOQN8Sdc/mNcwgi0xMmES6etyLaybVlb+1WefbyoNddgG14I8UnXAMgM26k8Cc7CoITkjSnNxnHw3jXS+L9ViCfCBascW5D03BvSQ==

RSA Private Key:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC+PR4b6xUBd+AiSkxCnmX0RHDUsN70rzOfhFhaN2Be7Aml0WD5
AmMxVDVF6ld0cwyDdaQlcUOQN8Sdc/mNcwgi0xMmES6etyLaybVlb+1WefbyoNdd
gG14I8UnXAMgM26k8Cc7CoITkjSnNxnHw3jXS+L9ViCfCBascW5D03BvSQIDAQAB
AoGAFqF2JruTOuK8ENA2XLlzpviKVJ760vBRq5EGoqrSRdB+AFIVX2H7k1dxY/ER
+Moj67KPtZ2Q/EPKGbH9dqh/x9JDDq7wTbZoJVjEMby4wzttjBWDswEoZvEUlRYK
xMMqDha5Dgo56G82s+vta/umkrvTM9mjegV3xFUe8wORALUCQQDbPAM96HwBkSgy
+80D6BrMXLBq7wEq7zT2CYab2ftQHPGA/EAztGZmMXNOOs6Pm1fj4co8duzFePgS
nb8BtSq1AkEA3iRJZl1WcbN+h5o+rMYMpF/mYcBQ8cfYZUQ6zExqrO6LHEBjgPZ8
mEcJwo5hM3Py/k6F+d/z++COwHoSpZ2KxQJBAK+/LzYcvfQfomMkmhgso/b5wu8m
RABgHEu0HTWpDB8P5MYq8WjBkGkR8UZgPCDBPjbPVWkdSPeQ3wVFcc5zphUCQFeO
R9vv+A1yqPF7qy5gFUWIgv6OVZkmorUvUlmJ2RX2I6BsBIwlGvDONxuXENq93c28
V3QogDsLxFg7BTR/xt0CQHYlJqZUM9fS+AHaPOAdqAKBZ2gbJf1oe24FSXWbEd/2
JpkR4+8ZuYpNE0WEtySN0luChXnqIwbMKiSqyfgxnu0=
-----END RSA PRIVATE KEY-----

Now inside Heroku, go to your staticman instance in apps > Settings > Config Vars, and add GITHUB_TOKEN (The GitHub PAS Token of the bot account) and RSA_PRIVATE_KEY (The whole of private key like highlighted above). After saving the config keys, the app should redeploy and URL to the app should return the following message

Hello from Staticman version 3.0.0!

If the above message doesn’t show up while accessing your staticman instance, then some step has went wrong, try to reverify if all the steps mentioned above are followed.

Configuring Staticman in your blog repository

We will need to add a staticman.yml file at the top level of your blog repository. Here is a sample file for the contents, which you can copy and modify acccordingly.

I am using Minimal Mistakes theme, so each theme has its own way to add comments. If your theme doesn’t has one, then Travis Downs has a section in his blog on how to add it.

Next we will have to make few modifications in _config.yml like below, for Minimal Mistakes, if not already present :

repository: <username>/<repository name>
# For Comments
comments:
  provider: staticman_v2
  staticman:
    branch: <your branch>
    endpoint: https://<your instance>.herokuapp.com/v2/entry/

Usually the staticman url will be of the format https://<your instance>.herokuapp.com/v2/entry/<github-username>/<blog-repo>/<branch-name>/comments, so modify accordingly. Also each theme will have a different way to provide this url.

Adding reCaptcha

We will need to add reCaptcha or alternative, to submit comments unless we want to get bombarded with spam and bot comments. Head over to reCaptcha, sign up/login and create a new site. Use v2 checkbox variant, because I’ve used that, and coudn’t find any resources on how it will look on v3 checkbox. You will need the reCaptcha site key and secret key for configuration. If you are stuck at any step, you will find lot of online examples explaining the same.

Next step is to add site_key and secret_key into config.yml and staticman.yml. The site_key will be used as it is, but the secret key needs to be encrypted using our hosted staticman instance. To encrypt the secret key, call the staticman instance with below url, replacing YOUR_SITE_KEY with site_key.

https://<your instance>.herokuapp.com/v2/encrypt/YOUR_SITE_KEY

This will return a string of characters which is the encrypted, which you will have to configure in config.yml and staticman.yml. For Minimal Mistakes, add the below kind of config to both files.

reCaptcha:
  enabled: true
  siteKey: <your site key>
  secret: <your encrypted secret>

If you are not using Minimal Mistakes theme, then check how you can add it to your comments changes online. If you added the above changes and still are unable to see the comments, then run JEKYLL_ENV=production jekyll serve instead of jekyll serve. By default GitHub Pages runs your site in production environment.

The comments are stored in the location mentioned in the staticman.yml file. It usually contains an _id, comment message, name, email (encoded using md5), url if provided and timestamp.

Thats it! If all the steps went well and you pushed your changes to Github Pages, then you should have a running comments section for the blog posts. If not, comment down in this post and we can check and get back!

This blog post is majorly inspired by Willy McAllister, Travis Downs and Minimal Mistakes, just a stripped down version on what to do to get it done.