Adding a Comment System to My Blog

A blog needs comments. But I didn’t want to set up a database and moderation system just for that. Giscus is the compromise.

This blog uses Giscus for comments. It’s based on GitHub Discussions. All comments live in the GitHub repo, no database needed, no third-party service.

Full Flow

User opens article page
      ↓
Loads giscus.app/client.js
      ↓
Giscus script reads data- attributes
      ↓
Uses mapping="pathname" to get current URL path
      ↓
Queries GitHub Discussions API for matching Discussion
      ↓
Found → renders comment box and existing comments
Not found → shows "leave a comment" input
      ↓
User writes comment → clicks submit
      ↓
Redirects to GitHub OAuth (first time only)
      ↓
Comment written to repo's Discussions via API
      ↓
Giscus WebSocket listens for changes → real-time updates

User never leaves the page. Entire flow is seamless.

Integration

Comment system embedded as a script tag in layouts/partials/comments.html:

<div class="blog-post-comments">
  <script src="https://giscus.app/client.js"
    data-repo="0x1428571429/time-friend.com"
    data-repo-id="MDEwOlJlcG9zaXRvcjoxNTQ0NDY1NTc="
    data-category="Announcements"
    data-category-id="DIC_kwDOCTSq3c4DB723"
    data-mapping="pathname"
    data-strict="0"
    data-reactions-enabled="1"
    data-emit-metadata="0"
    data-input-position="bottom"
    data-theme="noborder_dark"
    data-lang="{{ if eq .Lang "zh" }}zh-CN{{ else }}en{{ end }}"
    crossorigin="anonymous">
  </script>
</div>

Data storage is GitHub repo 0x1428571429/time-friend.com. Giscus script reads/writes comments through GitHub’s Discussions API. No backend needed.

Reference in page template:

{{ partial "comments.html" . }}

Parameters Explained

data-repo

GitHub repo where comments are stored. 0x1428571429/time-friend.com.

data-repo-id

GitHub internal ID for the repo. MDEwOlJlcG9zaXRvcjoxNTQ0NDY1NTc=.

Fixed value, generated automatically when you enter your repo name at https://giscus.app. First time I set this up, I thought repo-id was just the repo name. Spent a while before realizing I needed the actual generated ID.

data-category / data-category-id

Discussion category. Using Announcements, category ID DIC_kwDOCTSq3c4DB723.

Setup steps:

  1. Enable Discussions in GitHub repo Settings > Features
  2. Go to repo’s Discussions tab, create a category
  3. Select the category on Giscus website, it generates the category-id

One thing: GitHub repo Discussions is not enabled by default. You have to go to Settings > Features and check the Discussions box. I spent a while debugging why Giscus wasn’t working, eventually found this was the issue.

data-mapping

How articles map to Discussions. Using pathname, the current URL path.

For example, user visits /en/archive/blog-architecture-overview, Giscus uses this path to match a Discussion.

Other options:

  • title: matches by page title. But if you change the title later, old comments are lost → not recommended
  • url: matches by full URL. But if domain or protocol changes, comments are lost
  • og:title: matches by Open Graph title

pathname is the most stable. As long as the URL path doesn’t change, the mapping holds. But the flip side is: if you change an article’s slug, all previous comments are gone. Don’t change slugs after publishing. Learned this the hard way.

data-strict

Strict matching. Set to 0, allows partial matching, better tolerance.

data-theme

Giscus theme. noborder_dark matches the blog’s dark theme.

Giscus offers multiple themes: light, dark, noborder_light, noborder_dark, preferred_color_scheme. Custom CSS themes also supported.

data-lang

Comment UI language. Dynamic based on current page:

zh → zh-CN (Chinese)
en → en (English)

Giscus supports dozens of languages.

Others

  • data-reactions-enabled="1": emoji reactions on comments
  • data-emit-metadata="0": no metadata, privacy friendly
  • data-input-position="bottom": comment input at bottom
  • crossorigin="anonymous": cross-origin setting
  • async: non-blocking load

Data Management

All comments live in GitHub repo Discussions. Access at:

https://github.com/0x1428571429/time-friend.com/discussions

From GitHub you can:

  • Browse comments: by category, sorted by time
  • Manage comments: delete spam, edit or pin replies
  • Reply to visitors: reply in Discussions, visitors see it
  • Bulk operations: close Discussion, change category, mark as answer

Each article corresponds to one Discussion. Discussion title defaults to the page path, e.g. /en/archive/blog-architecture-overview. Easy to identify which article a comment belongs to.

Giscus internally uses GitHub’s GraphQL API:

  1. Uses data-repo to locate repo
  2. Uses data-mapping (pathname) to build search query
  3. Runs a search type GraphQL query to find matching Discussion
  4. Found → render, not found → show blank, auto-create on first comment

Markdown Support

Giscus comment box supports Markdown:

**bold**
`inline code`

\```javascript
const code = "code block";
\```

Code is auto-highlighted, consistent with the blog’s article style. Important for a tech blog — visitors can paste code when discussing technical issues.

Pros and Cons

Pros

Zero ops. No database, no server, no moderation backend. Comments live in your own GitHub repo, no third-party service shutdown risk.

Data ownership. Comments are repo Discussions. Exportable, migratable, backupable. Unlike Disqus where your data is locked in.

Good UX. GitHub account login, no extra registration. OAuth is handled by Giscus, developer writes zero code.

Real-time updates. WebSocket push, one visitor’s comment shows instantly to others viewing the same article.

Anti-spam. GitHub account has a registration barrier, much fewer spam comments compared to anonymous systems like Disqus.

Cons

Visitor needs GitHub account. Non-developers might not have one. But this blog’s audience is mostly developers, acceptable.

GitHub occasionally unstable in China. Giscus script loads from giscus.app, API calls go to GitHub. Access from China can be slow or timeout. Blog audience is mainly overseas, acceptable.

Article Link:

/en/archive/blog-architecture-giscus/

# Related Articles