@grabba/chat-widget
v0.0.4
Published
A React component library for embedding Grabba knowledge base agents as customer support chat widgets on websites.
Readme
@grabba/chat-widget
A React component library for embedding Grabba knowledge base agents as customer support chat widgets on websites.
Installation
npm install @grabba/chat-widgetBasic Usage
import React from 'react';
import { ChatWidget } from '@grabba/chat-widget';
function App() {
return (
<div>
<ChatWidget
agentId="your-agent-id"
apiKey="your-api-key"
/>
</div>
);
}The widget talks to the Grabba production endpoints by default
(https://api.grabba.dev/v1 and wss://chatbot.grabba.dev/ws/v1).
Features
- Easy Integration: Simple React component that can be mounted anywhere
- Agent Branding: Automatically applies agent's logo, colors, fonts, and styling
- Authentication: Handles private agent authentication flow
- Real-time Chat: WebSocket-based streaming responses
- Conversation Persistence: Maintains conversation state during session
- Responsive Design: Works seamlessly on mobile and desktop
- Customizable: CSS variables and style props for customization
- TypeScript Support: Full TypeScript definitions included
Configuration
Required Props
agentId(string): The ID of the knowledge base agent to render.apiKey(string): A Grabba API key belonging to the user that owns the agent. Used to fetch agent configuration and verify ownership.
Optional Props
email(string): Pre-filled email for private agent authentication.accessToken(string): Pre-issued access token for an authenticated session.onAuthRequired(function): Custom authentication handler called when the agent is private and noaccessTokenhas been provided. Should resolve with an access token string.customStyles(CSSProperties): Additional CSS styles applied to the widget root.className(string): Additional CSS class names for the widget root.
Example with Custom Authentication
import React from 'react';
import { ChatWidget } from '@grabba/chat-widget';
function App() {
const handleAuth = async (email: string) => {
// Custom authentication logic
const token = await yourAuthService.getToken(email);
return token;
};
return (
<ChatWidget
agentId="your-agent-id"
apiKey="your-api-key"
onAuthRequired={handleAuth}
customStyles={{
bottom: '100px',
right: '100px',
}}
/>
);
}Authentication Flow
Public Agents
Public agents only require a valid API key — no end-user auth is needed:
<ChatWidget agentId="public-agent-id" apiKey="your-api-key" />Private Agents
Private agents require email-based authentication on top of the API key:
- The user enters their email address
- An authorization email is sent containing an access token
- The user enters the access token to authenticate
- The chat session begins
The widget handles this flow automatically, but you can customize it using
the onAuthRequired prop.
Advanced Usage
Using Hooks Directly
For more control, you can use the hooks directly:
import { useAgentConfig, useChatWidget } from '@grabba/chat-widget';
function CustomChatComponent({ agentId, apiKey }) {
const { config, loading } = useAgentConfig(agentId, apiKey);
const {
messages,
sendMessage,
isConnected,
} = useChatWidget({
agentId,
agentConfig: config,
});
// Custom implementation...
}Using Services
You can also use the services directly for custom implementations:
import {
WebSocketClient,
AuthService,
AgentConfigService,
ChatMessage,
ConnectionStatus,
} from '@grabba/chat-widget';
// Fetch agent config (requires API key)
const configService = new AgentConfigService();
const config = await configService.fetchAgentConfig('agent-id', 'your-api-key');
// Authenticate end user for a private agent
const authService = new AuthService();
await authService.requestAuthorization('agent-id', '[email protected]');
const token = await authService.authenticate('agent-id', '[email protected]', 'access-token');
// Connect WebSocket
const wsClient = new WebSocketClient('wss://chatbot.grabba.dev/ws/v1', 'agent-id', token);
// Listen for incoming messages
const unsubscribeMessage = wsClient.onMessage((message: ChatMessage) => {
if (message.role === 'assistant') {
// Handle AI response
} else if (message.role === 'tool') {
// Handle tool output
}
});
// Listen for connection status changes
const unsubscribeStatus = wsClient.onStatusChange((status: ConnectionStatus) => {
// status: 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error'
});
await wsClient.connect();
wsClient.sendInitializeChat(config, conversationId);
wsClient.sendMessage('Hello!', conversationId);WebSocket Message Schema
Incoming Messages (ChatMessage):
interface ChatMessage {
id?: string;
role: 'user' | 'assistant' | 'system' | 'tool';
content: string;
created_at?: string;
relevant_sources?: RelevantSource[];
conversation_id?: string;
message_type?: string;
tool_name?: string;
tool_output?: any;
}
interface RelevantSource {
source: string;
source_type: string;
source_id?: string;
favicon?: string;
}Message Types:
message_chunk: Streaming AI response chunks (content is appended incrementally)done: Signals the end of a message streamtool_output: Tool execution resultserror: Error messages from the server
Streaming Behavior:
The client buffers message_chunk events into a single message keyed by
id. Each update replaces the previous one for the same id, so handlers
receive the latest accumulated content.
Connection Status:
The client automatically attempts to reconnect on failure (up to 5 attempts
with exponential backoff). Statuses: disconnected, connecting,
connected, reconnecting, error.
Customization
CSS Variables
The widget uses CSS variables that can be overridden:
.grabba-chat-widget {
--grabba-primary-color: #your-color;
--grabba-text-color: #your-text-color;
--grabba-border-radius: 12px;
--grabba-font-family: 'Your Font', sans-serif;
}Style Props
You can also pass custom styles:
<ChatWidget
agentId="agent-id"
apiKey="your-api-key"
customStyles={{
bottom: '50px',
right: '50px',
width: '400px',
height: '700px',
}}
/>Types
Full TypeScript definitions are included:
import type {
ChatWidgetProps,
ChatMessage,
AgentConfig,
ConnectionStatus,
} from '@grabba/chat-widget';Bundler Requirements
The package imports its stylesheet from ./styles/chat-widget.css at the
top of the entry module. Your bundler must be able to resolve .css
imports from node_modules — this works out of the box with webpack
(via css-loader/style-loader), Vite, Next.js, Docusaurus and most
modern toolchains.
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
License
MIT
Support
For issues, questions, or contributions, please visit our GitHub repository.
