Embeddable multi-language chat + voice assistant widget. Single script tag embed, customizable via window.AgentWidgetConfig. Backend powered by Vercel AI SDK with Google's Gemini.
- Install deps
npm install
- Configure API key
- Copy
.env.exampleto.envand setGOOGLE_GENERATIVE_AI_API_KEY
- Copy
- Run dev servers
npm run dev:server(Express on http://localhost:8788)- In another terminal:
npm run dev(Vite on http://localhost:5173)
- Open app:
http://localhost:5173(default Vite app) — the widget auto-mounts on any page including this one.
npm run build
npm run preview
# then open http://localhost:4173
The bundle is emitted as dist/agent-widget.js. Embed it on any site:
<script>
window.AgentWidgetConfig = {
position: "bottom-right",
theme: { primaryColor: "#4F46E5" },
agent: { name: "HelperBot", avatar: "https://example.com/avatar.png" },
enableVoice: true,
languageOptions: ["en", "hi", "es"],
context: "You are a front-end expert",
};
</script>
<script src="https://your-cdn/"></script>- Add config before the script
<script>
window.AgentWidgetConfig = {
position: "bottom-right",
theme: {
primaryColor: "#4F46E5",
backgroundColor: "#ffffff",
textColor: "#111827",
fontFamily:
"Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif",
},
agent: { name: "HelperBot", avatar: "" },
enableVoice: true,
languageOptions: ["en", "hi", "es"],
context: "You are a front-end expert",
};
// Optional: point the widget to your API base (defaults to same origin)
// window.__AGENT_WIDGET_API_BASE__ = ""; // same origin (e.g. Netlify with redirect)
// window.__AGENT_WIDGET_API_BASE__ = "https://your-site.netlify.app";
// window.__AGENT_WIDGET_API_BASE__ = "https://api.yourdomain.com";
</script>- Load the bundle
- Pinned version:
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>- Latest (auto-updates):
<script src="https://cdn.jsdelivr.net/npm/ai-chat-widget-react@latest"></script>Note: Do not use type="module" for this IIFE bundle.
- Configure the API path
- Netlify Functions (recommended, same-origin):
<script>
window.__AGENT_WIDGET_API_BASE__ = ""; // same origin; ensure redirect /api/* -> /.netlify/functions/:splat
</script>- External backend:
<script>
window.__AGENT_WIDGET_API_BASE__ = "https://api.yourdomain.com";
</script>- Programmatic control (optional)
<script>
// window.AgentWidget.open();
// window.AgentWidget.close();
// window.AgentWidget.toggle();
</script><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<script>
window.AgentWidgetConfig = {
position: "bottom-right",
theme: {
primaryColor: "#4F46E5",
backgroundColor: "#ffffff",
textColor: "#111827",
},
agent: { name: "HelperBot", avatar: "" },
enableVoice: true,
languageOptions: ["en", "hi", "es"],
context: "You are a front-end expert",
};
window.__AGENT_WIDGET_API_BASE__ = ""; // same origin (e.g. Netlify)
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
</body>
</html>Gotchas:
- Define
window.AgentWidgetConfig(and optionalwindow.__AGENT_WIDGET_API_BASE__) before the CDN script. - If calling cross-origin, ensure CORS allows
POSTwithContent-Type: application/json.
- POST
/api/chatwith JSON body:{ messages: {role, content}[], context?: string, lang?: string } - Local development served by Express (
server/index.ts). - Vercel deployment supported via
api/chat.tsserverless function.
position:'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'theme:primaryColor,backgroundColor,textColor,fontFamilyagent:name,avatarenableVoice: booleanlanguageOptions: e.g.['en','hi','es']context: string passed to the LLM each request
- Vite (library build; IIFE single-file)
- React + TypeScript
- Vercel AI SDK (
ai,@ai-sdk/google) with Gemini (gemini-1.5-flash) - Shadow DOM mounting to avoid host page CSS collisions
Approach and architecture notes: link-to-notion
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- @vitejs/plugin-react uses Babel (or oxc when used in rolldown-vite) for Fast Refresh
- @vitejs/plugin-react-swc uses SWC for Fast Refresh
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
export default defineConfig([
globalIgnores(["dist"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
// Other configs...
// Remove tseslint.configs.recommended and replace with this
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,
// Other configs...
],
languageOptions: {
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
]);You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:
// eslint.config.js
import reactX from "eslint-plugin-react-x";
import reactDom from "eslint-plugin-react-dom";
export default defineConfig([
globalIgnores(["dist"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs["recommended-typescript"],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
]);