Chat Widget
The drop-in widget gives your users a complete AI chat experience with zero custom UI code.
Basic Usage
<div id="chat" style="height: 500px;"></div>
<script>
BundleLLM.init().renderChat('#chat')
</script>
The widget handles everything: sign-in, provider selection, streaming responses, and sign-out.
Options
ai.renderChat('#chat', {
placeholder: 'Ask about this product...',
context: 'This is a product page for Acme Widget. Price: $49.',
welcomeMessage: 'Connect your AI to ask questions about this product.',
theme: 'dark',
})
| Option | Type | Default | Description |
|---|---|---|---|
placeholder | string | "Ask something..." | Input field placeholder text |
context | string | . | System prompt sent with every message. Use this to provide page content, product data, or instructions. |
welcomeMessage | string | "Connect your AI to start chatting." | Message shown before the user signs in |
theme | "light" | "dark" | "light" | Widget color theme |
markdown | boolean | true | Render markdown in assistant responses. Set to false for plain text. |
Markdown Rendering
Assistant responses render markdown by default: code blocks, inline code, bold, italic, headers, lists, and links. Links are restricted to http: and https: protocols for security.
To disable markdown and display responses as plain text:
ai.renderChat('#chat', { markdown: false })
Styling
The widget uses inline styles and is fully self-contained. It fills the container element you provide. control the size via the container’s CSS:
<!-- Fixed height -->
<div id="chat" style="height: 500px;"></div>
<!-- Full viewport -->
<div id="chat" style="height: 100vh;"></div>
<!-- Responsive -->
<div id="chat" style="height: min(600px, 80vh);"></div>
Context
The context option is the most important configuration. It tells the AI what your page is about:
ai.renderChat('#chat', {
context: `
You are a helpful assistant for Acme Inc.
The user is viewing the pricing page.
Plans: Free ($0), Pro ($49/mo), Enterprise (custom).
Answer questions about our plans and features.
`,
})
The context is sent as a system prompt with every message. Keep it concise because it counts toward the user’s token usage.
Dynamic Context
If your page content changes (e.g., the user navigates to a different product or section), you can update the context without re-rendering the widget. Chat history is preserved.
const ai = BundleLLM.init()
ai.renderChat('#chat', { context: 'Initial page content...' })
// Later, when the page content changes:
ai.setContext('Updated page content...')
// Clear to revert to the original context:
ai.setContext(undefined)
Session Expiry
By default, a user’s provider connection persists across page reloads. To auto-expire stored credentials after a set duration, pass sessionTTL (in seconds) when initializing:
const ai = BundleLLM.init({ sessionTTL: 3600 }) // expire after 1 hour
ai.renderChat('#chat')
When the TTL is exceeded, the user will be prompted to reconnect on their next visit. Omit sessionTTL to keep the default behavior (credentials persist indefinitely).
Events
The widget emits events on the instance:
const ai = BundleLLM.init()
ai.renderChat('#chat')
ai.on('connected', ({ provider, model }) => {
console.log(`User connected: ${provider}`)
})
ai.on('disconnected', () => {
console.log('User signed out')
})
Sign Out
The widget includes a hamburger menu with a “Sign out” option. Users can also be signed out programmatically:
ai.disconnect()