@rodgerai/embed
v2.0.0
Published
Embeddable chat widget for Rodger.ai agents
Downloads
4
Readme
@rodger/embed
Embeddable chat widget for Rodger.ai agents. Drop a fully functional AI chat interface into any website with just a few lines of code.
Features
- Drop-in embeddable chat widget
- Customizable positioning (4 corner positions)
- Themeable (colors, fonts, sizes)
- Unread message notifications
- Session management
- Custom tool widgets
- TypeScript support
- Framework agnostic (works with any React app)
Installation
npm install @rodger/embed
# or
pnpm add @rodger/embed
# or
yarn add @rodger/embedQuick Start
Basic Usage
import { RodgerEmbed } from '@rodger/embed';
function App() {
return (
<div>
{/* Your app content */}
<RodgerEmbed
endpoint="/api/chat"
sessionId="user-123"
/>
</div>
);
}With Custom Theme
import { RodgerEmbed } from '@rodger/embed';
function App() {
return (
<RodgerEmbed
endpoint="/api/chat"
position="bottom-right"
theme={{
primaryColor: '#6366f1',
fontFamily: 'Inter, sans-serif',
borderRadius: '12px',
width: '450px',
height: '650px',
}}
welcomeMessage={
<div>
<h3>Welcome to Support Chat!</h3>
<p>How can we help you today?</p>
</div>
}
/>
);
}With Custom Widgets
import { RodgerEmbed } from '@rodger/embed';
function WeatherWidget({ data }) {
return (
<div className="rounded-lg border p-4">
<h4>{data.location}</h4>
<p className="text-2xl">{data.temperature}°</p>
<p>{data.conditions}</p>
</div>
);
}
function App() {
return (
<RodgerEmbed
endpoint="/api/chat"
widgets={{
weather: WeatherWidget,
}}
/>
);
}Advanced Usage with Custom Trigger
import { EmbedProvider, EmbedTrigger, EmbedDialog, useEmbed } from '@rodger/embed';
function CustomTrigger() {
const { toggle, state } = useEmbed();
return (
<button onClick={toggle} className="my-custom-button">
Chat with us {state.unreadCount > 0 && `(${state.unreadCount})`}
</button>
);
}
function App() {
return (
<EmbedProvider
config={{
endpoint: '/api/chat',
position: 'bottom-right',
}}
>
<div>
{/* Your app content */}
<CustomTrigger />
<EmbedDialog />
</div>
</EmbedProvider>
);
}Configuration
EmbedConfig
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| endpoint | string | required | API endpoint for chat (e.g., /api/chat) |
| sessionId | string | auto-generated | Session ID for this user. Auto-generated as session-{timestamp} if not provided |
| position | 'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' | 'bottom-right' | Position of the widget on the screen |
| theme | EmbedTheme | - | Theme configuration for customizing appearance |
| widgets | Record<string, ComponentType> | - | Custom widgets for rendering tool results |
| welcomeMessage | ReactNode | - | Welcome message shown when thread is empty |
| trigger | TriggerConfig | - | Trigger button customization |
| defaultOpen | boolean | false | Whether the chat dialog is open by default |
| notifications | boolean | true | Enable unread message count badge on trigger button |
| zIndex | number | 50 | Z-index for widget positioning |
EmbedTheme
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| primaryColor | string | - | Primary brand color (hex, rgb, or CSS color) |
| fontFamily | string | - | Font family for the chat interface |
| borderRadius | string | - | Border radius for the chat dialog |
| width | string | '400px' | Width of chat dialog |
| height | string | '600px' | Height of chat dialog |
| cssVariables | Record<string, string> | - | Custom CSS variables for advanced theming |
TriggerConfig
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| icon | ReactNode | <MessageCircle /> | Custom icon for the trigger button |
| label | string | 'Open chat' | Aria label for accessibility |
| className | string | - | Additional CSS classes for the trigger button |
API
Hooks
useEmbed()
Access the embed context to control the widget programmatically.
const { config, state, open, close, toggle, incrementUnread, resetUnread } = useEmbed();Returns:
config: Current embed configurationstate: Current embed state (isOpen, unreadCount, sessionId)open(): Open the chat dialogclose(): Close the chat dialogtoggle(): Toggle the chat dialogincrementUnread(): Increment unread countresetUnread(): Reset unread count to 0
Examples
E-commerce Site
<RodgerEmbed
endpoint="/api/support"
position="bottom-right"
theme={{
primaryColor: '#10b981',
width: '420px',
}}
welcomeMessage={
<div>
<h3>Need help?</h3>
<p>Ask us about products, orders, or shipping!</p>
</div>
}
widgets={{
product: ProductCard,
order: OrderStatus,
}}
/>SaaS Application
<RodgerEmbed
endpoint="/api/assistant"
sessionId={userId}
position="bottom-left"
theme={{
primaryColor: '#3b82f6',
height: '700px',
}}
trigger={{
label: 'Ask AI Assistant',
}}
defaultOpen={false}
/>Documentation Site
<RodgerEmbed
endpoint="/api/docs-chat"
position="top-right"
theme={{
width: '500px',
height: '80vh',
}}
welcomeMessage="Search our docs or ask a question"
widgets={{
docLink: DocLinkCard,
codeSnippet: CodeSnippet,
}}
/>Backend Integration
The embed widget requires a chat API endpoint that follows the Vercel AI SDK streaming protocol. Here's an example Next.js API route:
// app/api/chat/route.ts
import { createAgent } from '@rodger/core';
import { streamText } from 'ai';
const agent = createAgent({
name: 'support-agent',
llm: { provider: 'openai', model: 'gpt-4o' },
systemPrompt: 'You are a helpful customer support agent.',
});
export async function POST(req: Request) {
const { messages, sessionId } = await req.json();
const stream = await streamText({
model: agent.llm,
messages,
// Add your tools here
});
return stream.toDataStreamResponse();
}
// History endpoint (optional but recommended)
export async function POST(req: Request) {
const { sessionId } = await req.json();
// Load message history from your database
const messages = await loadMessageHistory(sessionId);
return Response.json({ messages });
}Session Management
The widget automatically manages sessions:
- If
sessionIdis provided, it uses that ID - If not provided, generates a unique session ID (
session-{timestamp}) - Session ID is passed to both the chat endpoint and history endpoint
- Use the session ID to persist conversations in your database
Message History
The widget attempts to load message history from {endpoint}/history on mount. Implement this endpoint to restore previous conversations:
// app/api/chat/history/route.ts
export async function POST(req: Request) {
const { sessionId } = await req.json();
// Load from your database
const messages = await db.messages.findMany({
where: { sessionId },
orderBy: { createdAt: 'asc' }
});
return Response.json({ messages });
}Migration from Thread Component
If you're currently using the standalone Thread component from @rodger/ui, migrating to the embed widget is straightforward:
Before (Thread)
import { Thread, RodgerProvider, useRodgerChat } from '@rodger/ui';
function ChatPage() {
const { runtime } = useRodgerChat({
endpoint: '/api/chat',
sessionId: 'session-123',
});
return (
<RodgerProvider runtime={runtime}>
<div className="h-screen">
<Thread widgets={myWidgets} />
</div>
</RodgerProvider>
);
}After (Embed)
import { RodgerEmbed } from '@rodger/embed';
function App() {
return (
<div>
{/* Your app content */}
<RodgerEmbed
endpoint="/api/chat"
sessionId="session-123"
widgets={myWidgets}
/>
</div>
);
}The embed widget handles all the setup (RodgerProvider, useRodgerChat, positioning) automatically.
TypeScript
Full TypeScript support with exported types:
import type { EmbedConfig, EmbedTheme, EmbedState } from '@rodger/embed';
const config: EmbedConfig = {
endpoint: '/api/chat',
position: 'bottom-right',
theme: {
primaryColor: '#3b82f6',
width: '450px',
},
};Browser Support
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- React 18+ or React 19+
Development
# Install dependencies
pnpm install
# Build the package
pnpm build
# Development mode with watch
pnpm dev
# Type check
pnpm type-checkTroubleshooting
Widget doesn't appear
- Make sure you've imported the component correctly
- Check that
endpointprop points to a valid API route - Verify Tailwind CSS is configured if using custom styles
Messages not loading
- Verify your chat API endpoint is returning a valid stream
- Check browser console for errors
- Ensure session ID is being passed correctly
Styling issues
- The widget uses Tailwind CSS internally - make sure it's configured
- Use
theme.cssVariablesfor advanced custom styling - Check z-index if widget is hidden behind other elements
License
MIT
