87 lines
4.6 KiB
Markdown
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).
|