@bubblio/widget
v0.4.0
Published
Embeddable real-time AI customer-service character widget — drop into any React app in 5 lines of code.
Maintainers
Readme
@bubblio/widget
Embeddable real-time AI character widget for React apps. Floating bubble that opens into a live video character — connects directly to Runway, talks to your backend via @bubblio/server.
npm install @bubblio/widget @runwayml/avatars-react react react-domPeer dependencies:
react >= 18,react-dom >= 18,@runwayml/avatars-react >= 0.14.
Quickstart
import { BubblioWidget } from '@bubblio/widget'
export default function App() {
return (
<BubblioWidget
config={{
name: 'Aria',
character: '/aria.png',
serverUrl: '/api/bubblio/session',
}}
/>
)
}serverUrl is your own backend route that returns { sessionId, sessionKey }. Pair it with @bubblio/server:
// app/api/bubblio/session/route.ts
import { createBubblioSession } from '@bubblio/server'
export async function POST() {
const session = await createBubblioSession({
bubblioApiKey: process.env.BUBBLIO_API_KEY!,
characterId: process.env.BUBBLIO_CHARACTER_ID!,
})
return Response.json(session)
}That's it. The widget renders a floating bubble; clicking it opens the live character panel and starts a WebRTC connection. Closing the panel ends the session.
No React? One script tag.
Plain HTML, Webflow, Wix — drop this anywhere (Webflow/Wix users: paste it into a custom-code block):
<script defer
src="https://cdn.jsdelivr.net/npm/@bubblio/[email protected]/dist/embed.global.js"
data-server-url="https://yoursite.com/api/bubblio/session"></script>The bubble auto-mounts on DOM ready. Configure it with data-* attributes:
| Attribute | Maps to |
| --- | --- |
| data-server-url | serverUrl (required for auto-mount) |
| data-name | name |
| data-character | character |
| data-primary-color | theme.primaryColor |
| data-accent-color | theme.accentColor |
| data-dot-color | theme.dotColor |
Prefer to configure from JavaScript? Set window.bubblioConfig before the embed script tag (inline scripts run before defer scripts, so this ordering is always safe — including in Webflow/Wix custom-code blocks) and omit data-server-url:
<script>
window.bubblioConfig = { serverUrl: 'https://yoursite.com/api/bubblio/session' }
</script>
<script defer src="https://cdn.jsdelivr.net/npm/@bubblio/[email protected]/dist/embed.global.js"></script>For full runtime control there's also a global API — note it only exists once the embed script has loaded (call it from the script tag's load event or a later user interaction, never from an inline script above it):
window.Bubblio.init({ serverUrl: 'https://yoursite.com/api/bubblio/session' })
// later:
Bubblio.destroy()The embed is a single self-contained file (~290 KB gzipped) that loads deferred. React is not required on the page — and if the page already has React, nothing clashes: everything is bundled and scoped inside the script.
Persistence across navigation
Mount <BubblioWidget /> once in your root layout so the session survives page transitions. Mounting inside a page component will tear down and restart the session every time the user navigates.
// app/layout.tsx (Next.js App Router)
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
{children}
<BubblioWidget config={{ name: 'Aria', character: '/aria.png', serverUrl: '/api/bubblio/session' }} />
</body>
</html>
)
}Theming
<BubblioWidget
config={{
name: 'Aria',
character: '/aria.png',
serverUrl: '/api/bubblio/session',
theme: {
primaryColor: '#0066ff',
dotColor: '#0066ff',
},
}}
/>| Field | What it styles |
| --- | --- |
| primaryColor | Retry button, default bubble color |
| dotColor | Floating trigger bubble color (defaults to primaryColor) |
| accentColor | Reserved for future use |
Client events
The character can fire two built-in client events to drive your UI:
set_animation_state — Switch a visual state in the widget. The character should call this just before any tool call, then idle once the result is back. States: idle, searching, creating, found, analyzing, linking, closing.
show_link_card — Render a clickable link card inside the panel. Useful for directing the user to a specific page.
{ name: 'show_link_card', args: { title: 'Your dashboard', url: '/dashboard' } }Both events are registered automatically by the platform — you just need to mention them in the character's personality prompt so it knows when to use them.
API
<BubblioWidget config={config} />
interface BubblioConfig {
name: string // shown in panel header
character: string // portrait image URL or path
serverUrl: string // your backend endpoint that returns { sessionId, sessionKey }
theme?: {
primaryColor?: string
accentColor?: string
dotColor?: string
}
}
type AnimationState =
| 'idle' | 'searching' | 'creating' | 'found'
| 'analyzing' | 'linking' | 'closing'
interface LinkCard {
title: string
url: string
description: string
}License
MIT. See LICENSE.
