Comments with giscus
OINK supports giscus through a Hextra-compatible comments configuration
under params.comments. giscus gives each content page a comment thread backed
by GitHub Discussions and lets readers comment through GitHub OAuth.
How giscus works
When a page loads, giscus searches the configured repository for a Discussion that matches the page. If it does not find one, the giscus bot creates it when a reader submits the first comment or reaction. Maintainers moderate comments in GitHub Discussions.
Anyone can read a public thread. To comment, a reader selects Sign in with GitHub and authorizes the giscus app to post on their behalf. OINK never asks for or stores the reader’s GitHub password or access token.
giscus is an opt-in online integration. Active comment pages load a script and
iframe from https://giscus.app; they do not work in a network-isolated
runtime. Document this external boundary in the consuming site’s privacy and
security policy when required.
Prepare GitHub
Before configuring OINK:
- Use a public GitHub repository for the comment threads. Visitors cannot read Discussions in a private repository.
- Enable GitHub Discussions under the repository’s Settings > Features.
- Install the giscus GitHub App for that repository. Without the app, visitors cannot comment or react.
- Choose a Discussion category. giscus recommends an Announcements category so that only maintainers and the giscus bot can create new Discussions.
The repository ID and category ID are public identifiers, not credentials. Do not add a GitHub personal access token, OAuth secret, or password to Hugo configuration.
Generate repository settings
Open giscus.app and complete its configuration form:
- Select the interface language.
- Enter the repository as
OWNER/REPOSITORYand wait for the validation to succeed. - Select the page-to-Discussion mapping.
pathnameis OINK’s default. - Choose the Discussion category and optional features.
- Locate the generated
<script>block.
Copy these generated values into OINK configuration:
| Generated attribute | OINK key |
|---|---|
data-repo |
repo |
data-repo-id |
repoId |
data-category |
category |
data-category-id |
categoryId |
Choose a stable mapping
The mapping determines which Discussion belongs to each page. pathname is a
good default when published paths are stable and the same repository serves
multiple domains or preview environments.
Changing mapping, moving a page, or changing its permanent URL can make giscus
look for a different Discussion. Choose the mapping before collecting comments
and preserve redirects or Discussion titles during a migration. Enable strict
matching when similar page paths could otherwise select the wrong thread.
Enable comments site-wide
Add the generated identifiers to the consuming site’s hugo.yml and set
enable: true:
params:
comments:
enable: true
type: giscus
giscus:
repo: OWNER/REPOSITORY
repoId: REPOSITORY_ID
category: Announcements
categoryId: CATEGORY_ID
mapping: pathname
strict: 0
reactionsEnabled: 1
emitMetadata: 0
inputPosition: top
theme: auto
loading: lazyReplace all uppercase placeholders with the exact values generated by
giscus.app. OINK requires repo, repoId, category, and categoryId before
it renders giscus. Missing or blank required values produce a Hugo warning and
skip giscus instead of failing the build.
Configuration reference
| Key | Default | Purpose |
|---|---|---|
enable |
false |
Enables the configured comment provider globally. |
type |
giscus |
Selects giscus. Other provider names are not supported. |
repo |
— | Public repository in OWNER/REPOSITORY form. |
repoId |
— | Repository node ID generated by giscus.app. |
category |
— | GitHub Discussions category name. |
categoryId |
— | Category node ID generated by giscus.app. |
mapping |
pathname |
Maps the current page to a Discussion. |
term |
— | Supplies the term required by mappings such as specific or number. |
strict |
0 |
Uses strict Discussion-title matching when set to 1. |
reactionsEnabled |
1 |
Shows reactions for the Discussion’s main post. |
emitMetadata |
0 |
Sends Discussion metadata messages to the parent page. |
inputPosition |
top |
Places the comment editor at top or bottom. |
theme |
auto |
Follows the OINK theme, or selects a built-in/custom giscus theme. |
lang |
Page language | Overrides the automatically selected giscus interface language. |
loading |
lazy |
Defers iframe loading until the reader approaches the comments. |
ariaLabel |
Comments |
Labels the comments region for assistive technology. |
errorMessage |
Load-error text | Replaces the message shown when giscus cannot load. |
Boolean-like feature values accept YAML booleans or giscus-style 0 and 1
values.
Locale, theme, and accessible text
OINK selects the giscus locale from the active Hugo language. Simplified,
Traditional, and Hong Kong Chinese map to the corresponding giscus locales;
unsupported languages fall back to English. Set lang only when the automatic
choice is not appropriate.
With theme: auto, the iframe follows OINK’s light/dark selector and the
browser’s preferred color scheme. A built-in giscus theme name or custom theme
URL disables that automatic switch.
For a multilingual site, localize the comments-region label and load-error text under each language’s parameters. Language parameters merge with the global repository settings:
languages:
en:
params:
comments:
giscus:
ariaLabel: Comments
errorMessage: Comments could not be loaded.
zh:
params:
comments:
giscus:
ariaLabel: 评论
errorMessage: 评论加载失败。Override one page
The comments front matter field overrides the global switch in either
direction.
Enable one page
Keep the complete repository configuration in hugo.yml, leave the global
switch off, and opt in selected pages:
---
title: Community design notes
comments: true
---Disable one page
When comments are enabled globally, opt out pages that should remain static:
---
title: Security policy
comments: false
---An explicit comments: false suppresses both giscus and legacy Disqus on that
page.
Coexist with Disqus
OINK keeps existing Hugo Disqus configuration compatible during migration. When valid giscus configuration is active for a page, OINK suppresses Disqus so that only one comment system renders. If giscus is enabled but its required settings are incomplete, OINK warns, skips giscus, and can leave configured Disqus as a fallback.
Remove the Disqus service configuration after the migration is complete and every intended page uses giscus.
Content Security Policy
A strict Content Security Policy must permit giscus in both script-src and
frame-src. Merge these sources into the site’s existing policy instead of
replacing its other directives:
script-src 'self' https://giscus.app;
frame-src 'self' https://giscus.app;OINK’s initializer remains a same-origin bundled asset and is included only on
pages where giscus is active. If the external script fails or does not create an
iframe, OINK clears the loading state and exposes errorMessage in a live
status region.
Verify the integration
-
Build the site and confirm there is no missing-key warning:
hugo --minify -
Start a local preview and open a page where comments should be active:
hugo server --disableFastRender -
Confirm that the giscus iframe shows Sign in with GitHub and uses the active page language.
-
Toggle OINK between light and dark themes and confirm that the comment widget follows it when
theme: auto. -
Open a page with
comments: falseand confirm that it has no giscus or Disqus widget. -
Submit one test comment, then confirm that the expected Discussion appears in the configured category and can be moderated on GitHub.
A browser-console message saying that the Discussion was not found is expected before the first comment or reaction creates it.
Troubleshooting
- The build warns about missing keys: regenerate the configuration at giscus.app and copy all four required identifiers without renaming them.
- The widget does not appear: check
params.comments.enable,params.comments.type, the page’scommentsfront matter, and Hugo’s warning output. - GitHub sign-in or posting fails: confirm that the repository is public, Discussions are enabled, and the giscus GitHub App is installed for the repository.
- The browser blocks giscus: inspect the console and response headers, then
allow
https://giscus.appin the applicable CSP directives. - An existing thread is not found: restore the original mapping and page path, or rename/migrate the Discussion deliberately before changing the URL.
- The interface language is wrong: verify the Hugo language name and locale,
or set
params.comments.giscus.langexplicitly.