As noted in the last post, Jekyll does not have a built-in commenting system, but its themes often allow comments to be managed by connecting to third-party services such as Disqus and similar platforms.
The problem with these services is that they can stop working overnight (as happened last year with Muut, which no longer even has a website), or they have opaque usage policies and user data collection practices.
Another issue, which is far from negligible, is that most of these services require users to register before they can comment. Registration is useful for filtering inappropriate comments or spam, but it also acts as a barrier for casual readers who just want to share their thoughts.
Then there is the problem of cost. Some comment management services are paid and not exactly cheap, take Hyvor Talk as an example, which costs 12 euros per month. A price that is more than reasonable for a professional site or a small business that wants to interact with its users – especially since these services often also handle newsletters and other promotional materials – but that is completely out of scale for a toy handmade blog like this one.
Looking for the ideal commenting system
My interest in comment-related issues began a year ago when, after the sudden shutdown of Muut, I observed the enormous work being done behind the scenes by Mimmo, MacMomo, and Paoloo to recover from Muut all the comments from Quickloox – one of the must-read blogs for anyone interested in Apple, Macs, and related topics – convert them to the format of the new commenting engine, and reinsert them neatly into the blog.1
A few months later, I began working on my own transition from WordPress to a Jekyll, and the commenting system was one of the main problems to solve. With WordPress, this isn’t an issue, because comments are integrated and stored in the site’s database along with the text of the post. But with a static site, like the one generated by Jekyll, it is necessary to implement some mechanism to add comments, which by their very nature are dynamic objects.
In hindsight, I could have followed Mimmo’s advice and chosen Comma from the beginning. But coming from WordPress, using a database seemed like the most natural approach.
So I tried Cusdis, Commento, Commento++, Remark42, and Zooment, all database-based commenting systems.1 I carefully followed the instructions step by step, I used Docker, I ran Linux virtual machines on the cloud, I tested services that are supposed to handle everything automatically, like Railway and Vercel. Nothing worked. There wasn’t a single commenting system that worked like it should!!2
I also ruled out all systems that rely on GitHub, such as Giscus, Staticman, or utterances. These are perfect for developers who already have a GitHub account, but impractical for casual readers who would be forced to create yet another unnecessary account. That left only one option. Comma, of course.
Working on Comma
And Comma it was. Comma is written in Go and is distributed only as source code. To compile it, we need a compiler for the Go language. On a Mac, the compiler can be installed by downloading the prepackaged package and following the instructions, or via the usual Homebrew with
$ brew install golang
Similarly, on Linux, Go can be installed by downloading a compressed file and extracting it into the usr/local
directory, or using the package manager commands of our distribution,
$ sudo apt install golang
$ sudo dnf install golang
$ sudo pacman -S go
depending on whether we are using Debian/Ubuntu, Fedora/CentOS, Arch, or one of their countless derivatives.
Once Go is installed, compiling Comma is a matter of seconds,
$ git clone https://github.com/Dieterbe/comma.git
$ cd comma/src
$ go build
where the last command checks that the program compiles correctly. If everything is fine, we can run
$ go install .
which compiles the source code and installs the comma
executable in ~/go/bin/
(as usual, the ~
represents the Home
directory of the account we are using).
Before cloning the Comma repository, I made a fork in my personal account, but only because I wanted to tweak a bit the code a bit.
The first thing I did was to change the filename extension of the comments from .cmt
to .xml
(lines 67 and 105 of my comment.go
file). Comma comments are stored as XML files, and there was no reason to use a non-standard extension. Also, this change makes it easier to open them with a text editor, which will automatically format them for better readability. A small convenience, but very useful during development. To further improve readability, I also added four spaces before each XML tag (lines 71-73 of comment.go
).
Lastly, I removed the requirement to enter an email address when submitting a comment (lines 94-96 of main.go
). My goal was to have a site free of any form of user tracking, thus avoiding many headaches related to GDPR compliance.3 In theory, this could pose some security risks, but do we really think that someone with malicious intent would enter their real email address?
For the frontend – i.e., how the user sees his new comment as well as the list of previous comments – I used most of the original code from the author of Comma, adapting it to work with Jekyll. To that I added Markdown support and filtering of potentially malicious code from comments. For these two features, I took a lot of inspiration from the code that by Mimmo, MacMomo, and Paoloo wrote for Quickloox.
As for the icons associated with each commenter, I chose to generate them with Jdenticon, probably because its symmetrical geometric patterns fit my personality better.
The final appearance of the comments seems quite pleasant and well integrated with the rest of the site, and the localization works well, even in small details like the more prominent thin line under “Add a comment,” that changes depending on whether the text is in Italian or in English.
All the frontend code is in _includes/custom/comma-comments.html
. While I was at it, I also added a small JavaScript function to the post page (_layouts/post.html
) that allows users to jump back to the top of the post with a single click. I originally needed it during development, but I believe it could be useful for readers as well, so I left it in the final code.
Putting all together
Once the comment system and the code to display them on the site are ready, we need to make everything work together. First, we need to create a folder to store all the comments,
$ cd
$ mkdir ~/comments
and start Comma manually,
$ ~/go/bin/comma ~/comments localhost:5888
$
telling it it to listen for new comments on port 5888
of the local computer localhost
and save them in the ~/comments
folder. The last step is to add a line to _config.yml
to connect Jekyll to the comment server
#--- Comma comments ---
commentserver: http://localhost:5888
and everything should work on the first try.
If instead of a physical computer we are using a cloud virtual machine, we will need to replace localhost
with the machine’s reverse DNS name
(see the previous post). However, the exact steps depend on the service we are using, so I can’t be more specific.
On a real site, things get a bit more complex, for example, because one needs to use the secure https:
protocol instead of simple http:
, which requires proper web server configuration. But again, the details depend on the web server, the configuration of installed services, and so on, making it impossible to explain everything without writing a whole manual.
However, I can say for sure that a real website requires Comma to be started automatically, just like the web server that manages the site.
Assuming that the site is running on a Linux server (in the next post, I will explain why using a Mac as a web server doesn’t make much sense) and that Comma was installed by the user webuser
, in order to start Comma automatically on every system reboot (as well as when the program stops unexpectedly), we need to run
$ cd /etc/systemd/system
$ sudo touch comma.service
which creates an empty configuration file called comma.service
. We need to add the following lines to this file,
[Unit]
Description=comma backend server
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/home/webuser/go/bin/comma /home/webuser/comments :5888
Restart=always
RestartSec=1
User=webuser
Group=webuser
[Install]
WantedBy=graphical.target
making sure to replace webuser
with the actual username of the user who installed Comma. Running,
$ sudo systemctl enable comma
activates the automatic startup mechanism, allowing us to almost forget about Comma’s existence. To manually interact with the service, we can use the following commands,
$ sudo systemctl status comma
$ sudo systemctl stop comma
$ sudo systemctl start comma
which are useful for checking the status of the service or manually stopping and restarting it. These commands are particularly useful during debugging, but can also be helpful in production, so it’s good to know they exist.
Conclusions
I had originally planned to end this long journey through the technical description of the new site here. However, while writing this post, I realized that a few words about hosting might be useful. And that will be the subject of the next post.
-
And not even a small database like SQLite! All these comment systems use heavyweights like MariaDB or PosgreSQL. ↩ ↩2
-
If I were mean, I might think the instructions were wrong on purpose to push me to use their paid cloud solutions. But I am a good guy. ↩
-
I have nothing against GDPR. In fact, I think it is a very useful regulation, at least in theory. In practice, however, it does little to truly protect user privacy and ultimately becomes a not-so-useful bureaucratic burden. ↩