Add Disqus Comments to Docusaurus Blog Posts

TL;DR Recently I have switched from Jekyll to Docusaurus for my personal website. And immediately noticed the issue with letting the visitors place comments to blog posts. It seems that the comments work out of the box only for Facebook comments and then only if one has a registered FB business site (according to this PR). Searching on adding e.g. Disqus blog comments in Docusaurus brought back more questions than answers. (see some references at the end of this post)

The closest I could get to the solution was How to add forum to Docusaurus using Utterances comments via GitHub issues. I got the gist but the vendor binding was too big to my taste.

So, I have made my own go on this issue and finally succeeded in adding the Disqus blog comments to my Docusaurus blog. In this blog post you can see them in action and also read how I did it. I hope it might help some of you to do the same on yours.

Let's Go!#

Prerequisites#

Here is a very small list of things we need to have ready to get the job done:

  1. your project running Docusaurus with at least one blog post;
  2. you have installed your project using theme classic
  3. a terminal session open in the root of your project;
  4. an account with Disqus with your registered Docusaurus webapp.

In your terminal session run one of the following commands to install disqus-react depending on what your package manager is:

yarn add disqus-react
# or
npm add disqus-react

If you need some guidance as to Disqus weblog registration, see my Register Your Weblog with Disqus section below.


Prepare the frontmatter#

Run your Docusaurus project locally running either yarn start or npm run start in your terminal. Browse to http://localhost:3000/blog and make sure you see at least one blog post. Choose one of them to work with.

Open the chosen blog post file in your favorite editor and add the following two lines at the end of the frontmatter:

---
slug: your-blog-post-slug
...
draft: true
no_comments: false # for Disqus
---

I advise you to set draft to true until you know for sure everything works fine. What it does is that it lets you see your post while running Docusaurus locally. But if you publish it to the web, this particular blog post won't be published and visible. When you are ready, you can set it to false or remove completely from the frontmatter.

I have added the second no_comments property so that you could decide for each blog post if you want your visitors leave comments. Set it to true and there will be nog Disqus comments section underneath your blog post. Without this property or if it is set to false the comments section will be present.

In my project, I have replaced the id with slug as id has been deprecated by Docusaurus. Feel free to use it however if that is your preference. Just replace the slug with id in the code snippet below.

Swizzle the BlogPostPage component#

Swizzling a Docusaurus component means including its source code into your project code so that it can be customized and your customized version overrides the standard one. As the Docusaurus component responsible for rendering the blog posts is the BlogPostPage of the classic theme, we need to swizzle it into our project.

According to the official Docusaurus documentation, the commands in this case are:

yarn swizzle @docusaurus/theme-classic BlogPostPage --danger
# or
npm run swizzle @docusaurus/theme-classic BlogPostPage --danger

If you are using Typescript in your Docusaurus project, you can use the same commands by adding the --typescript flag to them.

--danger flag

The --danger flag is necessary to acknowledge that we understand the risks. (do you? ๐Ÿ˜ƒ )

Somehow, only the yarn version of the command worked for me. The npm version produced an error. See npm run swizzle errors section.

Once it is finished, go to the src/theme/BlogPostPage folder and open the index.js file inside it.

Add DiscussionEmbed Code Snippet#

I have roughly followed the instruction from the disqus-react repository but changed the code a bit to include the no_comments property and to add the missing specifics of integration with Docusaurus.

Add the following code to the swizzled src/theme/BlogPostPage/index.js:

import { DiscussionEmbed } from 'disqus-react'
function BlogPostPage(props) {
...
const { slug, title, description, nextItem, prevItem } = metadata
const { hide_table_of_contents: hideTableOfContents, no_comments } = frontMatter
...
return (
...
// after Edit this Page block
{!no_comments && (
<DiscussionEmbed
shortname='your_website_disqus_shortname'
config={{
url: slug,
identifier: slug,
title: title,
language: 'en_US',
}}
/>
)}
// before nextItem
...
)
}

If your webapp has been properly registered with Disqus, you should see the Disqus comments appear under every blog post when running Docusaurus locally. Once you got it working you may set draft: false in the frontmatter or remove the setting completely and publish your website. The comments block will be there as well.

One personal observation how smart Disqus is:

info

The comments you add when testing you website locally do not synchronize with the comments of the same deployed page.

CommentCount and CommentEmbed#

Using the disqus-react code snippets for CommentCount and CommentEmbed it is also be possible to add those to your Docusaurus project in a similar manner.

Adding Comments to Docs#

It is also possible to add comments to your regular documents inside the Docs section of your Docusaurus project. For that, you need to swizzle and patch the DocsItem component of the theme-classic.


Final Observations#

While swizzling is handy, it is still a workaround. That means that if Docusaurus in some future release changes the code of these components, you will probably need to swizzle their new versions. Meaning that you will also need to reapply the patch described here. A better approach would probably be creating a PR for Docusaurus. However, its policy is that adding comments is the sole resposibility of devs themselves as they have provided us with the swizzle feature and/or we can write our own React component for that. I have come across the following comment of endiliey when reading the Proposal: Add support for comments powered by Discourse:

I will close this since we already have FB comment for v1. On v2 user can extends their own layout and write React component so this is up to the user


Troubleshooting#

npm run swizzle errors#

Running

npm run swizzle @docusaurus/theme-classic BlogPostPage --danger

produces the following error:

> frontend-guild@0.1.12 swizzle /Users/madrus/src/frontend-guild
> docusaurus swizzle "@docusaurus/theme-classic" "BlogPostPage"
BlogPostPage is an internal component, and have a higher breaking change probability. If you want to swizzle it, use the "--danger" flag.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! frontend-guild@0.1.12 swizzle: `docusaurus swizzle "@docusaurus/theme-classic" "BlogPostPage"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the frontend-guild@0.1.12 swizzle script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/madrus/.npm/_logs/2020-12-24T09_13_04_111Z-debug.log

Try running the yarn version of it as specified above.


References#

Here are some references I have found useful when doing my research on adding Disqus blog post comments: