How to Add Comments On a Website

ยท

3 min read

Introduction

Adding comments to a Jamstack website is a challenge. The main reason for this is because comments require some sort of database, and (one of) Jamstack's selling point is that it doesn't need one! You can choose to connect a database such as Firestore or AWS - but we're not going to do that because it's

  • challenging
  • time consuming
  • costs money!

In this article, I'll show you how to connect utterances to your React based application.

What Is Utterances?

Utteranc under the hood interacts with the GitHub api to store all of your comments in the issues tab. According to their website, some of the pros of using utteranc are:

  • Open source. ๐Ÿ™Œ
  • No tracking, no ads, always free. ๐Ÿ“ก๐Ÿšซ
  • No lock-in. All data stored in GitHub issues. ๐Ÿ”“
  • Styled with Primer, the css toolkit that powers GitHub. ๐Ÿ’…
  • Dark theme. ๐ŸŒ˜
  • Lightweight. Vanilla TypeScript. No font downloads, JavaScript frameworks or polyfills for evergreen browsers. ๐Ÿฆ๐ŸŒฒ

I don't know about you, but this sounds like a great comment solution.

Adding Utterances To A React Website

If you want to add Utteranc to a simple html site, all you need to do is paste in a <script> tag. Unfortuantly, in React, we can't do this. We need to create a custom component.

Step 1: Create a GitHub repo

The first step is to create a GitHub repo to store your comments. You can use the same repo that your website is pushed to, however, I recommend creating a new one just for the comments. You can then name this comments-your-website-name - or another name if you feel so inclined.

2.png

โ— Make sure this repo is public and that Utterances is authorized. โ—

Step 2: Create The React Component

Next, create a component named Comments.js in your app.

Add the following code:

import React, { Component } from "react";

export default class Comments extends Component {

    constructor(props) {
        super(props);
        this.commentBox = React.createRef(); // use ref to create our element
    }

    componentDidMount() {
        scriptEl.setAttribute("theme", 'github-light');
        let scriptEl = document.createElement("script");
        scriptEl.setAttribute("src", "https://utteranc.es/client.js");
        scriptEl.setAttribute("crossorigin", "anonymous");
        scriptEl.setAttribute("async", true);
        scriptEl.setAttribute("repo", "your-repo-name-here"); // i.e. bjcarlson42/comments-coffeeclass.io
        scriptEl.setAttribute("issue-term", "url"); // you can change 'url' with other options
        this.commentBox.current.appendChild(scriptEl);
    }

    render() {
        return (
            <div style={{ width: '100%' }} id="comments">
                <div ref={this.commentBox} />
            </div>
        );
    }
}

As you can see, we are doing the following:

  • Create a class named Comments which extends Component
  • Creating our element using React.createRef()
  • Using componentDidMount() to set all the properties

Be sure to include your repo name on this line:

scriptEl.setAttribute("repo", "your-repo-name-here");

Be sure to add your username too. For example, I would do bjcarlson42/comments-coffeeclass.io and not comments-coffeeclass.io.

Dynamic colorMode

If you want to dynamically change the color mode, you can do that too. Here is an example of that using Chakra-UI.

import React, { Component } from "react";

export default class Comments extends Component {

    constructor(props) {
        super(props);
        this.commentBox = React.createRef(); // use ref to create our element
    }

    componentDidMount() {
        // dynamically getting color mode
        let colorMode = localStorage.getItem('chakra-ui-color-mode');
        const utteranceTheme = colorMode === "dark" ? "github-dark" : "github-light";
        scriptEl.setAttribute("theme", utteranceTheme);

        // or
        scriptEl.setAttribute("theme", 'github-light');

        // rest
        let scriptEl = document.createElement("script");
        scriptEl.setAttribute("src", "https://utteranc.es/client.js");
        scriptEl.setAttribute("crossorigin", "anonymous");
        scriptEl.setAttribute("async", true);
        scriptEl.setAttribute("repo", "your-repo-name-here"); // i.e. bjcarlson42/comments-coffeeclass.io
        scriptEl.setAttribute("issue-term", "url"); // you can change 'url' with other options
        this.commentBox.current.appendChild(scriptEl);
    }

    render() {
        return (
            <div style={{ width: '100%' }} id="comments">
                <div ref={this.commentBox} />
            </div>
        );
    }
}

Finally, we return the actual html:

render() {
        return (
            <div style={{ width: '100%' }} id="comments">
                <div ref={this.commentBox} />
            </div>
        );
    }

1.png

Make sure to add the style={{ width: '100%' }} otherwise your comment box will be squished. The id=comments is optional.

Final Deployed Version

Now, go ahead and test it out by importing the component anywhere in your application! If you have questions feel free to leave them in the comments below.

ย