Comments
OINK’s comments run on giscus: each page maps to one GitHub Discussion, readers sign in with a GitHub account to post, and maintainers moderate in GitHub Discussions. The theme provides no comment backend of its own and bundles no provider other than giscus.
The prerequisite is a public GitHub repository; a visitor cannot read a private repository’s Discussions.
A page with comments enabled loads a script and an iframe from
https://giscus.app, which does not work in a network-isolated environment.
It is off by default and loads only when explicitly enabled. Where a site has
a privacy policy, this external data boundary belongs in it.
Preparing the GitHub repository
-
Choose a public repository to hold the comment threads; the site’s source repository works.
-
In the repository’s Settings → General → Features, tick Discussions.
-
Install the giscus GitHub App for that repository. Without the App, visitors cannot comment or react.
-
Choose a Discussion category. giscus recommends the Announcements type: only maintainers and the giscus bot can open a Discussion there, so readers cannot start one by accident.
The repository ID and category ID are public identifiers, not credentials. Never put a personal access token, an OAuth secret or a password in Hugo configuration.
Generating the configuration
Open giscus.app, fill in the repository, mapping and
category, and the page generates a <script> block below. Copy four of its
attributes into the OINK configuration:
The mapping decides which page corresponds to which Discussion. OINK defaults
to pathname, which suits a site with stable published paths and one repository
serving several domains or preview environments. Changing mapping or moving a
page after comments have accumulated makes giscus look for a different
Discussion: the existing comments are not deleted, but the page can no longer
find them. Settle the mapping before launch; where a URL really must change,
keep a redirect or rename the Discussion at the same time.
Enabling it site-wide
Write the generated identifiers into the site configuration:
That is this site’s live configuration. All four of repo, repoId,
category and categoryId are required: if any is missing or only whitespace,
Hugo prints one WARNING and skips giscus without failing the build — which is
why a production build carries --panicOnWarning. type accepts only giscus
today, and any other value likewise warns and skips. The params.comments key
names match Hextra’s, so a configuration migrated from Hextra transfers as it
stands.
The remaining keys (strict, reactionsEnabled, emitMetadata, term,
lang, lightTheme, darkTheme, ariaLabel, errorMessage) all have
defaults, defined fully in Configuration. A feature
switch takes either a YAML boolean or giscus-style 0 / 1.
Per-page control
comments in front matter overrides the site switch in either direction, and
the value nearest the page wins.
To enable comments on selected pages only, turn the site switch off while keeping the full repository configuration, then let chosen pages opt in:
To disable them on selected pages, leave the site switch on and let unsuitable pages opt out:
Use a cascade to set a whole section at once. This site writes comments: true
in the cascade of content/docs/_index.md, which is why a real giscus section
sits at the bottom of this page.
Where a site also configures services.disqus.shortname, giscus wins: an active
giscus suppresses Disqus, comments: false turns off both, and if a required
giscus key is missing it warns, skips, and lets Disqus take over.
Multilingual text
giscus’s interface language follows the current Hugo language automatically:
Simplified, Traditional and Hong Kong Traditional Chinese each map to the
corresponding giscus locale, and an unsupported language falls back to English.
Set lang explicitly only where the automatic choice is wrong.
What does need translating is the two strings on OINK’s side: the comment section’s accessible label and the loading-failure message. They are configured per language and merged with the global repository configuration:
A language layer only needs the differences; repo / repoId / category /
categoryId stay in params.comments.
Following light and dark
With theme: auto, the giscus iframe follows OINK’s light/dark control and the
browser’s prefers-color-scheme, so the comment section changes with the rest
of the page.
For a closer match to the site’s palette, give lightTheme / darkTheme two
giscus themes; each value is a built-in giscus theme name or CSS hosted by the
site. This site does the latter:
A fixed theme name in theme stops it following the toggle.
A custom giscus theme has to be readable cross-origin
The giscus iframe loads from giscus.app, so reading a CSS file on your site
requires CORS to allow it. This site adds
Access-Control-Allow-Origin: '*' under server.headers in hugo.yml for
local preview; in production it is the host’s response header configuration.
Privacy and CSP
- OINK never asks for or stores a reader’s GitHub password or access token; signing in and posting happen entirely on the giscus / GitHub side.
- The comment initialization script is a same-origin asset shipped with the theme, added only to pages with comments enabled; a page without them has no such script.
- With
loading: lazy, the iframe loads only as the reader scrolls near the comment section. - Where a site has a strict Content Security Policy, both
script-srcandframe-srcmust permit giscus — merged into the existing policy rather than replacing other directives (the general rules are in Content Security Policy):
When the external script fails to load or no iframe is created, OINK ends the
loading state and shows errorMessage in a live status region rather than
leaving the page on “loading”.
Verify
Then confirm each of these:
- Open a page that should have comments: giscus appears at the bottom, showing “Sign in with GitHub”, with its interface in the current page’s language.
- Toggle OINK’s light/dark control and the comment section follows (with
theme: auto). - Open a page with
comments: falseand confirm there is neither giscus nor any other comment component. - Post a test comment, return to GitHub, and confirm a Discussion appeared in the chosen category and can be managed there.
Before the first comment or reaction creates a Discussion, a browser console message saying the Discussion was not found is expected.
When something is wrong, check in this order: WARNINGs in the build log (the
four required keys) → params.comments.enable and type → the page’s
comments front matter → whether the repository is public, Discussions are
enabled and the giscus App is installed → the browser console and response
headers (whether a CSP blocked giscus.app). If existing threads have gone
missing, restore the original mapping and page path first.
Related
- Repository links and page info — edit this page, open an issue, contributors and the “was this helpful?” widget
- Analytics and SEO — the other capability needing an external service
- Deploy — Content Security Policy and external integrations in preview deployments
- Configuration — every
params.comments.*key - Page parameters —
commentsin front matter