Add a Voice AI Agent to an Eleventy (11ty) Site
Add the AnveVoice voice agent to an Eleventy site: where the base layout lives, using _data for the embed ID, serve versus build mode and fixes.
How to add AnveVoice to an Eleventy site
Eleventy has no fixed page template, so the tag goes in the layout your pages use, usually a base layout in _includes. Paste the AnveVoice script tag before the closing body tag in the outermost layout, rebuild, and every page that uses it carries the voice agent. Steps checked against the official documentation on 2026-10-14.
At a glance
- Where the code goes: The outermost layout file, for example _includes/layouts/base.njk
- Coding needed: One line of template; an optional data file for the embed ID
- Plan limits: None from Eleventy. Free AnveVoice plan is enough
- Time: About 2 minutes
Find the right layout
Eleventy's layouts documentation explains the mechanism: a template opts in with a layout key in its front matter, and the layout file receives the page output as content. By default layouts are looked up in the _includes folder, and subfolders are allowed, so layout: layouts/base.njk means the file _includes/layouts/base.njk. Layouts can wrap other layouts, with the one closest to the content applying first. That chaining matters here. If a post layout wraps a base layout which wraps everything, the closing body tag exists only in the outermost one. Add the tag there and every page is covered, instead of repeating it in each layout. Look at the front matter of any page, for example index.md or a post, to see its layout value, then open the chain until you reach the file containing the html element.
- 1. Copy the install tag — Create a bot at app.anvevoice.app, copy the embed ID and put it where YOUR_EMBED_ID appears. Add &position=bottom-left or &theme=dark if you like. Code: <script src="https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID" async></script>
Method 1: paste it into the base layout
- 1. Open the outermost layout — In most starters this is _includes/layouts/base.njk or base.liquid. If you set a separate layouts directory in your config, look there instead. Config defaults are input of the current folder, includes of _includes and output of _site.
- 2. Insert before the closing body tag — Place the tag on the line directly above </body>. It is plain HTML, so it works in Nunjucks, Liquid, WebC, Handlebars and JavaScript layouts alike.
- 3. Rebuild — Run npx @11ty/eleventy --serve for a local server that refreshes on change, or npx @11ty/eleventy to write the site into _site.
Method 2: keep the embed ID in global data
Eleventy's global data feature turns every JSON file or JavaScript module in the _data folder into a variable named after the file. A file called anvevoice.json therefore becomes {{ anvevoice }} in every template, with the lowest priority in the data cascade so front matter can override it. This keeps the ID out of layout code and lets you swap it for staging.
- 1. Create _data/anvevoice.json — Put your ID in one place. Code: { "embedId": "YOUR_EMBED_ID" }
- 2. Reference it in the layout — In Nunjucks or Liquid, use double braces around anvevoice.embedId inside the URL. Code: <script src="https://anvevoice.app/embed.js?embedId={{ anvevoice.embedId }}" async></script>
Method 3: show it only on the built site
Eleventy 2.0 added an ELEVENTY_RUN_MODE environment variable whose value is build, serve or watch. The documentation notes that environment variables are available in JavaScript files evaluated at build time, so templates in other languages need the value exposed through a data file. That is useful if you want the button on the deployed site but not while writing.
- 1. Expose the mode — Create _data/anvevoice.js. On Eleventy 3 you may use export default instead of module.exports. Code: module.exports = { embedId: "YOUR_EMBED_ID", enabled: process.env.ELEVENTY_RUN_MODE === "build", };
- 2. Wrap the tag — Use an if block in your layout language so the tag renders only when enabled is true. Code: {% if anvevoice.enabled %} <script src="https://anvevoice.app/embed.js?embedId={{ anvevoice.embedId }}" async></script> {% endif %}
Gotchas specific to Eleventy
- Pages with no layout, or with layout set to false, do not receive the tag, including RSS files, redirects and any raw HTML template. Add the tag to those pages directly if they are real pages.
- Eleventy is a static builder, so the voice button works anywhere you host the _site folder: Netlify, Cloudflare Pages, GitHub Pages or a plain server. Deploy the new output after every layout change.
- Passthrough files copied as-is are not templated. If you ship a hand-written HTML file that way, the layout edit will not reach it.
- A multi-language site with a layout per locale needs the tag in each outermost layout, or a shared partial included by all of them.
Check that it works
- 1. Open the output — Look at _site/index.html after a build and search for anvevoice.app. It should appear once, just before </body>.
- 2. Load it in a private window — Serve _site or open the deployed address. Microphone access needs HTTPS on a live site.
- 3. Use the button — Click the round microphone button at bottom-right, allow microphone access and ask a question.
Common problems
- No button locally: with Method 3 the mode is serve, so enabled is false. Build, then open _site.
- Template error on the braces: you are using a language where double braces mean something else. Use that language's output syntax.
- Tag shown as text: the layout escapes HTML. Ensure the tag sits in the layout, not in a variable that is escaped on output.
- Button on some pages only: those pages use a different layout chain. Trace their layout values.
Sources
- Eleventy docs: layouts (https://www.11ty.dev/docs/layouts/) — checked 2026-10-14
- Eleventy docs: configuration (directories) (https://www.11ty.dev/docs/config/) — checked 2026-10-14
- Eleventy docs: global data files (https://www.11ty.dev/docs/data-global/) — checked 2026-10-14
- Eleventy docs: environment variables (https://www.11ty.dev/docs/environment-vars/) — checked 2026-10-14
- Eleventy docs: command line usage (https://www.11ty.dev/docs/usage/) — checked 2026-10-14
Related
- How to add AnveVoice to a Hugo 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.