blog/content/blog/004-comments/index.md

87 lines
4.6 KiB
Markdown

---
title: Comments
date: "2020-09-05T17:56:22.339Z"
description: I would love to hear from you!
---
## Where do comments live?
I built this blog with [`GatsbyJS`](https://www.gatsbyjs.org/), which is optimized for static content. It works great for everything that exists when I build the code and create another docker image. But now I want to add comments from my readers. Which of course aren't static and don't exist on compile-time. So it seems GatsbyJS would not be the right tool for the job.
Luckily, GatsbyJS is expandable. There even is a [guide on how to integrate comments](https://www.gatsbyjs.com/docs/adding-comments/) in a blog on the gatsby website itself. But it assumes you just go and use some external service like disqus (although it does mention several alternatives). I didn't want to outsource that, the whole point of this blog is to run things myself and learn from that.
What I found was [Commento](https://commento.io/). It focusses around privacy and can be [self-hosted](https://docs.commento.io/installation/self-hosting/) instead of using an external service. It even has docker support. I quickly set up my very own instance on my server:
```bash
docker run -d --name blog-commento \
-e "COMMENTO_ORIGIN=https://comments.while-false.de" \
-e "COMMENTO_POSTGRES=postgres://commentoDbUser:SuperSecretPassword@db_postgres/commento?sslmode=disable" \
registry.gitlab.com/commento/commento
```
*(In reality, I use a few more parameters and steps required for my specific hosting setup, which I will explain in a future post)*
So my blog itself can still be static and throught the magic of gatsby's automatic optimization blazing fast, while the dynamic comments are handled by an external server, which I can fully control as I host it myself.
## Include the comments in the blog
Next, I followed the [documentation for commento](https://docs.commento.io/installation/self-hosting/register-your-website/) and registered the blog on my commento instance. Easy.
Now to the tricky part. The static Gatsby.js website must embed the dynamic comments from the commento server. Again, I am lucky and found that [someone already did exactly that](https://itnext.io/adding-commento-to-react-apps-like-gatsby-871824fb57ae). With some small tweaks, this is what I use:
```js
import React, { useEffect } from 'react';
/**
* Helper to add scripts to the page.
* @param {string} src The source path for the script to insert.
* @param {string} id The unique identifier for the script element to insert.
* @param {HTMLElement} parentElement The DOM element to insert the script into.
*/
const insertScript = (src, id, parentElement) => {
const script = window.document.createElement('script');
script.async = true;
script.src = src;
script.id = id;
parentElement.appendChild(script);
return script;
};
/**
* Helper to remove scripts from the page.
* @param {string} id The unique identifier for the script element to remove.
* @param {HTMLElement} parentElement The DOM element to remove the script from
*/
const removeScript = (id, parentElement) => {
const script = window.document.getElementById(id);
if (script) {
parentElement.removeChild(script);
}
};
const Commento = ({ id }) => {
useEffect(() => {
// If there's no window there's nothing to do for us
if (!window) {
return;
}
const { document } = window;
// In case our #commento container exists we can add our commento script
if (document.getElementById('commento')) {
insertScript('https://comments.while-false.de/js/commento.js', 'commento-script', document.body);
}
// Cleanup; remove the script from the page
return () => removeScript('commento-script', document.body);
}, [id]);
return <div id="commento" />;
};
export default Commento;
```
This component itself is evaluated at runtime (it uses `useEffect`, which gatsby understands as non-static). It dynamically loads the scripts required by commento. The commento component is then included in my default blog-post template component by adding the line `<Commento id={this.props.slug} />`. The slug is the part of the URL after the hostname, i.e. `004-comments/` for this page. Thus, commento differentiates which comment belongs to which page.
Now, users can register and directly comment or comment anonymously with a required moderator review (which is me). Also, markdown, up- and downvoting, sorting, sticky, replies and moderation tools are included. Give it a try, I'd love to hear from you!
In the next few days I will tinker around with commento's settings for moderation notification emails, custom styling and comment analytics (number of views and number of comments).