Info
Note that comments are currently disabled on this site.

Setting up a commenting system with Staticman on this site (which uses the Minimal Mistakes Jekyll theme and is hosted on GitLab Pages) has not been easy, but thanks to existing guides (see Useful links below), I managed to figure things out. Here are the steps I followed.

Prerequisites

  1. Create a new GitLab account to act as the bot.

  2. Generate a personal access token for the new GitLab bot account, with the api and read_repository scopes enabled, and store it securely.

  3. Login to the GitLab account which hosts the site repository. In the repository, go to Members and grant the bot account access as a Developer to the repository.

  4. Create an account with a hosting service. I’m using Fly now since Heroku has discontinued its free product plans. See this GitHub issue for more alternatives to Heroku.

  5. [Optional] Sign up for Akismet and reCAPTCHA for spam protection.

Note
Spam protection is optional but highly recommended as the number of spam comments can get overwhelming and pollute the site repository’s merge requests and waste CI minutes.

Preparing Staticman files

  1. Clone the Staticman repository and navigate to its directory:

     git clone https://github.com/eduardoboucas/staticman
     cd staticman
    
  2. Generate a RSA private and public key pair:

     openssl genpkey -outform PEM -algorithm RSA > staticman_key
     openssl pkey -inform PEM -in staticman_key -pubout > staticman_key.pub
    
  3. Create a Procfile with the line web: npm start at the repository’s root:

     echo web: npm start > Procfile
    
  4. Create a file called config.production.json in the repository’s root with the following configurations:

     echo '{
       "gitlabToken": process.env.GITLAB_TOKEN,
       "githubToken": process.env.GITHUB_TOKEN,
       "rsaPrivateKey": JSON.stringify(process.env.RSA_PRIVATE_KEY)
     }' > config.production.json
    
  5. Add config.production.json as an exception to .gitignore:

     echo "\n\!config.production.json" >> .gitignore
    

Deploying the app

Info
You may be charged by the hosting provider depending on your usage. If you’re using a free service, be sure to check what’s included in the free tier prior to setting up your app, and note that you may be asked to provide a payment info.

Refer to the hosting service’s documentation for instructions on deploying a new app (see here for instructions for new Fly apps).

Note
This will likely require usage of the hosting service’s command line interface (CLI). I have not done this as I simply migrated my app from Heroku to Fly. The hosting service’s docs should have all the details.

Set the necessary environment variables:

  • NODE_ENV should be production
  • GITLAB_TOKEN should be the GitLab personal access token generated earlier
  • RSA_PRIVATE_KEY should be the staticman_key private key generated earlier

If using Akismet for spam protection, two additional variables must be set:

  • AKISMET_API_KEY should be the Akismet API key
  • AKISMET_SITE should be the site’s URL

Stage, commit, and push the changes (I’m using a production branch).

Check if the app works by opening https://${appname}.fly.dev/. The message Hello from Staticman version 3.0.0! should appear.

Get a reCAPTCHA key

reCAPTCHA is optional, but it has become a requirement for me due to the number of spambot comments I was getting. Get a reCAPTCHA v2 Checkbox site key for your site’s domain. Then, encrypt the site secret using the https://${appname}.fly.dev/v3/encrypt/${text-to-encrypt} endpoint. The site key and encrypted secret must be entered in the site’s configuration files (i.e. _config.yml and staticman.yml).

Configuring the Minimal Mistakes Jekyll theme

To modify the reCAPTCHA’s theme, copy _includes/comments.html and change line 75 as follows:

                  <div class="g-recaptcha" data-sitekey="{{ site.reCaptcha.siteKey }}" data-theme="{{ site.reCaptcha.theme | default: 'light' }}"></div>

Note
For Minimal Mistakes v4.24.0 and below, be sure to copy the latest available version of _includes/comments.html, i.e. from the latest commit in the default branch, as it includes a new feature (sort comments by date ascending).

Make the following changes to _config.yml in the site repository:

comments:
  provider: staticman_v2
  staticman:
    branch: main
    endpoint: https://${appname}.fly.dev/v3/entry/gitlab/
reCaptcha:
  siteKey: "your_site_key"
  secret: "your_encrypted_site_secret"
  theme: dark  # "dark" or "light" (default)

Paste the following in _staticman.yml in the site repository:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
comments:
  allowedFields: [name, email, url, message]

  branch: main  # your default branch

  commitMessage: New comment by {fields.name}

  filename: comment-{@timestamp}

  format: yml

  generatedFields:
    date:
      type: date
      options:
        format: iso8601

  moderation: true

  akismet:
    enabled: true
    author: name
    authorEmail: email
    authorUrl: url
    content: message
    type: comment

  path: _data/comments/{options.slug}

  requiredFields: [name, email, message]

  transforms:
    email: md5

  reCaptcha:
    enabled: true
    siteKey: "your_site_key"
    secret: "your_encrypted_site_secret"

Note
I’m using unauthenticated comments with moderation. If moderation is set to false, the bot must have elevated permissions (e.g. Maintainer instead of Developer), or the main branch of the repository must be unprotected; otherwise, the bot will attempt to commit directly to the main branch and fail. See this guide on the Performance Matters blog for other configuration options.

Additionally, copy _includes/comment.html and make the following change to line 7, so that no link will appear if a commenter omits the website URL field:

{% unless include.url == nil or include.url == empty or include.url == "" %}

Note
I also changed the date format to match that of my locale, i.e. en-GB.

In _config.yml, I defined the date format:

long_date_format: "%-d %B %Y at %H:%M"

I changed line 16 of _includes/comment.html as follows:

        <time datetime="{{ include.date | date_to_xmlschema }}" itemprop="datePublished">{{ include.date | date: long_date_format }}</time>

I then added the following to the very top of _includes/comment.html:

{% assign long_date_format = site.long_date_format | default: "%B %-d, %Y at %I:%M %p" %}

Stage, commit, and push the changes to rebuild the site.

Go to a post on the newly-built site and submit a test comment. A pull request will be created by the bot with the new comment if the submission is successful. Merge it to publish the comment on the site.

To-do

Nested comments / replies and email notifications.

  1. Staticman Powered GitLab Pages - Solarized Sublime Sekai
  2. Comments with Staticman - Michaels Blog
  3. Staticman With Github and Zeit Now - Blogger Bust
  4. Staticman Repo Setup Errors - Solarized Sublime Sekai
  5. Improving static comments with Jekyll & Staticman - Made Mistakes
  6. Going static part 2: static comments - Made Mistakes
  7. Staticman…The Journey Continues - Dan C Williams
  8. Hugo + Staticman: Nested Replies and E-mail Notifications - Dan C Williams
  9. Adding Staticman Comments - Performance Matters
  10. Staticman: Adding comments to my Jekyll site - Gabe’s Code
  11. Staticman - Solarized Sublime Sekai

Comments

Comments are closed