Bot widget
The Exolvra chat widget is a single JavaScript file served from your deployment. It renders a floating chat bubble on your website that talks to a specific bot via the public API. Zero dependencies, Shadow DOM isolated, ~9 KB.
Quick start
- Create a bot in the dashboard at
/bots/new. Give it a name, description, system prompt, and optionally a knowledge collection. - Generate an API key. Open the bot in edit mode, go to section “05 — API Keys”, click Generate new key. Copy the plaintext
exo_...key — it is shown exactly once. - Paste the snippet onto any page of your website:
<script
src="https://your-exolvra.example/widget/chat-widget.js"
data-api-key="exo_a1b2c3d4e5f6..."
data-theme="light"
data-position="bottom-right"></script>
That’s it. A chat bubble appears in the corner. Clicking it opens a panel that loads the bot’s name, icon, and conversation starters from /api/v1/bots/me and sends messages through /api/v1/chat/completions.
CORS setup
If your site is on a different domain from the Exolvra deployment, add your site’s origin to the key’s Allowed Origins list in the dashboard. The widget will include the browser’s Origin header on every request; the Exolvra API rejects keys whose origin is not on the allowlist.
If you’re embedding the widget on the same Exolvra host that serves the script (the typical “first run” setup), CORS is not required — the browser won’t send an Origin header on same-origin requests.
Script attributes
| Attribute | Required | Default | Description |
|---|---|---|---|
data-api-key | yes | — | Plaintext bot API key from the dashboard (exo_...) |
data-theme | no | light | light or dark |
data-position | no | bottom-right | bottom-right or bottom-left |
data-origin | no | script src origin | Override the API base URL if you host the script on a CDN separate from the Exolvra deployment |
What the widget shows
- Floating bubble — icon in the configured corner
- Chat panel — 380×580 by default, responsive on mobile
- Header — bot icon and name (fetched from
/api/v1/bots/me) - Conversation starters — clickable chips (first four from the bot’s configured starters) shown on a fresh session
- Message stream — user and assistant bubbles, markdown-style text, scrollable
- Input box and Send button — submits via the OpenAI-compatible endpoint
Session persistence
The widget stores a per-bot session id in localStorage under the key exolvra-widget-session:<botId>. This is passed as the user field on every chat completion request, which the Exolvra backend uses to thread multi-turn conversations into the same session. Clearing browser storage (or opening an incognito window) starts a fresh conversation.
React / Vue / Next.js integration
The widget is a vanilla <script> tag — any framework can host it. The simplest pattern is a top-level layout component that appends the script on mount.
React
import { useEffect } from "react";
export function ExolvraWidget({ apiKey }: { apiKey: string }) {
useEffect(() => {
const script = document.createElement("script");
script.src = "https://your-exolvra.example/widget/chat-widget.js";
script.setAttribute("data-api-key", apiKey);
script.setAttribute("data-theme", "light");
script.setAttribute("data-position", "bottom-right");
document.body.appendChild(script);
return () => {
script.remove();
const host = document.getElementById("exolvra-chat-widget");
if (host) host.remove();
};
}, [apiKey]);
return null;
}
Next.js (App Router)
// app/layout.tsx
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Script
src="https://your-exolvra.example/widget/chat-widget.js"
data-api-key={process.env.NEXT_PUBLIC_EXOLVRA_KEY}
data-theme="light"
strategy="lazyOnload"
/>
</body>
</html>
);
}
Theming
The widget ships with two themes (light and dark) selected via data-theme. For deeper brand customisation, fork chat-widget.js on your own deployment — it’s a single file with an inline <style> block you can edit to change colours, border radii, or fonts.
Security model
The widget is the external, public-facing entry point to a bot. The underlying API key has hard restrictions that cannot be lifted from the browser:
- Cloud mode is always enforced — network and memory tools only, no filesystem, shell, or browser access
- CLI providers are blocked — bot API sessions cannot be routed through external CLI tools
- Specialists are unreachable — API keys can only bind to bots, not your internal specialist workforce
- Key-level CORS — stolen keys still fail if used from an unauthorised origin
- Per-key revocation — instantly kill a leaked key from the dashboard
Demo page
A minimal example page ships at /widget/demo.html on your deployment. Open it in your browser, edit the file to set a real key, and refresh to try the widget end-to-end.
Troubleshooting
“Could not reach the bot” banner. The key is wrong, revoked, or expired — check the dashboard API keys tab. Or the bound bot was deleted — re-create the key against a live bot. Or CORS rejected the origin — add your site to the key’s allowed origins list.
Widget renders but messages fail. Same causes as above, plus: the backend could be routing through a model the bot doesn’t have credentials for. Check the bot’s configured model in the dashboard.
Bubble doesn’t appear at all. The <script> tag is missing data-api-key — check the browser console for the warning. Or the page has a CSP that blocks script-src from the Exolvra origin — add it to your CSP.