How to Add Giscus Comments to an Astro Blog

Feb 10, 2025 Updated Jul 5, 2026

I wanted comments on my Astro blog without taking on a database, moderation panel, or another service to babysit, so I ended up using Giscus. It stores discussions in GitHub, takes about 10 minutes to wire up, and with a little extra code it can follow your site’s dark mode cleanly.

This is the same setup running on this site, scroll to the bottom of this post to see it live.

What You Need

One thing to know before you commit to Giscus: readers need a GitHub account to comment. For a dev blog that’s basically everyone, but for a general audience blog it might rule it out.

Why I Picked Giscus

I’ve wanted comments on the blog for a while, mostly so posts could have a place for follow-up questions and corrections. I wanted something I didn’t have to host, something easy to moderate, and something I could make match the rest of the site. I landed on Giscus after seeing it on Nick Winans’s blog, and it checked all of those boxes.

The short version on alternatives: Disqus was heavier than I wanted, Utterances was close but less flexible, and self-hosted options felt like too much infrastructure for a static site. Giscus gave me threaded replies, reactions, GitHub-based moderation, and no server to maintain.

Adding Giscus

The initial setup all happens on the Giscus site, which generates a script tag configured for your repo.

  1. Go to Giscus.app
    • Create a public repo that you want to use, enable the Discussions feature in settings. This is disabled by default and Giscus won’t work without it
    • Install the Giscus app, you can select it to manage just the repo you’ve created
    • Select the mapping (I use pathname which ties each discussion thread to the page’s url path), themes, and any other options there
  2. Copy the <script> that Giscus generates for you
  3. Add it to your article page in Astro.
  4. If you want it somewhere else you can create a div with class giscus
    • ie: <div class="giscus pt-2"></div>

At this point comments work. The script injects an iframe, and the first comment on any page automatically creates a matching Discussion thread in your repo.

Stylizing Giscus

You can either use one of the existing themes or pass in your own fully qualified url path to a custom css file into the data-theme attribute as is documented in giscus’s advanced usage docs

The main extra step is theme syncing. Giscus lives in an iframe, so you can’t just restyle it with CSS when your site theme changes. You need to send it a postMessage when the theme flips, and you want to set the initial theme before the script loads so it doesn’t flash the wrong colors on first render.

<script is:inline>
  function updateGiscusTheme() {
    const dataTheme =
      document.documentElement.getAttribute("data-theme") || "light";
 
    const giscusFrame = document.querySelector("iframe.giscus-frame");
    if (!giscusFrame) return;
 
    giscusFrame.contentWindow.postMessage(
      {
        giscus: {
          setConfig: {
            theme: dataTheme === "dark" ? "dark_dimmed" : "light",
          },
        },
      },
      "https://giscus.app",
    );
  }
 
  document.addEventListener("themechange", updateGiscusTheme);
</script>
 
<div class="giscus"></div>
<script>
  // doing this manually lets astro pick up the initial set theme without flashing or erroring
  const theme =
    localStorage.getItem("theme") === "dark" ? "dark_dimmed" : "light";
 
  const script = document.createElement("script");
  script.src = "https://giscus.app/client.js";
  script.async = true;
  script.crossOrigin = "anonymous";
 
  script.setAttribute("data-repo", "davidteather/dteather.com");
  script.setAttribute("data-repo-id", "R_kgDONz7hYA");
  script.setAttribute("data-category", "Announcements");
  script.setAttribute("data-category-id", "DIC_kwDONz7hYM4CmoaD");
  script.setAttribute("data-mapping", "pathname");
  script.setAttribute("data-reactions-enabled", "1");
  script.setAttribute("data-emit-metadata", "1");
  script.setAttribute("data-input-position", "top");
  script.setAttribute("data-lang", "en");
  script.setAttribute("data-loading", "lazy");
  script.setAttribute("data-theme", theme);
 
  document.querySelector(".giscus")?.appendChild(script);
</script>

Make sure to swap the data-repo, data-repo-id, data-category, and data-category-id values for the ones the Giscus configurator generated for your repo, mine won’t work on your site. The rest of the attributes map to the options you picked on giscus.app, so you can tweak things like data-input-position (comment box above or below the thread) here without regenerating anything.

If you want a tighter visual match with your Astro theme, the next step would be generating a custom Giscus CSS theme from your site colors and passing that stylesheet through data-theme.

Complete GiscusComments.astro Example

If you want this wrapped in one component instead of spreading it across a layout file, a dedicated component works well too:

src/components/GiscusComments.astro
---
const theme =
  Astro.cookies.get("theme")?.value === "dark" ? "dark_dimmed" : "light";
---
 
<div class="giscus"></div>
 
<script is:inline>
  function updateGiscusTheme() {
    const dataTheme =
      document.documentElement.getAttribute("data-theme") || "light";
 
    const giscusFrame = document.querySelector("iframe.giscus-frame");
    if (!giscusFrame) return;
 
    giscusFrame.contentWindow.postMessage(
      {
        giscus: {
          setConfig: {
            theme: dataTheme === "dark" ? "dark_dimmed" : "light",
          },
        },
      },
      "https://giscus.app",
    );
  }
 
  document.addEventListener("themechange", updateGiscusTheme);
</script>
 
<script define:vars={{ theme }}>
  const script = document.createElement("script");
  script.src = "https://giscus.app/client.js";
  script.async = true;
  script.crossOrigin = "anonymous";
 
  script.setAttribute("data-repo", "your-org/your-repo");
  script.setAttribute("data-repo-id", "YOUR_REPO_ID");
  script.setAttribute("data-category", "General");
  script.setAttribute("data-category-id", "YOUR_CATEGORY_ID");
  script.setAttribute("data-mapping", "pathname");
  script.setAttribute("data-reactions-enabled", "1");
  script.setAttribute("data-emit-metadata", "1");
  script.setAttribute("data-input-position", "top");
  script.setAttribute("data-lang", "en");
  script.setAttribute("data-loading", "lazy");
  script.setAttribute("data-theme", theme);
 
  document.querySelector(".giscus")?.appendChild(script);
</script>

Troubleshooting

Most of the ways this breaks are configuration, and the errors don’t always point at the actual cause.

And that’s all you have to do to get comments on your site. If you’re building out an Astro blog I’ve also written about adding a search bar, pulling live stats into a static site, and interactive charts which uses the same themechange event trick as this post.

If this helped or you got stuck somewhere, leave a comment below.

Frequently asked questions

Does Giscus work with Astro?

Yes. Giscus works well with Astro because it just needs a script tag or component in your page layout. You can keep the rest of the site static and still get comments, reactions, and GitHub-based moderation.

Do users need GitHub accounts to comment with Giscus?

Yes. Visitors need to authorize the Giscus GitHub app through GitHub OAuth before they can post comments or reactions.

Can I use Giscus on a private repo?

For a public blog, you should assume no. Giscus comments are backed by GitHub Discussions, so commenters need access to the repository discussions used for the thread.

How do I sync Giscus with dark mode in Astro?

Set the initial `data-theme` before injecting the Giscus script, then send the iframe a `postMessage` with `setConfig.theme` whenever your site theme changes.

Related posts

← Back to blog More in Building with Astro · 7 posts →