Skip to content

Comments on Static Sites — utterances, giscus & Alternatives

DodaTech Updated 2026-06-22 7 min read

In this tutorial, you'll learn about Comments on Static Sites. We cover key concepts, practical examples, and best practices.

Adding comments to static sites requires third-party services since there is no database or server — GitHub-issue-based tools like utterances and giscus provide free, lightweight, privacy-respecting comment systems that sync with your repository.

What You'll Learn

Why It Matters

Comments drive engagement, provide reader feedback, and build community around your content. Traditional comment systems require a database and moderation backend, but static sites eliminate servers entirely. Third-party comment widgets fill this gap, and choosing the right one affects page load time, user privacy, moderation workflow, and data ownership.

Real-World Use

A developer blog uses utterances to store comments as GitHub Issues, keeping moderation within the existing GitHub workflow. A documentation site uses giscus with GitHub Discussions for threaded conversations and upvoting. A corporate blog chooses Hyvor Talk for its privacy compliance and custom moderation team features.

Comment System Architecture

flowchart TD
  A[Static Page] --> B[Comment Widget JS]
  B --> C{Backend Service}
  C -->|utterances| D[GitHub Issues API]
  C -->|giscus| E[GitHub Discussions API]
  C -->|Disqus| F[Disqus Servers]
  C -->|Hyvor Talk| G[Hyvor Cloud]
  C -->|Self-hosted| H[Your Server]
  D --> I[GitHub Repository]
  E --> I
  F --> J[Disqus Database]
  G --> K[Hyvor Database]
  H --> L[PostgreSQL/SQLite]
  style C fill:#f90,color:#fff

Comment Platform Comparison

Feature utterances giscus Disqus Hyvor Talk Self-hosted (Isso)
Backend GitHub Issues GitHub Discussions Proprietary Proprietary Python/PostgreSQL
Free tier Yes Yes Yes (ads) Limited Yes
Privacy High (no tracking) High (no tracking) Low (tracks users) Medium High
Moderation Via GitHub Via GitHub Dashboard Dashboard Admin panel
Threading Flat Nested Nested Nested Flat
Markdown Yes Yes (GFM) Limited Yes Yes
SSO/LDAP GitHub Auth GitHub Auth Social login Yes Self-managed
Spam filter None None Built-in Built-in Akismet plugin
Load time Very fast Very fast Slow (ads) Fast Fast
Data ownership You (GitHub) You (GitHub) Disqus Hyvor You

utterances Integration

utterances is a lightweight widget that uses GitHub Issues for comment storage. Each page gets its own issue, and readers comment using their GitHub account.

Setup Steps

  1. Install the utterances GitHub App in your repository
  2. Configure the widget with your repo mapping

JavaScript Integration

<div id="utterances-container"></div>
<script src="https://utteranc.es/client.js"
  repo="yourusername/your-repo"
  issue-term="pathname"
  label="comments"
  theme="github-light"
  crossorigin="anonymous"
  async>
</script>

Expected behavior: When the page loads, utterances creates or finds a GitHub Issue matching the page path. Readers sign in with GitHub to post comments, which appear as issue comments. All data lives in your repository.

Hugo Shortcode for utterances

{{/* layouts/shortcodes/utterances.html */}}
{{ if not .Site.IsServer }}
<div class="comments">
  <h2>Comments</h2>
  <script src="https://utteranc.es/client.js"
    repo="{{ .Site.Params.utterancesRepo }}"
    issue-term="{{ .Site.Params.utterancesTerm | default "pathname" }}"
    label="comments"
    theme="{{ .Site.Params.utterancesTheme | default "github-light" }}"
    crossorigin="anonymous"
    async>
  </script>
</div>
{{ end }}

Expected behavior: The shortcode renders the utterances widget only in production (not during local development). Configuration values come from the site parameters, making it easy to switch repositories or themes.

giscus Integration

giscus uses GitHub Discussions instead of Issues, providing threaded conversations, upvotes, and a cleaner UI.

Setup Steps

  1. Install the giscus GitHub App in your repository
  2. Enable Discussions in your repository settings
  3. Get your configuration from the giscus website

JavaScript Integration

<div id="giscus-container"></div>
<script src="https://giscus.app/client.js"
  data-repo="yourusername/your-repo"
  data-repo-id="R_kgDO..."
  data-category="Announcements"
  data-category-id="DIC_kwDO..."
  data-mapping="pathname"
  data-strict="0"
  data-reactions-enabled="1"
  data-emit-metadata="0"
  data-input-position="bottom"
  data-theme="light"
  data-lang="en"
  crossorigin="anonymous"
  async>
</script>

Expected behavior: giscus initializes with the provided configuration, loading comments from GitHub Discussions. Users authenticate via GitHub and can post comments, reply to threads, and add reactions.

giscus Configuration in Hugo

# hugo.toml — giscus parameters
[params]
  giscusRepo = "yourusername/your-repo"
  giscusRepoId = "R_kgDO..."
  giscusCategory = "Announcements"
  giscusCategoryId = "DIC_kwDO..."
  giscusMapping = "pathname"
  giscusTheme = "light"

Disqus Integration

Disqus is the most widely known comment platform but comes with privacy concerns and ad injection on the free tier. It also conflicts with GDPR requirements that static sites typically avoid.

<div id="disqus_thread"></div>
<script>
  var disqus_config = function () {
    this.page.url = "{{ .Permalink }}";
    this.page.identifier = "{{ .RelPermalink }}";
  };
  (function() {
    var d = document, s = d.createElement('script');
    s.src = 'https://your-shortname.disqus.com/embed.js';
    s.setAttribute('data-timestamp', +new Date());
    (d.head || d.body).appendChild(s);
  })();
</script>
<noscript>
  Please enable JavaScript to view the
  <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a>
</noscript>

Privacy and GDPR Compliance

Service Cookies Tracking GDPR Safe Alternative for EU
utterances 0 None Yes utterances (no cookies)
giscus 0 None Yes giscus (no cookies)
Disqus 5+ Behavioral ads No Disqus with Do Not Sell
Hyvor Talk 2 Analytics only Yes Hyvor Talk (EU hosting)
Isso 0 None Yes Isso (self-hosted)

Common Errors

1. Comments Not Loading Due to Missing GitHub App Installation

If utterances or giscus comments do not appear, the GitHub App may not be installed in the repository. Verify the app is installed under your repository settings. Check the browser console for 401 or 403 errors.

2. Cross-Origin Errors with Comment Widgets

Comment widgets loaded from external domains may trigger CORS errors. Ensure the crossorigin="anonymous" attribute is present on the script tag. For utterances, verify the repo name format is owner/repo.

3. Comments Appearing on Wrong Pages

If issue-term is set to pathname but your site uses URL parameters or trailing slashes inconsistently, the same issue may map to multiple pages or the wrong page. Use url mapping or a custom term function for consistent mapping.

4. Rate Limiting with GitHub API

Free GitHub accounts have API rate limits (60 requests/hour for unauthenticated requests). If your site gets heavy traffic, comments may stop loading. utterances and giscus use authenticated requests through the GitHub App, which has higher limits (5,000 requests/hour).

5. Comment Data Loss When Repository Changes

If you rename or transfer the GitHub repository, all existing comment issues are lost. Plan repository names carefully before launching. Use a dedicated repository for comments that will not change.

Practice Questions

1. What is the difference between utterances and giscus?

utterances stores comments as GitHub Issues, while giscus uses GitHub Discussions. giscus supports threaded replies, upvotes, and a richer UI, but requires Discussions to be enabled in the repository.

2. Why is Disqus considered less privacy-friendly than alternatives?

Disqus sets multiple tracking cookies, serves targeted ads on the free tier, and shares user data with third-party ad networks. This violates GDPR requirements without explicit consent.

3. How does utterances map a page to its comment thread?

utterances uses an issue-term parameter that can be set to pathname, url, title, or a custom og:title value. It creates or finds a GitHub Issue matching that term.

4. What happens if the GitHub API rate limit is exceeded?

Comments stop loading temporarily. Authenticated requests (via GitHub App) have a 5,000 requests/hour limit, which is sufficient for most sites. Unauthenticated requests are limited to 60/hour.

5. Challenge: Set up a Hugo shortcode that conditionally renders utterances in production and giscus in a staging environment. Add a fallback message for when JavaScript is disabled. Test both comment systems on the same page.

Mini Project: Comment System Integration with Theme Support

Integrate a comment system into a Hugo theme:

  1. Create a partial layouts/partials/comments.html that supports utterances, giscus, and Disqus
  2. Configure the comment system via hugo.toml parameters
  3. Add a page-level frontmatter toggle to disable comments on specific pages (comments: false)
  4. Implement a dark mode theme that switches the comment widget theme dynamically
  5. Test the integration on a single page and verify comments appear, post correctly, and respect the dark mode setting

Example frontmatter:

---
title: "My Blog Post"
comments: true
commentSystem: giscus
---

The partial implementation:

{{/* layouts/partials/comments.html */}}
{{ if and .Params.comments (not .Site.IsServer) }}
  <section class="comments">
    <h2>Comments</h2>
    {{ if eq .Params.commentSystem "giscus" }}
      {{ partial "comments/giscus.html" . }}
    {{ else if eq .Params.commentSystem "utterances" }}
      {{ partial "comments/utterances.html" . }}
    {{ else }}
      {{ partial "comments/disqus.html" . }}
    {{ end }}
  </section>
{{ end }}

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro