How to Set Up Giscus Comments for Your Website - Complete Technical Guide

Step-by-step guide to adding GitHub-powered comments using Giscus. Includes GraphQL queries to get repoId and categoryId, React component setup, and configuration.

November 18, 2025By qz-l team

How to Set Up Giscus Comments - Complete Technical Guide

If you want to add a clean, GitHub-powered comment system to your website, Giscus is one of the best options. It stores comments as GitHub Discussions, requires no backend, and has zero infrastructure costs.

This guide walks you through everything required to get Giscus comments working on your website.

What is Giscus?

Giscus is a comments system powered by GitHub Discussions. Instead of maintaining a separate database:

  • Comments are stored as GitHub Discussions
  • Users authenticate with their GitHub account
  • Everything is public, transparent, and version-controlled
  • No ads, no tracking, no data selling

Perfect for developer-focused audiences and open-source projects.

Prerequisites

Before you start, you'll need:

  • A GitHub account
  • A repository where you want to store comments (public or private)
  • A personal access token (PAT) with public_repo scope (for GraphQL queries)

Step 1: Create a Repository for Comments

First, create a dedicated GitHub repository to store all comments:

Q-Z-L-Corp/giscus-comments

This repository will contain all the GitHub Discussions that become your website comments. Keep it public so comments are visible to everyone.

Why a separate repo?

  • Keeps your main repository clean
  • Makes it easy to manage discussion settings separately
  • Allows you to archive or reset comments independently

Step 2: Enable GitHub Discussions

Go to your comments repository settings:

Path: Settings → General → Features

Check the Discussions checkbox:

☑ Discussions

Without Discussions enabled, Giscus cannot store or retrieve comments.

Create Discussion Categories

After enabling Discussions, go to the Discussions tab and set up categories. By default, GitHub creates an "Announcements" category. Create a category for your use case:

Example: "Blog Comments"

  • Name: Blog Comments
  • Description: Comments on blog posts from qz-l.com
  • Emoji: 💬

You'll need the Category ID later (more on that in Step 5).

Step 3: Install the Giscus GitHub App

Giscus needs a GitHub App to read and write discussions on your behalf.

Install here: https://github.com/apps/giscus

During installation:

  1. Select your GitHub account or organization
  2. Select "Only select repositories"
  3. Choose your comments repository (e.g., Q-Z-L-Corp/giscus-comments)
  4. Click "Install"

The app will request permissions for:

  • Discussions (read/write comments)
  • Contents (optional, for metadata)
  • Metadata (optional, for repo info)

Once installed, Giscus is authorized to create and manage discussions in your repo.

Step 4: Get Your Repository ID (repoId)

Giscus requires the GraphQL repository ID, not the repository name. To get it, you'll query GitHub's GraphQL API.

Create a GitHub Personal Access Token

  1. Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
  2. Click "Generate new token (classic)"
  3. Name it: Giscus Setup
  4. Select scopes: public_repo (for public repos)
  5. Click "Generate token"
  6. Copy the token (you'll use it in the next step)

Query the Repository ID

Use the GitHub GraphQL Explorer or your terminal:

GraphQL Query:

query {
  repository(owner: "Q-Z-L-Corp", name: "giscus-comments") {
    id
    name
  }
}

Using cURL:

curl -X POST https://api.github.com/graphql \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query { repository(owner: \"Q-Z-L-Corp\", name: \"giscus-comments\") { id name } }"
  }'

Response:

{
  "data": {
    "repository": {
      "id": "R_kgDOQX9xSQ",
      "name": "giscus-comments"
    }
  }
}

Your repoId is: R_kgDOQX9xSQ

Save this value—you'll need it in the Giscus component.

Step 5: Get Your Discussion Category ID (categoryId)

Now query for your discussion categories to get the categoryId:

GraphQL Query:

query {
  repository(owner: "Q-Z-L-Corp", name: "giscus-comments") {
    discussionCategories(first: 20) {
      nodes {
        id
        name
        slug
        description
      }
    }
  }
}

Using cURL:

curl -X POST https://api.github.com/graphql \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query { repository(owner: \"Q-Z-L-Corp\", name: \"giscus-comments\") { discussionCategories(first: 20) { nodes { id name slug description } } } }"
  }'

Response:

{
  "data": {
    "repository": {
      "discussionCategories": {
        "nodes": [
          {
            "id": "DIC_kwDOQX9xSc4Cx7Fn",
            "name": "Blog Comments",
            "slug": "blog-comments",
            "description": "Comments on blog posts from qz-l.com"
          }
        ]
      }
    }
  }
}

Your categoryId is: DIC_kwDOQX9xSc4Cx7Fn

Step 6: Install Giscus in Your Project

Install the NPM Package

npm install @giscus/react

Or with yarn:

yarn add @giscus/react

Create a Giscus Component

Create a new file components/GiscusComments.tsx:

"use client";

import { useEffect } from "react";
import Giscus from "@giscus/react";

export default function GiscusComments() {
  useEffect(() => {
    console.log("Giscus component mounted");
  }, []);

  return (
    <div className="mt-12 pt-8 border-t border-gray-200">
      <h3 className="text-2xl font-bold text-gray-900 mb-6">Comments</h3>
      <Giscus
        id="comments"
        repo="Q-Z-L-Corp/giscus-comments"
        repoId="R_kgDOQX9xSQ"
        category="Blog Comments"
        categoryId="DIC_kwDOQX9xSc4Cx7Fn"
        mapping="pathname"
        strict="0"
        reactionsEnabled="1"
        emitMetadata="0"
        inputPosition="top"
        theme="light"
        lang="en"
        loading="lazy"
      />
    </div>
  );
}

Key props explained:

  • repo: Your repository in owner/name format
  • repoId: From your GraphQL query (Step 4)
  • categoryId: From your GraphQL query (Step 5)
  • mapping: How to match page → discussion
    • pathname: Use the current URL path
    • url: Use the full URL
    • title: Use the page title
    • specific: Use a custom term
  • reactionsEnabled: Allow emoji reactions
  • inputPosition: Where the comment form appears (top or bottom)
  • theme: light, dark, or preferred_color_scheme
  • loading: lazy for lazy loading (recommended)

Use the Component

In your page component (e.g., Next.js blog post page):

import GiscusComments from "@/app/components/Giscus";
import { Suspense } from "react";

export default function BlogPostPage() {
  return (
    <main>
      {/* Your blog post content */}
      <article>Post content here...</article>

      {/* Comments section */}
      <Suspense fallback={<div className="h-96" />}>
        <GiscusComments />
      </Suspense>
    </main>
  );
}

That's it! Since GiscusComments is marked with "use client", it automatically renders on the client side even though it's imported in a Server Component.

The Suspense boundary shows a loading placeholder while the Giscus iframe loads.

Step 7: Verify Everything Works

  1. Load your page in the browser
  2. Scroll to the comments section
  3. Sign in with GitHub (if not already logged in)
  4. Write a test comment
  5. Check your discussions repo to see the comment as a GitHub Discussion

Advanced Configuration

Using a Custom Mapping Strategy

If you want all comments in a single discussion:

<Giscus
  mapping="specific"
  term="Blog Comments"
  // ... other props
/>

Dark Mode Support

const theme = isDarkMode ? "dark" : "light";

<Giscus
  theme={theme}
  // ... other props
/>

Handling Lazy Loading

Giscus iframe content loads asynchronously. For better UX, add a loading skeleton:

const [isLoading, setIsLoading] = useState(true);

<Suspense fallback={
  <div className="bg-gray-100 rounded-lg h-96 animate-pulse" />
}>
  <GiscusComments onLoad={() => setIsLoading(false)} />
</Suspense>

Troubleshooting

"404 Not Found" Error

Cause: Wrong repoId or categoryId, or Giscus app not installed.

Fix:

  1. Double-check repoId and categoryId from GraphQL queries
  2. Verify Giscus app is installed on the repo
  3. Verify Discussions are enabled

Comments Not Showing

Cause: SSR (server-side rendering) issue, or Giscus script not loading.

Fix:

  1. Use dynamic() with ssr: false (as shown in Step 6)
  2. Check browser DevTools Console for errors
  3. Verify Giscus script loads from https://giscus.app

"Not Authorized" When Trying to Comment

Cause: User not logged in to GitHub, or Giscus app permissions missing.

Fix:

  1. User must sign in with GitHub
  2. Reinstall Giscus app with required permissions

Why We Chose Giscus

After evaluating many comment systems, we chose Giscus for qz-l because:

GitHub-native – Comments are part of your repo
Zero backend – No database to manage
Free forever – GitHub Discussions are free
Privacy-first – No tracking, no ads
Transparent – All discussions are public
Developer-friendly – Perfect for technical audiences

Next Steps

Now that you have Giscus set up:

  1. Monitor discussions – Check your repo's Discussions tab regularly
  2. Respond to comments – Engage with your audience
  3. Archive old discussions – Keep the repo organized
  4. Customize styling – Adjust theme and component styling as needed

Have questions about setting up Giscus? Drop a comment below! This post has comments enabled—try it out. 👇

Found a mistake or have suggestions? Your feedback helps us improve this guide for other developers.


This guide was based on our experience setting up Giscus for the qz-l blog. Check out the live implementation at qz-l.com/blog.

Comments