Skip to content

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.

5 min setup No dependencies
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

Step 1 — Create the partial

Create a new file at layouts/partials/echothread.html:

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:

layouts/_default/single.html {{ 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.
Recommendation: Use {{ .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>
Hugo params: You can pull theme values from your Hugo config. For example, set 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:

layouts/partials/echothread.html (updated) {{ 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:

content/about.md --- 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 localhost for local dev).
  • Open your browser's developer console and look for network errors on the widget.js request.

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