How to add comments to a Hugo site
Add EchoThread comments to a Hugo static site. Partial templates, per-post threads, theming, front-matter toggles, and multilingual setups.
On this page
Why Hugo + EchoThread
Hugo is one of the fastest static site generators available, but static sites have no built-in backend for comments. Most Hugo users either skip comments entirely or resort to heavyweight third-party services that inject ads and tracking scripts.
EchoThread is built for exactly this use case: a lightweight, privacy-first comment widget that loads from a CDN with zero dependencies. The entire widget is under 20 KB gzipped, so it won't slow down your blazing-fast Hugo build.
Prerequisites
- A Hugo site (any version)
- An EchoThread account — create one free
- Your site's API key from the EchoThread dashboard
Step 1 — Create the partial
Create a new file at layouts/partials/echothread.html:
<!-- EchoThread comments widget -->
<div id="echothread"
data-api-key="YOUR_API_KEY"
data-page-url="{{ .Permalink }}"
data-identifier="{{ .File.UniqueID }}"
data-page-title="{{ .Title }}"></div>
<script src="https://cdn.echothread.io/widget.js" async></script>
Replace YOUR_API_KEY with the API key from your EchoThread dashboard.
Step 2 — Include in your layout
Open your single post layout — usually layouts/_default/single.html or layouts/posts/single.html — and add the partial where you want comments to appear:
{{ define "main" }}
<article>
<h1>{{ .Title }}</h1>
{{ .Content }}
<!-- Comments -->
{{ partial "echothread.html" . }}
</article>
{{ end }}
That's it — comments will now appear on every page that uses this layout.
Choosing an identifier
The data-identifier attribute determines which comment thread is loaded. If you change your URL structure later, the identifier keeps comments attached to the right page.
Hugo gives you several good options:
{{ .File.UniqueID }}— a hash of the file path. Stable as long as you don't move the file.{{ .RelPermalink }}— the relative URL, e.g./blog/my-post/.{{ .Params.comment_id }}— a custom front matter field you control entirely.{{ .File.ContentBaseName }}— the filename without extension, e.g.my-post.
{{ .File.UniqueID }} for most sites. If you use a custom field like comment_id, you get full control but need to remember to set it in every post's front matter.
Theming
EchoThread follows the visitor's OS preference (light/dark) by default. You can override this with the data-theme attribute:
<!-- Force dark mode -->
<div id="echothread"
data-api-key="YOUR_API_KEY"
data-theme="dark"></div>
<!-- Custom background color (text adapts automatically) -->
<div id="echothread"
data-api-key="YOUR_API_KEY"
data-theme="#FAF7F2"></div>
You can also set a custom accent color for buttons and links:
<div id="echothread"
data-api-key="YOUR_API_KEY"
data-accent-color="#2563eb"></div>
data-theme="{{ .Site.Params.echothread_theme | default "auto" }}" and configure it in hugo.toml under [params].
Disable per page
Wrap the partial in a conditional so you can disable comments on specific pages via front matter:
{{ if ne .Params.comments false }}
<div id="echothread"
data-api-key="YOUR_API_KEY"
data-page-url="{{ .Permalink }}"
data-identifier="{{ .File.UniqueID }}"
data-page-title="{{ .Title }}"></div>
<script src="https://cdn.echothread.io/widget.js" async></script>
{{ end }}
Then in any post's front matter, set comments: false to hide the widget:
---
title: "About Me"
comments: false
---
Multilingual sites
Hugo's multilingual mode creates separate URL trees per language. EchoThread automatically creates a unique thread per URL, so each language version of a post gets its own comment thread.
If you want to share comments across translations, use a language-independent identifier:
data-identifier="{{ .File.TranslationBaseName }}"
This uses the filename (without the language suffix), so my-post.en.md and my-post.fr.md will share the same thread.
Troubleshooting
Comments don't appear
- Check that your API key is correct — you can verify it in the dashboard.
- Make sure the domain in your EchoThread site settings matches your Hugo site's domain (including
localhostfor local dev). - Open your browser's developer console and look for network errors on the
widget.jsrequest.
Comments load on the wrong page
This usually means data-identifier is the same across multiple pages. Verify the identifier is unique per page by inspecting the rendered HTML.
Widget doesn't match my theme
Use data-theme to match your Hugo theme's background. For full control, override the CSS custom properties on .et-widget. See the theming docs for all available variables.
Ready to add comments to your Hugo site?
Free during beta. Set up in under 5 min.
Create free account