Migrating from Disqus to Giscus

As I mentioned in the Google Analytics to Umami migration post, I am in the middle of a major blog overhaul. After addressing the visit data analytics, the next task was switching the comment platform.

This website started from a Jekyll template I purchased in 2021. Disqus was the comment platform built into that template.

As I mentioned, I treat data sovereignty and privacy as core values — and Disqus does not align with them. Comment data is owned by the platform, users are tracked and profiled, and there have been multiple security breach incidents. It was a poor choice from a privacy standpoint.

I chose Giscus as the alternative: an open-source comment widget backed by GitHub Discussions.


What is Giscus?

Giscus Cover Image

Giscus is an open-source comment widget that uses GitHub Discussions.

Comment data is stored and managed in a GitHub Repository’s Discussions, powered by a lightweight open-source client script. No ads, no tracking, no separate server required.

Control over comment data stays with me, setup is simple, and there is no user tracking — all three matched my requirements, so I went with Giscus.


Implementing Giscus

GitHub Repository Discussions Setup

Enable the Discussions feature in the GitHub Repository where comments will be stored. Since Giscus accesses the Repository’s Discussions to manage comments, the target Repository must be Public. Go to Repository → Settings → General → Features and check “Discussions”.

Next, create a category for Giscus to use. If you haven’t configured anything, a few categories are created by default as shown below — you can use them as-is.

GitHub Discussions Initial State Image


Connecting the Giscus App to GitHub

You need to grant Giscus permission to access your GitHub Repository’s Discussions. Fortunately, this can be done directly through GitHub Apps without any painful environment setup.

Find the giscus App in the Marketplace and add it to your GitHub account.

In the giscus App settings under Repository access, select Only select repositoriesthe Repository where Discussions is configured to grant access.


Confirming Configuration at giscus.app

The only thing left is to get the script to attach to the website.

Go to giscus.app and enter your configuration — language, repository, path mapping, and so on.

Once complete, a script like the one below is generated in the “Enable giscus” section at the bottom. Add this script to your website to activate the comment widget.

<script src="https://giscus.app/client.js"
        data-repo="username/repo-name"
        data-repo-id="R_xxxxxxxx"
        data-category="Announcements"
        data-category-id="DIC_xxxxxxxx"
        data-mapping="pathname"
        data-strict="0"
        data-reactions-enabled="1"
        data-emit-metadata="0"
        data-input-position="bottom"
        data-theme="preferred_color_scheme"
        data-lang="en"
        crossorigin="anonymous"
        async>
</script>


Attaching Giscus to the Website

I’ll cover two approaches: applying it with simple HTML editing, and applying it on a Jekyll website.


HTML Editing

Copy the script generated from giscus.app and place it wherever you want comments to appear.

<div class="comments">
  <script src="https://giscus.app/client.js"
          data-repo="username/repo-name"
          data-repo-id="R_xxxxxxxx"
          data-category="Announcements"
          data-category-id="DIC_xxxxxxxx"
          data-mapping="pathname"
          data-strict="0"
          data-reactions-enabled="1"
          data-emit-metadata="0"
          data-input-position="bottom"
          data-theme="preferred_color_scheme"
          data-lang="en"
          crossorigin="anonymous"
          async>
  </script>
</div>


Jekyll Website Application

Add Giscus configuration environment variables to the configuration file (_data/settings.yml), matching the script generated from giscus.app.

# Giscus Comments
giscus:
  repo: "username/repo-name"
  repo_id: "R_xxxxxxxx"
  category: "Announcements"
  category_id: "DIC_xxxxxxxx"
  mapping: "pathname"
  strict: "0"
  reactions_enabled: "1"
  emit_metadata: "0"
  input_position: "bottom"
  theme: "preferred_color_scheme"
  lang: "en"

Create giscus-comments.html in the _includes directory and add the script from giscus.app. Set each attribute value as a Liquid variable so it pulls from the configuration file.


<script src="https://giscus.app/client.js"
        data-repo="{{ site.data.settings.giscus.repo }}"
        data-repo-id="{{ site.data.settings.giscus.repo_id }}"
        data-category="{{ site.data.settings.giscus.category }}"
        data-category-id="{{ site.data.settings.giscus.category_id }}"
        data-mapping="{{ site.data.settings.giscus.mapping }}"
        data-strict="{{ site.data.settings.giscus.strict }}"
        data-reactions-enabled="{{ site.data.settings.giscus.reactions_enabled }}"
        data-emit-metadata="{{ site.data.settings.giscus.emit_metadata }}"
        data-input-position="{{ site.data.settings.giscus.input_position }}"
        data-theme="preferred_color_scheme"
        data-lang="en"
        crossorigin="anonymous"
        async>
</script>

Then reference it in any HTML file where you want comments displayed.


<div class="container">
  <div class="row">
    <div class="col col-12">
      {% include giscus-comments.html %}
    </div>
  </div>
</div>

After loading the page, you can confirm the widget is working correctly.

Giscus Comment Image


Hiding Comments Per Post

To disable comments on specific posts, add a condition to the giscus-comment.html include logic that checks the page.comments variable from the post’s Front Matter.


{% if page.comments != false %}
<div class="container">
  <div class="row">
    <div class="col col-12">
      {% include giscus-comments.html %}
    </div>
  </div>
</div>
{% endif %}

Then add comments: false to the Front Matter of any post where you want to hide the comment section.

---
title: "Post Title"
comments: false
---


Polyglot Multilingual Support

For multilingual websites like mine, there is a need to provide a different comment UI per language.

When using the Jekyll-Polyglot plugin, the currently active language is stored in the site.active_lang global variable, so multilingual support is straightforward.


<script src="https://giscus.app/client.js"
        data-lang="{{ site.active_lang | default: site.data.settings.giscus.lang }}"
        async>
</script>


Syncing the Blog Theme with the Giscus Theme

The default value of preferred_color_scheme for the data-theme variable follows the OS/browser setting.

My blog lets users toggle between light and dark mode, but if the blog theme and OS/browser setting differ, the comment widget no longer matches the page.

To fix this, I updated the script loading logic to reference site.data.settings.color_scheme — the blog’s active theme setting — so the Giscus theme updates in sync with the blog theme.


{% if site.data.settings.color_scheme == "light" %}
  <script src="https://giscus.app/client.js"
          data-theme="light""
          async>
  </script>
{% else %}
  <script src="https://giscus.app/client.js"
          data-theme="dark"
          async>
  </script>
{% endif %}