Add a Voice AI Agent to an Ember.js App (2026)
Add the AnveVoice voice agent to Ember.js: which index.html to edit in Vite and classic builds, the content-for hooks, an initializer option and checks.
How to add AnveVoice to an Ember.js app
Ember apps boot from a single index.html. In apps generated since Ember 6.8 that file is at the project root; in older classic-build apps it is app/index.html. Paste the AnveVoice tag in that file's body, just above the body-footer hook, then rebuild. Steps checked against the official documentation on 2026-10-14.
At a glance
- Where the code goes: index.html (Vite-based apps, root) or app/index.html (classic Broccoli apps)
- Coding needed: One line of HTML; an initializer is optional
- Plan limits: None from Ember. Free AnveVoice plan is enough
- Time: About 2 minutes plus a build
Which Ember build do you have?
Ember's CLI documentation notes that the default build environment switched to Vite at Ember 6.8, and that Vite builds are supported on apps back to Ember 3.28. Your project's page template therefore lives in one of two places, and editing the wrong one is the usual reason an added tag never shows up. Check package.json. If it has a build script that runs vite build and a vite.config file sits in the project root, you have a Vite app, and the page template is index.html in the root. If instead ember-cli-build.js is the only build file, you have a classic app, and the CLI's folder-layout reference lists app/index.html as the single page of the app.
- 1. Copy the install tag — Create a bot at app.anvevoice.app, copy the embed ID, and drop it into the URL. Add &position=bottom-left or &theme=dark if you want. Code: <script src="https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID" async></script>
Method 1: edit index.html
The file is a template. The Ember app blueprint's index.html contains four placeholders written as content-for with the names head, head-footer, body and body-footer. Ember fills them with output from addons and from the framework. You should leave them alone and add your own line beside them.
- 1. Open the right file — Root index.html for Vite-based apps; app/index.html for classic apps. Do not use tests/index.html, which is the page the test runner loads.
- 2. Paste above the body-footer hook — Insert the AnveVoice tag on the line before the content-for "body-footer" placeholder, after the application script. Keep the placeholders and the app boot script exactly as generated.
- 3. Build — npm start runs the Vite dev server (Ember's quick-start guide says the start script defers to Vite on current apps) and npm run build runs vite build, writing the deployable site to dist/. Classic apps use ember serve and ember build.
Method 2: an initializer for conditional loading
Ember's guides describe application initializers as the place to configure an app while it boots, in app/initializers, and instance initializers in app/instance-initializers for per-instance setup. Use one when the script must load only in production, or only when a feature flag is on. Generate it with ember generate initializer anvevoice, then edit the file. FastBoot or server-rendered Ember has no document at boot. Guard the initializer with typeof document !== 'undefined' if you render on the server.
- 1. Write the initializer — This version loads the script in production only and avoids adding it twice. Replace my-app with the name from your package.json, and YOUR_EMBED_ID with your ID. Code: // app/initializers/anvevoice.js import config from 'my-app/config/environment'; export function initialize() { if (config.environment !== 'production') return; const src = 'https://anvevoice.app/embed.js?embedId=YOUR_EMBED_ID'; if (document.querySelector(`script[src="${src}"]`)) return; const s = document.createElement('script'); s.src = src; s.async = true; document.body.appendChild(s); } export default { initialize };
Routing, the public folder and caching
- Ember's router is client-side, so transitions between routes do not reload index.html. The tag runs once per full load and the button persists.
- The public folder is copied verbatim into the build root and is for assets without a build step. Putting a copy of embed.js there is not useful; use the remote URL so the script stays current.
- Fingerprinted app assets change on every build, but index.html itself should not be cached for long. If visitors keep seeing an old page without the button, shorten the cache time on index.html at your host or CDN.
- Apps with a Content Security Policy, for example through an addon, need https://anvevoice.app allowed in script-src and connect-src.
Check that it works
- 1. Serve or deploy — Load the app in a private window. Ember dev servers use http://localhost:4200, which browsers treat as a secure context for the microphone.
- 2. Look for the button — A round microphone button should sit bottom-right. Click it, allow the microphone and ask something.
- 3. Verify the built file — Open dist/index.html and search for anvevoice.app. With Method 2 expect no match in the HTML, because the tag is added at runtime.
Common problems
- Nothing changes after editing: you edited app/index.html in a Vite app, or the root index.html in a classic app. Re-check the build type.
- Placeholder text visible: a content-for line was edited or removed. Restore it from version control.
- Initializer error, config not found: the import path must use your app's module name from package.json, not a literal my-app.
- Button appears in production only: that is the behaviour of the environment check in Method 2. Remove it to test locally.
Sources
- Ember CLI docs: folder layout (app/index.html, public) (https://cli.emberjs.com/release/basic-use/folder-layout/) — checked 2026-10-14
- Ember guides: Vite build tools (start and build scripts) (https://guides.emberjs.com/release/build-tools/vite/) — checked 2026-10-14
- Ember guides: quick start (npm start and build) (https://guides.emberjs.com/release/getting-started/quick-start/) — checked 2026-10-14
- Ember guides: initializers (https://guides.emberjs.com/release/applications/initializers/) — checked 2026-10-14
- Ember app blueprint: index.html (GitHub source) (https://github.com/ember-cli/ember-app-blueprint/blob/main/files/index.html) — checked 2026-10-14
Related
- How to add AnveVoice to an Angular application
- How to add AnveVoice to a React app
- How to add AnveVoice to a Vue app
- 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.