Every visual building block of the Botino chat + voice widget - anatomy, states, theming tokens, data shapes and the JS API. Built so an engineer (or coding agent) can wire a real backend & API to UI that already matches the brand. The same .cw* classes power the live preview in the app's Appearance tab.
The widget is two top-level pieces: a floating launcher bubble and the conversation window it opens. Both inherit your theme tokens and sit in a fixed corner of the host page.
| Part | Class | Role |
|---|---|---|
| Header | .cw__header | Avatar, bot name, live status, minimize/close. |
| Message list | .cw__body | Scrollable stream of bot/user bubbles & quick replies. |
| Bot bubble | .cw__msg--bot | Answer from the knowledge base, with avatar. |
| User bubble | .cw__msg--user | Visitor's message, accent colour, right-aligned. |
| Quick replies | .cw__chips | Tappable suggested actions / prompts. |
| Composer | .cw__foot | Text input, mic toggle and send button. |
| Attribution | .cw__powered | Optional "Powered by Botino" (hidden on Pro). |
| Launcher | .cw-launcher | Floating bubble with optional unread badge. |
The widget renders inside a Shadow DOM in production so host-page styles never leak in. Tokens are still exposed as inheritable CSS custom properties - see Theming.
Launcher, messages, voice, input, empty, loading and error states - the full surface a backend drives via the event API.
Every colour the merchant picks in the dashboard's Appearance tab maps to one CSS variable on the .cw root. Set them inline, in your stylesheet, or let the dashboard push them at runtime.
| Token | Default | Drives |
|---|---|---|
--cw-accent | #3B5BFC | Header, launcher, send button |
--cw-accent-2 | #6D4AF2 | Gradient partner |
--cw-user | #3B5BFC | User message bubble |
--cw-bot | #EEF2F7 | Bot message bubble |
--cw-text | #0B1220 | Bot bubble text colour |
.botino-widget {
--cw-accent: #3B5BFC;
--cw-accent-2: #6D4AF2;
--cw-user: #3B5BFC;
--cw-bot: #EEF2F7;
--cw-text: #0B1220;
}
Wire these JSON contracts to your API. The widget is presentation-only - it renders whatever the backend streams and emits events back.
{
"chatId": "tv-store-9f2a-4c1e",
"name": "TV Store Assistant",
"status": "Online · replies instantly",
"welcome": "Hi! How can I help?",
"position": "bottom-right",
"locale": "auto",
"voice": { "enabled": true, "voiceId": "zofia-pl" },
"theme": {
"accent": "#3B5BFC",
"accent2": "#6D4AF2",
"userBubble": "#3B5BFC",
"botBubble": "#EEF2F7"
},
"quickReplies": ["Track order", "Returns"]
}
{
"id": "msg_01HZ…",
"role": "assistant", // user | assistant | system
"type": "text", // text | voice | card
"content": "Your order #4821 ships tomorrow.",
"quickReplies": ["Track it", "Change date"],
"sources": [{ "title": "Shipping policy", "url": "/shipping" }],
"createdAt": "2026-06-04T08:12:30Z",
"tokens": 142
}
Suggested REST surface: POST /v1/chats/:chatId/messages to send, GET /v1/chats/:chatId/history to hydrate, and a WebSocket / SSE channel for streamed assistant tokens. The widget never holds API keys - it authenticates with a short-lived session token scoped to chatId.
After the script loads, a global Botino object is available. Drive the widget imperatively and subscribe to lifecycle events to sync your own analytics or CRM.
Subscribe with Botino.on(event, cb).
chat-id | Bot identifier (required) |
data-position | bottom-right | bottom-left |
data-locale | auto | en | pl |
data-open | auto | manual |
One script tag for static sites & CMSs; an npm wrapper for SPAs. Both read the same config from the dashboard.
<!-- before </body> -->
<script src="https://cdn.botino.eu/botino-voicebot.js"
chat-id="tv-store-9f2a-4c1e"
data-position="bottom-right"
data-locale="auto" defer></script>
// React / Next.js
import { Botino } from "@botino/widget";
useEffect(() => {
Botino.init({ chatId: "tv-store-9f2a-4c1e", locale: "auto" });
Botino.on("botino:handoff", openLiveChat);
return () => Botino.reset();
}, []);
botino:handoff to bridge into your human live-chat..cw__mic).setTheme().defer and self-mounts..cw* internals; use the documented tokens & API.