Embeddable voice + text AI agent widget. Drop a single script tag into any website to add an intelligent chat assistant powered by Rapida.
Add the widget to any HTML page with two lines:
<script>window.chatbotConfig={assistant_id: "YOUR_ASSISTANT_ID",token: "YOUR_API_KEY",};</script><scriptsrc="https://cdn-01.rapida.ai/public/scripts/app.min.js"></script>That's it. A floating chat button appears in the bottom-right corner of your page.
Use the latest version:
<scriptsrc="https://cdn-01.rapida.ai/public/scripts/app.min.js"></script>Pin to a specific version:
<scriptsrc="https://cdn-01.rapida.ai/public/scripts/v1.2.0/app.min.js"></script>npm install @rapidaai/web-widgetThen import the built file from dist/app.min.js in your bundler or serve it statically.
Set window.chatbotConfigbefore loading the script:
<script>window.chatbotConfig={// Requiredassistant_id: "your-assistant-id",token: "your-api-key",// Optional - API endpoint (defaults to Rapida cloud)api_base: "https://assistant-01.in.rapida.ai",// Optional - user identityuser: {name: "Jane Doe",user_id: "user-123",meta: {plan: "pro"},},// Optional - identityname: "Support Bot",logo_url: "https://example.com/avatar.png",// Optional - layout sectionlayout: {mode: "floating",// "floating" | "docked-right" | "docked-left" | "inline"position: "bottom-right",// "bottom-right" | "bottom-left" | "top-right" | "top-left"corners: "square",showFrame: true,},// Optional - theme sectiontheme: {mode: "light",// "light" | "dark" | "system"injectTheme: "g10",// "white" | "g10" | "g90" | "g100"},// Optional - AI Chat sectionsaiEnabled: false,header: {title: "Support Bot",showAiLabel: false,minimizeButtonIconType: "side-panel-right",},launcher: {isOn: true,},history: {isOn: false,},messaging: {messageTimeoutSecs: 150,messageLoadingIndicatorTimeoutSecs: 1,},// Optional - misclanguage: "en",assistant_version: "latest",debug: false,};</script>The widget has two configuration layers:
- Rapida layer: connection, authentication, user identity, message bridge, and audio controls.
- UI layer: native IBM AI Chat configuration exposed directly on
window.chatbotConfig.
Rapida always owns messaging.customSendMessage because text messages must go through @rapidaai/react. Rapida also appends its audio controls through renderWriteableElements.afterInputElement; if you provide your own afterInputElement, it is preserved and Rapida audio is appended after it.
Use the sectioned config shape below. Do not use a carbon config key.
| Property | Type | Default | Description |
|---|---|---|---|
assistant_id | string | required | Rapida assistant/deployment ID. |
token | string | required | Public web plugin token used to authenticate the widget. |
| Property | Type | Default | Description |
|---|---|---|---|
api_base | string | https://assistant-01.in.rapida.ai | Rapida API base URL. Use this for local or environment-specific backends. |
assistant_version | string | latest | Assistant version to load when the backend supports versioned deployments. |
user.name | string | Guest | Display name for the current user. |
user.user_id | string | generated and stored locally | Stable user ID. Provide one if your host app already has an authenticated user ID. |
user.meta | Record<string, string> | { source: "web plugin" } | Extra metadata sent to Rapida with the user session. |
language | string | host page language or en | Locale/language passed to the UI. The widget also watches <html lang>. |
debug | boolean | false | Enables additional client logging. Also passed to the UI layer. |
name | string | deployment name | Friendly assistant name. Used as the default assistantName and header.title. |
logo_url | string | default assistant avatar | Assistant avatar URL. Used as the default assistantAvatarUrl. |
Use theme for all theme-level options.
| Property | Type | Default | Description |
|---|---|---|---|
theme.mode | "light" | "dark" | "system" | "light" | Widget color mode. dark defaults the UI token injection to g100; light defaults it to g10; system lets the host/system decide unless theme.injectTheme is set. |
theme.injectTheme | "white" | "g10" | "g90" | "g100" | derived from theme.mode | UI theme token injected into the chat shadow DOM. Set this when the host page does not already provide compatible theme tokens. |
theme.color | string | none | Legacy primary brand color. Prefer layout.customProperties for current UI customization. |
layout can be a string for old embeds or an object for the current sectioned config.
window.chatbotConfig={layout: {mode: "floating",position: "bottom-right",corners: "square",showFrame: true,customProperties: {width: "420px",height: "640px",},},};| Property | Type | Default | Description |
|---|---|---|---|
layout | string | object | "floating" | Widget layout. String values are still supported: "floating", "docked-right", "docked-left", "inline". |
layout.mode | "floating" | "docked-right" | "docked-left" | "inline" | "floating" | Rapida placement mode. |
layout.position | "bottom-right" | "bottom-left" | "top-right" | "top-left" | "bottom-right" | Floating launcher and panel position. |
layout.showLauncher | boolean | true for floating | Legacy launcher shortcut inside layout. Prefer launcher.isOn. |
layout.showFrame | boolean | true | Keeps the native border and shadow frame. |
layout.hasContentMaxWidth | boolean | UI default | Constrains message content to the UI max-width. |
layout.corners | "round" | "square" | object | "square" | Corner style. Use a string for all corners or an object for per-corner control. |
layout.customProperties | Record<string, string> | generated for floating | CSS variable overrides for the chat UI. Values are raw CSS strings. |
Per-corner layout.corners object:
| Property | Type | Description |
|---|---|---|
startStart | "round" | "square" | Top-left in LTR, top-right in RTL. |
startEnd | "round" | "square" | Top-right in LTR, top-left in RTL. |
endStart | "round" | "square" | Bottom-left in LTR, bottom-right in RTL. |
endEnd | "round" | "square" | Bottom-right in LTR, bottom-left in RTL. |
Supported layout.customProperties keys:
| Key | Description |
|---|---|
height | Floating chat height. |
max-height | Floating chat maximum height. |
width | Floating chat width. |
min-height | Floating chat minimum height. |
max-width | Floating chat maximum width. |
z-index | Floating chat z-index. |
bottom-position | Floating panel distance from viewport bottom. |
right-position | Floating panel distance from viewport right. |
top-position | Floating panel distance from viewport top. |
left-position | Floating panel distance from viewport left. |
launcher-default-size | Launcher button size. |
launcher-position-bottom | Launcher distance from viewport bottom. |
launcher-position-right | Launcher distance from viewport right. |
launcher-extended-width | Expanded launcher width. |
messages-max-width | Maximum width for message content. |
messages-min-width | Minimum width for message content. |
workspace-min-width | Minimum width for workspace panels. |
card-max-width | Maximum width for card responses. |
launcher-color-background | Launcher background color. |
launcher-color-avatar | Launcher icon/avatar color. |
launcher-color-background-hover | Launcher hover background. |
launcher-color-background-active | Launcher active background. |
launcher-color-focus-border | Launcher focus border color. |
launcher-mobile-color-text | Mobile launcher text color. |
launcher-expanded-message-color-text | Expanded launcher text color. |
launcher-expanded-message-color-background | Expanded launcher background. |
launcher-expanded-message-color-background-hover | Expanded launcher hover background. |
launcher-expanded-message-color-background-active | Expanded launcher active background. |
launcher-expanded-message-color-focus-border | Expanded launcher focus border color. |
unread-indicator-color-background | Unread indicator background color. |
unread-indicator-color-text | Unread indicator text color. |
| Property | Type | Default | Description |
|---|---|---|---|
header.isOn | boolean | true | Enables the native chat header. Set false for a fully embedded/fullscreen experience with your own app header. |
header.title | string | name or deployment name | Header title. Set "" to remove the visible title. |
header.name | string | UI default | Secondary name shown after the title. Set "" to remove it. |
header.minimizeButtonIconType | "close" | "minimize" | "side-panel-left" | "side-panel-right" | "side-panel-down" | side-panel icon based on dock side | Icon for the close/minimize button. |
header.hideMinimizeButton | boolean | false | Hides the close/minimize button. |
header.showRestartButton | boolean | false | Shows the restart conversation button. |
header.menuOptions | Array<{ text: string }> | none | Custom menu options in the header menu. |
header.showAiLabel | boolean | false | Shows the AI label in the header. Disabled by default. |
header.hideDefaultAiLabelContent | boolean | true | Hides the default AI label popover content. |
header.hasContentMaxWidth | boolean | false | Constrains the header to the message content width. |
header.actions | ToolbarAction[] | none | Custom header toolbar actions. |
| Property | Type | Default | Description |
|---|---|---|---|
launcher.isOn | boolean | true for floating, false for docked/inline | Shows the floating launcher button. |
launcher.showUnreadIndicator | boolean | UI default | Shows the unread dot on the launcher. |
launcher.mobile.avatarUrlOverride | string | none | Custom mobile launcher avatar/icon URL. |
launcher.mobile.isOn | boolean | false | Deprecated expanded call-to-action launcher state. |
launcher.mobile.title | string | translated default | Deprecated expanded launcher title. |
launcher.mobile.timeToExpand | number | 15 | Deprecated delay before launcher expansion, in seconds. |
launcher.desktop.avatarUrlOverride | string | none | Custom desktop launcher avatar/icon URL. |
launcher.desktop.isOn | boolean | false | Deprecated expanded call-to-action launcher state. |
launcher.desktop.title | string | translated default | Deprecated expanded launcher title. |
launcher.desktop.timeToExpand | number | 15 | Deprecated delay before launcher expansion, in seconds. |
| Property | Type | Default | Description |
|---|---|---|---|
history.isOn | boolean | false | Enables the native history panel. |
history.showMobileMenu | boolean | true | Shows mobile header menu options for new chat and view chats. |
history.startClosed | boolean | false | Starts history closed and preserves open/closed state across responsive mode changes. |
| Property | Type | Default | Description |
|---|---|---|---|
messaging.skipWelcome | boolean | UI default | Starts new conversations without requesting a welcome message. |
messaging.messageTimeoutSecs | number | 150 | Message timeout in seconds. Use 0 to disable automatic timeout. |
messaging.messageLoadingIndicatorTimeoutSecs | number | 1 | Delay before the UI shows a loading indicator. Use 0 to prevent the UI from showing one automatically. |
messaging.customSendMessage | function | Rapida bridge | Reserved. Rapida overwrites this so text is sent through @rapidaai/react. |
messaging.customLoadHistory | function | none | Optional function that returns native history items for the UI. |
messaging.showStopButtonImmediately | boolean | false | Shows the stop button as soon as a message request starts. |
| Property | Type | Default | Description |
|---|---|---|---|
input.maxInputCharacters | number | 10000 | Maximum characters allowed in the text input. |
input.isVisible | boolean | true | Shows or hides the main input surface. |
input.isDisabled | boolean | false | Disables text input. Rapida also disables text input while audio mode is active. |
| Property | Type | Default | Description |
|---|---|---|---|
homescreen.isOn | boolean | false | Enables the native home screen before chat. |
homescreen.greeting | string | none | Greeting text on the home screen. |
homescreen.starters.isOn | boolean | UI default | Shows starter buttons. |
homescreen.starters.buttons | Array<{ label: string; isSelected?: boolean }> | none | Starter utterances displayed as buttons. |
homescreen.customContentOnly | boolean | false | Hides the built-in greeting and starters so custom content can own the home screen. |
homescreen.disableReturn | boolean | false | Prevents returning to the home screen after a user has sent a message. |
File upload is experimental in the underlying UI.
| Property | Type | Default | Description |
|---|---|---|---|
upload.is_on | boolean | false | Enables the attachment button. Requires upload.onFileUpload. |
upload.accept | string | all file types | Accepted MIME types or extensions, same format as the HTML accept attribute. |
upload.maxFileSizeBytes | number | none | Client-side maximum file size. |
upload.maxFiles | number | none | Maximum number of pending files. |
upload.onFileUpload | function | none | Called once per selected file. Return structured data for the pending message. |
Keyboard shortcut configuration is experimental in the underlying UI.
| Property | Type | Default | Description |
|---|---|---|---|
keyboardShortcuts.messageFocusToggle.is_on | boolean | true | Enables the message/input focus toggle shortcut. |
keyboardShortcuts.messageFocusToggle.key | string | "F6" | Primary shortcut key. |
keyboardShortcuts.messageFocusToggle.modifiers.alt | boolean | false | Requires Alt. |
keyboardShortcuts.messageFocusToggle.modifiers.shift | boolean | false | Requires Shift. |
keyboardShortcuts.messageFocusToggle.modifiers.ctrl | boolean | false | Requires Control. |
keyboardShortcuts.messageFocusToggle.modifiers.meta | boolean | false | Requires Command/Meta. |
| Property | Type | Default | Description |
|---|---|---|---|
disclaimer.isOn | boolean | false | Shows a disclaimer screen before chat. |
disclaimer.disclaimerHTML | string | required when enabled | HTML content for the disclaimer. If this changes after acceptance, the user must accept again. |
These are advanced native UI options for human-agent handoff integrations.
| Property | Type | Default | Description |
|---|---|---|---|
serviceDeskFactory | function | none | Factory that creates a service desk integration instance. |
serviceDesk.availabilityTimeoutSeconds | number | UI default | Timeout used while checking whether human agents are available. |
serviceDesk.skipConnectHumanAgentCard | boolean | false | Auto-connects to an available agent after a connect-to-agent response while still showing the card. |
serviceDesk.agentJoinTimeoutSeconds | number | none | Timeout while waiting for an agent to join after one is requested. |
serviceDesk.allowReconnect | boolean | true | Attempts to reconnect the user to a prior human-agent conversation when supported. |
These are passed through to the native UI layer. Use them only when the host page needs lower-level control.
| Property | Type | Default | Description |
|---|---|---|---|
aiEnabled | boolean | false | Enables AI visual styling. The widget disables this by default. |
assistantName | string | name or deployment name | Assistant name used by the UI for accessibility, errors, and defaults. |
assistantAvatarUrl | string | logo_url | Assistant avatar URL used by native messages. |
locale | string | language | UI locale. Prefer language unless you need to override only the UI. |
namespace | string | "rapida-chat" | Namespace for DOM IDs, storage keys, and multi-instance isolation. Must be 30 characters or fewer. |
openChatByDefault | boolean | true for docked/inline, false for floating | Opens the chat when it first renders. |
shouldSanitizeHTML | boolean | true | Sanitizes assistant HTML before rendering. |
shouldTakeFocusIfOpensAutomatically | boolean | false | Moves focus into the chat when it opens on page load. |
disableCustomElementMobileEnhancements | boolean | false | Disables mobile enhancements that can conflict with custom element embedding. |
isReadonly | boolean | false | Puts the chat in read-only mode for viewing old conversations. |
persistFeedback | boolean | false | Keeps feedback controls visible beyond the latest message. |
strings | partial language pack | UI defaults | Overrides built-in UI strings. |
injectCarbonTheme | "white" | "g10" | "g90" | "g100" | derived from theme | Raw UI prop. Prefer theme.injectTheme. |
onError | function | none | Called for catastrophic UI errors. |
| Property | Type | Description |
|---|---|---|
onBeforeRender(instance) | function | Called before the UI renders. Rapida uses this internally, then calls your handler. |
onAfterRender(instance) | function | Called after the UI renders. |
onViewPreChange(event, instance) | function | Called before the chat opens or closes. Can return a promise to delay the view change. |
onViewChange(event, instance) | function | Called after the chat opens or closes. Rapida uses this to track docked/inline shell state, then calls your handler. |
renderUserDefinedResponse | function | Renders custom user_defined response items. |
renderCustomMessageFooter | function | Renders custom message footers. |
renderWriteableElements | object | Renders writable slots. Rapida merges afterInputElement with its audio controls. |
These remain supported for old embeds. Prefer the sectioned config above for new usage.
| Property | Replacement |
|---|---|
layout: "floating" | layout: { mode: "floating" } |
layout: "docked-right" | layout: { mode: "docked-right" } |
layout: "docked-left" | layout: { mode: "docked-left" } |
layout: "inline" | layout: { mode: "inline" } |
position | layout.position |
showLauncher | launcher.isOn |
A fixed-position panel with a launcher FAB. Click the button to open/close the chat.
window.chatbotConfig={layout: {mode: "floating",position: "bottom-right",// or "bottom-left", "top-right", "top-left"},launcher: {isOn: true,},};Panel fixed to the side of the viewport. Pushes page content to make room.
window.chatbotConfig={layout: {mode: "docked-right",// or "docked-left"},};Flows with the page content. Place the <div id="rapida-chat-app"> where you want it.
window.chatbotConfig={layout: {mode: "inline",},};- Text + Voice - type messages or speak with your assistant using WebRTC
- Markdown rendering - assistant responses render as rich Markdown
- Microphone device selector - choose input device during voice conversations
- Dark mode - automatic or manual light/dark theme switching
- Responsive - works on desktop and mobile browsers
- Single file - one
app.min.jsbundle, no external dependencies to load - Versioned CDN - pin to a specific version or always use the latest
- Node.js 20+
- npm
npm installnpm start # Dev mode with watch (serves at webpack-dev-server)
npm run build # Production build -> dist/app.min.js
npm test# Run tests
npm run test:watch # Run tests in watch mode
npm run test:coverage # Run tests with coverage reportsrc/
├── index.tsx # Entry point, mounts React app
├── app/
│ ├── index.tsx # App root, creates VoiceAgent
│ └── pages/
│ ├── web-plugin-chat/ # Deployment loader
│ └── v3/
│ ├── index.tsx # Chat UI (messages, header, launcher)
│ └── input.tsx # Text/voice input + device selector
├── contexts/
│ ├── environment-context.tsx # Config from window.chatbotConfig
│ └── dark-mode-context.tsx # Theme management
├── hooks/
│ └── use-environment.ts # Environment context hook
├── configs/
│ └── index.ts # API base URL + constants
├── styles/
│ └── carbon.scss # Theme/component styles and widget style overrides
├── types/
│ ├── globals.d.ts # ChatbotConfig type definition
│ └── types.rapida.ts # Shared types
└── utils/
└── time.ts # Time formatting helpers
On push to main:
- Build -
npm ci && npm run build - CDN - uploads
dist/app.min.jsto S3 with CloudFront invalidation - npm - publishes to npm as
@rapidaai/web-widget - Release - creates a GitHub release with a version tag
Pull requests run the CI pipeline (build + test) without deploying.