New Launch

Take a deep dive into the fastest Gatsby, yet: Gatsby 5!

ContactSign Up for Free

Roll Your Own Comment System

Tania Rascia
August 27th, 2019

A while ago, I migrated my site from WordPress to Gatsby, a static site generator that runs on JavaScript/React. Gatsby recommends Disqus as a possible option for comments, and I briefly migrated all my comments over to it…until I looked at my site on a browser window without adblocker installed. I could see dozens of scripts injected into the site and even worse – truly egregious BuzzFeed-esque ads embedded between all the comments. I decided it immediately had to go.

I had no comments for a bit, but I felt like I had no idea what the reception of my articles was without having any place for people to leave comments. Occasionally people will leave useful critiques or tips on tutorials that can help future visitors as well, so I wanted to try adding something very simple back in.

I looked at all the options, but I really didn't want to invest in setting up some third party code that I couldn't rely on, or something with ads. So I figured I'd set one up myself. I designed the simplest possible comment system in a day, which this blog now runs on.

Here's some pros and cons to rolling your own comment system:


  • Free
  • No ads
  • No third party scripts injected into your site
  • Complete control over functionality and design
  • Can be as simple or complicated as you want
  • Little to no spam because spambots aren't set up to spam your custom content
  • Easy to migrate – it all exists in one Heroku + Postgres server


  • More work to set up
  • Less features
  • Need to set up manual anti-spam measures and moderation

If you've also struggled with this and wondered if there could be an easier way, or are just intrigued to see one person's implementation, read on!


This guide will not be a full, guided walkthrough – however, all the steps to create this are documented from start to finish in Create and Deploy a Node.js, Express, & PostgreSQL REST API to Heroku. The comments API is a Node + Express server connected to a Postgres instance hosted for free on the hobby tier of Heroku (Hopefully I don't go over the 10,000 row limit any time soon). A combination of that article and what I've documented here can get you all the way to having your own comment system.

Note: Comments overall aren't a big deal to me, so I don't care if I'm just running some little hobby API I created, or if it goes down for any reason. I think it should be pretty solid, but obviously if your needs are more professional than mine, you should go ahead and buy Disqus or something.

The comments API consists of three parts:

The frontend is written for React, but if you know how to make a form and an API call, it can be easily adjusted to whatever static system you're using.


The first step assumes we'll be setting up a Postgres database called comments_api with a comments table.

In the comments_api database, I created a comments table, with ID, name, date, and text. The slug refers to the article URL – so for, the slug would be how-to-bake-a-cake. Finally, I added parent_comment_id in case you want to have the ability to reply to comments.

You could probably get more fancy with it and add website, email, upvotes and other features, but I just wanted it to be simple. I'm not adding in any login or OAuth/user authentication either, which makes it even more simple, but comes with the drawbacks of an anonymous online system.


In Create and Deploy a Node.js, Express, & PostgreSQL REST API, I document how to set up an Express server and make a Postgres pool connection.

The aforementioned article goes much deeper into production level concerns of a Node.js server, such as error handling, validation, and brute force rate limiting.

In our simplified, development example setup, we'll require express, a Node.js server, plus bodyParser and cors to allow our app to parse and request the data, and pg to create a Postgres pool connection.

This article is using default values for the Postgres connection – user as username, password as password, etc.

Remember that this example is simply for demonstration purposes and development.

Get all comments

First, I want a GET query that will just return everything to Node.js, ordered by date. This is just for me to have, so I can easily review all comments.

Get comments by page slug

More importantly, I want a query that will only return the comments that match the current page's slug. This is the query I'll use for each article.

Create a comment

Add the ability to POST a new comment, which people will be able to do through the HTML form.

Update an existing comment

As moderator, I want the ability to update an existing comment. Commentors won't be able to edit their comments, because they're all anonymous. This will be a protected endpoint.

Delete a comment

Another protected endpoint, only I will have the ability to delete a comment.

Putting it together

We have our two GETs, a POST, PUT, and DELETE.

Front End

Again, for the frontend I'm using React as an example, but the concept is the same for any template system. In whatever your post template file is, use JavaScript to make a fetch or axios call to your comment API, and save the data in state somewhere. Once I retrieve the JSON response from the API server, which will be an array of comment objects, I can pass it to wherever I'm displaying the comments.

Sorry, I'm not using hooks yet. It's okay, deep breath. We'll get through this.

In this case, that will be a Comments component.

The Comments component will contain both the form to submit a comment, and the list of existing comments if there are any. So in state, I'll save the comments list, and an object to store new comment state for the form.

I'll admit this code is not the most pristine I've ever seen, but as I mentioned, I wrote the thing in a day, so feel free to refactor and write however you want.

When a comment is submitted, I'll use fetch once again, this time with the post method. If everything went through correctly, append the new comment to the comments array, and reset the new comment.

I'll also have an onChange handler for the form.

We can start the render lifecycle now.

I made some simple error or success messages to show after submitting the form.

The comment form only consists of name and comment in my case, as I decided to go the Sivers route and only allow comment replies by yours truly on the site.

Finally, we'll display the form and the comments. I decided to either display the form or a success/error message. A visitor won't be able to leave two comments in a row without reloading the page.

After that, it's just a matter of looping through the comments and displaying them. I've made comment replies incredibly simple – only one reply allowed per post, and no nesting.


You'll probably also want to add in some anti-spam moderation system, like adding a moderated column to the comments, setting it to false by default, and manually setting it to true if you approve the comment.

I hope this helps out someone who wants a simple, free system for their own personal site. I like reinventing the wheel and making things from scratch. It's fun, and I learn a lot.

For more information on building contact forms with Gatsby, check out the docs reference guides.

Share on TwitterShare on LinkedInShare on FacebookShare via Email

Web developer and writer specializing in modern JavaScript.

Follow Tania Rascia on Twitter

Tagged with apis, commentsView all Tags

Originally published at

Talk to our team of Gatsby Experts to supercharge your website performance.

Contact Gatsby Now
© 2022 Gatsby, Inc.