Add a Voice AI Agent to a Hugo Site (2026 Guide)
Add the AnveVoice voice agent to a Hugo site: baseof.html or a partial, theme overrides, new versus old layout paths, and a production-only guard.
How to add AnveVoice to a Hugo site
In Hugo, the page skeleton is the base template, baseof.html. Add the AnveVoice script tag near the end of its body, ideally through a small partial, and every page that uses the base template carries it. If your theme owns baseof.html, copy it into your project first. Steps checked against the official documentation on 2026-10-14.
At a glance
- Where the code goes: layouts/baseof.html (Hugo 0.146 and later) or layouts/_default/baseof.html (older)
- Coding needed: One line of template; Go template syntax for the optional guard
- Plan limits: None from Hugo. Free AnveVoice plan is enough
- Time: About 3 minutes
Know which template layout you have
Hugo v0.146.0 re-implemented how templates are looked up. According to the project's template-system overview, the _default folder no longer exists, files that were in layouts/_default now sit directly in layouts, and the partials folder is renamed _partials. Hugo's base template reference places the page skeleton at layouts/baseof.html. Run hugo version. From 0.146 on, use layouts/baseof.html and layouts/_partials. On older versions, the same files live under layouts/_default/baseof.html and layouts/partials. The code you paste is identical in both; only the paths differ.
- 1. Copy the install tag — Create a bot at app.anvevoice.app and copy its embed ID. We will store it in site configuration, so keep the value handy. Code: <script src="https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID" async></script>
Method 1: a partial included from baseof.html (recommended)
Partials are Hugo's reusable fragments. The partial reference shows them stored in layouts/_partials and called with the partial function, passing the context as the second argument. Putting the AnveVoice tag in its own partial keeps baseof.html tidy and makes the tag easy to remove.
- 1. Store the embed ID — Add a params table to hugo.toml (hugo.yaml and hugo.json also work). Hugo's params reference shows custom values under [params], read in templates through .Site.Params. Code: [params] anvevoiceEmbedId = "YOUR_EMBED_ID"
- 2. Create the partial — Make layouts/_partials/anvevoice.html with this content. Hugo's context here is the page; the site-wide value comes through site.Params. Code: <script src="https://anvevoice.app/embed.js?embedId={{ site.Params.anvevoiceEmbedId }}" async></script>
- 3. Call it from baseof.html — Open layouts/baseof.html and add the call on the line before the closing body tag. Code: {{ partial "anvevoice.html" . }} </body>
If the base template comes from a theme
Hugo looks in your project before it looks in themes. Its theme-components documentation states that for any given file Hugo checks the project first, and that layouts merge at file level with the left-most file winning. So a layouts/baseof.html in your project replaces the theme's file of the same name. Copy the theme's baseof.html (found under themes/NAME/layouts, or in the module cache if you use Hugo Modules) into your layouts folder, then edit your copy. You then no longer receive upstream changes to that one file, which is the price of the override. Some themes expose a hook such as a custom footer partial; check the theme's documentation first, since using that avoids copying anything.
Production-only loading
The configuration docs say hugo server defaults to the development environment and hugo build defaults to production, and the HUGO_ENVIRONMENT variable or the --environment flag overrides this. The template function hugo.IsProduction reports whether the running environment is production, so you can wrap the call and keep the button off your local preview.
- 1. Wrap the partial call — Edit baseof.html so the partial renders only in production builds. Code: {{ if hugo.IsProduction }} {{ partial "anvevoice.html" . }} {{ end }}
Hugo-specific gotchas
- Pages that bypass baseof.html, such as RSS, sitemap and custom output formats, never receive the tag. That is normal, because they are not web pages.
- Hugo does not clear the public directory before building, so old files can linger. If you rename or remove things, delete public first for a clean output.
- Shortcodes and content files are not the place for a site-wide tag. Using baseof.html is what puts it on every page once.
- If a page type defines its own baseof, for example layouts/docs/baseof.html, that section has its own skeleton and needs the same partial call.
- Hugo's HTML templates auto-escape values inside URLs. An embed ID of letters and numbers passes through unchanged.
Check that it works
- 1. Build for production — Run hugo (or hugo build). Hugo's usage guide says it writes the site to the public directory.
- 2. Search the output — Open public/index.html and look for anvevoice.app near the end of the body. It should appear once.
- 3. Load a page — Serve public or visit the deployed site over HTTPS. The round microphone button should be at bottom-right; click it and allow the microphone.
Common problems
- Embed ID renders empty: the key name in the partial differs from hugo.toml. Params keys are case-insensitive in Hugo but must otherwise match, and kebab-case keys cannot be chained in templates.
- partial not found: you created layouts/partials on a 0.146+ site (use _partials) or _partials on an older site.
- Works with hugo build, not hugo server: you added the production guard. Run with --environment production, or remove the guard.
- Netlify or another host shows no button: their build uses an older Hugo. Pin the version in the host's settings to match your local one.
Sources
- Hugo docs: new template system in v0.146.0 (https://gohugo.io/templates/new-templatesystem-overview/) — checked 2026-10-14
- Hugo docs: base templates (layouts/baseof.html) (https://gohugo.io/templates/base/) — checked 2026-10-14
- Hugo docs: partial templates (https://gohugo.io/templates/partial/) — checked 2026-10-14
- Hugo docs: configuration introduction (environments) (https://gohugo.io/configuration/introduction/) — checked 2026-10-14
- Hugo docs: usage (public directory) and configure params (https://gohugo.io/getting-started/usage/) — checked 2026-10-14
- Hugo docs: configure params (https://gohugo.io/configuration/params/) — checked 2026-10-14
Related
- How to add AnveVoice to an Eleventy site
- How to add AnveVoice to a Jekyll site
- How to add AnveVoice to a Hexo site
- How to add AnveVoice to a plain HTML website
Try AnveVoice on your site
Free plan: $0, 50,000 tokens a month, no card. Get your embed ID in the dashboard, then paste one tag.