Comments for static pages? - Part 1

4 minute read Published: 2020-01-21
tech

This is actually a static page hosted by GitHub, powered by Jekyll. But how to get a comment section?

🔗Give Me Comments

Weeeelll.... You could use a service like Disqus.

Or, you use the idea from damieng.

Jekyll has a neat feature: you can place data files under _data and access in Liquid templates.

And that's more or less the starting point. Add comments as data and render them via Jekyll (utilizing Liquid).

Using the folder _data/comments/{slug}/ to place comment files in. (slug being the "slugified" post name.) The actual files can be in a few formats, but I used yaml. Here is an example comment:

---
id: 1579711318_617889634
ref: basil-timeouts
message: Testing comments
name: Bytekeeper
url: ""
date: 1579711318

id is the id of the comment and the base name of the file: 1579711318_617889634.yml. ref is a reference for what the comment was for. Ie. a slug or the id of another comment (not yet working here). message is too complicated to explain... really. So is name. url is the website a user gave and will be used to render the commenter's name as a link to the site. date a simple timestamp and, as you might have noticed, part of the id.

But having the comments stored as data will not be enough, unless I can convince people to check out the GitHub repo for comments.

🔗Render Me Comments

This one will be quick. I use a modified version of damieng's _includes. Since I modified the structure a bit I had to adapt it. I also changed the layout bit, the final version can be seen down here (unless it does not work in which case: bummer).

For now they look ok but will certainly need more fine-tuning, especially once it's possible to reply to individual comments as well.

Storage place for comments ✓

Rendering comments ✓

Adding comments: ❌

🔗Add Me Commentse

This could be as simple as people wanting to comment grabbing a fork of my repository and adding a comment file in data and creating a PR for it. I'm pretty sure this avoids all comment spamming bots and requires almost no moderation.

You don't want to fork? Ok, I'll give you commit r... waaait.

So basically, using damieng's idea:

🔗Step 1: Create a service that accepts comments

This could be any form of (micro) web service. Damieng used Azure Functions. But Amazon Lambda or Google Functions would be fine too. But I'm oldschool... I already have a VPS, so I use CGI!

I'm also a experienced Java developer, so I used Kotlin. J/K of course I used Rust.

I learn Rust as I go (I already tried that once but the burrow checker tried to murder me in my sleep), so take everything here with a grain of salt.

So, let's start with some Rust code. There is this really nice library called serde which has a ton of serializers and deserializers for various formats. Like urlencoded which is what a simple form post will send.

Now let's write the code to process a POSTed comment:

#[derive(Deserialize)]
struct Post {
    r#ref: String,
    message: String,
    name: String,
    url: String,
    redirect: String,
}

For those who have never seen C, a struct is like a class: A container for fields.

That's it! The derive attribute with the Deserialize argument will create the code to dump in a urlendcoded string and get out an instance of Post: {% highlight Rust %} let post: Post = serde_urlencoded::from_bytes(body.as_slice()).unwrap(); {% endhighlight %}

I omitted the boilerplate code to read the data from stdin - which is how you get data with CGI. The full code can be seen in my GitHub repo.

🔗Step 2: Create a branch and PR automatically

Creating a branch and pushing it should be fairly simply with GIT's CLI. But for the PR, the GitHub API will have to be used.

It can also be used to create a branch and (!) even create a file in there. So I just have to use a GitHub API Rust implementation to solve this. Actually, there are a few - but they are mostly unmaintained. They also don't allow the shenanigans I need.

To be continued