How To Add Utterances Comment System To Your Gatsby Blog

Overview

This article shows you how to add utterances light weight comments widget to your Gatsby website. The widget is built on GitHub issues.

Limitations of Utterances Comments System

  • Needs Github authentication by users to make a comment
  • There is no reply functionality

Initial Setup

Create Public Github Repository

  • This repository will be linked to Utterance Github Application that we're going to install below.

Install Utterance Github Application

utterance comment

Select the repository that you've created above from the dropdown list:

utterance comment

Create Comments Component

The offical utterances doc instructs us to add the following script tag to your blog template.

utterance settings

Howerver, I use Gatsby framework, so I had to create a React component to configure the settings. Note that the component we crate here is to be imported in our blog post template later.

./src/components/Comments.js
1import React, { useEffect } from 'react'
2
3const COMMENTS_ID = 'comments-container'
4
5const Comments = () => {
6 useEffect(() => {
7 if (!process.env.GATSBY_COMMENTS_REPO) return
8
9 const script = document.createElement('script')
10 script.src = 'https://utteranc.es/client.js'
11 script.setAttribute('repo', process.env.GATSBY_COMMENTS_REPO)
12 script.setAttribute('issue-term', 'pathname')
13 script.setAttribute('theme', 'icy-dark')
14 script.setAttribute('crossorigin', 'anonymous')
15 script.async = true
16
17 const comments = document.getElementById(COMMENTS_ID)
18 if (comments) comments.appendChild(script)
19
20 // This function will get called when the component unmounts
21 // To make sure we don't end up with multiple instances of the comments component
22 return () => {
23 const comments = document.getElementById(COMMENTS_ID)
24 if (comments) comments.innerHTML = ''
25 }
26 }, [])
27
28 return (
29 <div>
30 <h4>Comments</h4>
31 <div id={COMMENTS_ID} />
32 </div>
33 )
34}
35
36export default Comments

Setup Gatsby Environment Variable

For your local development

Let's add the following codes to the top of gatsby-config.js to use an environment variable in Gatsby:

./gatsby-config.js
1require('dotenv').config({
2 path: `.env`,
3})

Then create .env file in your project root and add a key and a value pair to indicate our repo for uttterances comment system:

./.env
1GATSBY_COMMENTS_REPO=<github_owner_name>/<github_repository_name_connected_to_utterances>

Example

GATSBY_COMMENTS_REPO=johndoe/utterances-comments

With this configuration, now the Comments component that we've created above will have access the env variable using process.env.GATSBY_COMMENTS_REPO syntax.

For your production development

The above setting definitely works in the dev environment, but how about production environment? We have two concerns to address:

  1. Because we are not pushing our .env file to the remote repository by adding .env to the .gitignore file, we have to add one manually to our Github repository Settings:
Note that pushing .env file with sensitive data to a remote repository is always dangerous practive, so it should be avoided.
  1. Because I publish my site to Github pages using GitHub Actions, the workflows script needs to be able to access and read the environment variable during the deploying process. To set it:

For those who missed reading my article on how to deploy Gatsby website to github pages using github actions, please refer to How To Deploy Gatsby Website To GitHub Pages Using GitHub Actions.

Add a Github Secret Key

Go to GitHub>Settings of your repository and add a secret key:

github env variable

Update Github Actions

Then let's make some changes to the deploy.yml that creates the same .env file to the original github actions that I've been using so far:

./github/workflows/deploy.yml
1# This is a basic workflow to help you get started with Actions
2name: CI
3
4# Controls when the action will run.
5on:
6 # Triggers the workflow on push or pull request events but only for the dev branch
7 push:
8 branches: [dev]
9 pull_request:
10 branches: [dev]
11 # Allows you to run this workflow manually from the Actions tab
12 workflow_dispatch:
13
14# A workflow run is made up of one or more jobs that can run sequentially or in parallel
15jobs:
16 # This workflow contains a single job called "build"
17 build:
18 # The type of runner that the job will run on
19 runs-on: ubuntu-latest
20
21 # Steps represent a sequence of tasks that will be executed as part of the job
22 steps:
23 # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
24 - uses: actions/checkout@v2
25
26 - name: Setup Node.js environment
27 uses: actions/setup-node@v2.1.5
28 with:
29 # Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0
30 node-version: 16
31 - run: npm ci
32
33 - run: npm run build --if-present
34 - run: |
35 touch .env
36 echo GATSBY_COMMENTS_REPO=${{ secrets.GATSBY_COMMENTS_REPO }} >> .env
37 npm run build --if-present
38
39 - run: npm test
40
41 - name: Deploy to GitHub Pages
42 uses: JamesIves/github-pages-deploy-action@v4.2.5
43 with:
44 branch: gh-pages # The branch the action should deploy to.
45 folder: public # The folder the action should deploy.

Import the Comment Component

The last part of making Utterances comment work in each blog post is to import the Comments.js component and use it in the blog post template.

The following is the part of codes in post-template.js used in this website. To see the entire codes, please refer to this.

post-template.js is a template that is used to create new pages for blog posts programmatically using Gatsby's filesystem route api.
./src/templates/post-template.js
1...
2...
3...
4import Comments from '../components/Comments'
5...
6...
7...
8const PostTemplate = ({ data, pageContext }) => {
9...
10...
11...
12 return (
13 <Layout>
14 <Seo
15 title={title}
16 description={excerpt}
17 image={image?.childImageSharp.resize}
18 pathname={pathName}
19 />
20 <Wrapper toc={isThereTableOfContent}>
21 {/* Table of Contents */}
22 {isThereTableOfContent && (
23 <TableOfContents items={tableOfContents.items} />
24 )}
25 {/* Post Info */}
26 <article className='mdx-page'>
27 <GatsbyImage
28 image={getImage(image)}
29 alt={title}
30 className='main-img'
31 />
32 <div className='post-info'>
33 <h1>{title}</h1>
34 {tags?.length > 0 && <TagsList tags={tags} isPost={true} />}
35 <p>{date}</p>
36 <div className='underline' />
37 <div className='social-buttons-top'>
38 <SocialShareButtons url={url} description={description} />
39 </div>
40 </div>
41 <MDXRenderer
42 embeddedImages={embeddedImages}
43 videoSourceURL={videoSourceURL}
44 videoTitle={videoTitle}
45 >
46 {body}
47 </MDXRenderer>
48 <div className='social-buttons'>
49 <span>If you found this article informative, please share: </span>
50 <SocialShareButtons url={url} description={description} />
51 </div>
52 <PrevAndNext prev={previousPost} next={nextPost} />
53 {relatedPosts?.length > 0 && (
54 <YouMightAlsoLike posts={relatedPosts} tag={tags[0]} />
55 )}
56 <Comments />
57 </article>
58
59 {/* Banner on the right side */}
60 <article>
61 <Banner isPost={true} />
62 </article>
63 </Wrapper>
64 </Layout>
65
66)
67}
68
69export default PostTemplate
70...

The following is the capture of the same utterances comment embedded in this article.

utterance comment
all posts

Comments

© 2022 Youngjae Jay Lim. All Rights Reserved, Built with Gatsby