Package Exports
- @voxket-ai/voxket-live
- @voxket-ai/voxket-live/style.css
Readme
๐ฏ Voxket Web SDK (@voxket-ai/voxket-live)
The Complete AI Agent Integration Solution - Seamlessly embed voice, video, and chat experiences powered by Voxket AI agents into any web application.
๐ Key Features
๐ฅ Multi-Modal AI Interactions
- ๐ค Voice Conversations - Real-time voice chat with AI agents
- ๐ฌ Text Chat - Instant messaging with typing indicators and message history
- ๐น Video Calls - Face-to-face conversations with video support
- ๐บ Screen Sharing - Share your screen with AI agents for enhanced support
๐จ Flexible Display Options
- ๐ช Widget Mode - Embedded widget for seamless integration
- ๐ Popup Mode - Floating chat bubble with customizable positioning
- ๐ฅ๏ธ Fullscreen Mode - Immersive full-screen experience
- ๐ฑ Responsive Design - Works perfectly on desktop and mobile
๐ญ Rich Theming System
- ๐ Dark Theme - Modern dark interface
- โ๏ธ Light Theme - Clean light interface
- ๐ Vox Theme - Custom branded Voxket theme
- ๐จ Custom Themes - Create your own themes with full CSS control
โก Powerful Integration Options
๐ง 1. Simple Widget Integration (React)
Perfect for React applications with minimal setup.
๐ 2. Client SDK Integration (Any Framework)
Use the powerful VoxketClient for programmatic control with vanilla JavaScript, Vue, Angular, or any framework.
๐ 3. Advanced React Integration
Full React ecosystem with providers, hooks, and compound components.
๐ ๏ธ Advanced Features
๐ช Interactive Components (RPC System)
- ๐ฏ Agent-Triggered UI - Agents can display custom React components
- ๐ Forms & Surveys - Collect user input through interactive forms
- ๐ Data Visualization - Show charts, tables, and rich content
- ๐ฎ Custom Interactions - Build any interactive experience
๐ Session Analytics & Logging
- ๐ Real-time Metrics - Monitor session quality and performance
- ๐ Event Logging - Track all user interactions and system events
- ๐พ Data Export - Export session data for analysis
- โฑ๏ธ Session Timers - Track session duration and activity
๐ Event System
- ๐ก Connection Events - Track connection status and quality
- ๐ฅ Participant Events - Monitor who joins and leaves
- ๐ต Media Events - Handle track publishing/unpublishing
- ๐ฌ Message Events - Real-time message and transcription events
- ๐ค Agent Events - Monitor agent state (thinking, speaking, idle)
๐๏ธ Media Controls
- ๐ค Microphone Control - Mute/unmute with visual feedback
- ๐ท Camera Control - Enable/disable video with device selection
- ๐บ Screen Share - Start/stop screen sharing
- ๐ง Audio Devices - Select input/output devices
- ๐น Video Devices - Choose camera sources
๐ผ Business-Ready Features
- ๐ Enterprise Security - HIPAA-compliant options available
- ๐ Multi-Language Support - Internationalization ready
- ๐ฑ Cross-Platform - Works on all modern browsers and devices
- โก High Performance - Built on LiveKit for optimal real-time performance
- ๐ก๏ธ Error Handling - Robust error recovery and user feedback
- ๐ Auto-Reconnection - Automatic connection recovery
๐ Quick Start
๐ฆ Installation
npm install @voxket-ai/voxket-liveor
yarn add @voxket-ai/voxket-liveThat's it! All dependencies including LiveKit are bundled automatically. React and React DOM are peer dependencies (your project should already have them).
๐จ IMPORTANT: Import the CSS Styles
The SDK includes pre-compiled CSS with all necessary styles. You MUST import the CSS file for the widget to display correctly:
// In your main App.tsx or entry file
import '@voxket-ai/voxket-live/style.css';Or in vanilla JavaScript/HTML:
<link rel="stylesheet" href="node_modules/@voxket-ai/voxket-live/dist/index.css">Note: The SDK does NOT require Tailwind CSS in your project - all styles are pre-compiled and bundled. The CSS import includes everything needed.
๐จ Popup Icon Customization
The popup trigger button comes with a default Voxket logo. You can customize it in two ways:
Option 1: Use a Custom Logo URL
Pass your own logo URL to the popupTriggerLogoUrl prop:
<VoxketWidget
// ... other props
popupTriggerLogoUrl="https://example.com/my-custom-logo.png"
/>Option 2: Default Voxket Logo
If you don't pass popupTriggerLogoUrl, the SDK automatically uses the bundled Voxket logo - no additional setup required!
๏ฟฝ๐ฏ Option 1: Simple Widget (React)
Perfect for React apps - drop in the widget component:
import React from 'react';
import VoxketWidget from '@voxket-ai/voxket-live';
function App() {
return (
<div>
<h1>My App</h1>
<VoxketWidget
agentId="your-agent-id"
baseUrl="https://your.voxket.api"
appId="your-app-id"
appSecret="your-app-secret"
participantName="User"
modalities={['voice', 'chat']} // Choose: voice, chat, video, screen_share
theme="vox" // Options: dark, light, vox
displayType="widget" // Options: widget, popup, fullscreen
width="400px"
height="600px"
/>
</div>
);
}๐ง Option 2: Client SDK (Any Framework)
Use with vanilla JavaScript, Vue, Angular, or any framework:
import { VoxketClient } from '@voxket-ai/voxket-live';
// Create client
const client = new VoxketClient({
appId: "your-app-id",
appSecret: "your-app-secret",
baseUrl: "https://your.voxket.api",
agentId: "your-agent-id",
participantName: "User"
});
// Connect and render UI
await client.connect();
client.renderUI({
target: '#voxket-container', // CSS selector or HTMLElement
modality: ['voice', 'chat'],
theme: 'dark',
displayType: 'widget',
autoStart: true
});๐๏ธ Option 3: Advanced React Integration
Full React ecosystem with providers and hooks:
import { VoxketProvider, useVoxket } from '@voxket-ai/voxket-live';
function App() {
return (
<VoxketProvider config={{
appId: "your-app-id",
appSecret: "your-app-secret",
baseUrl: "https://your.voxket.api"
}}>
<MyComponent />
</VoxketProvider>
);
}
function MyComponent() {
const { client, connect, session } = useVoxket();
const handleStartChat = async () => {
await connect();
const session = await client.startSession("agent-id", {
modalities: ['chat'],
participantName: "User"
});
};
return (
<div>
<button onClick={handleStartChat}>Start Chat</button>
{session && <p>Session active: {session.id}</p>}
</div>
);
}๐๏ธ Display Types
๐ช Widget Mode
Embedded widget that fits naturally into your application:
<VoxketWidget
displayType="widget"
width="400px"
height="600px"
// ... other props
/>๐ Popup Mode
Floating chat bubble that can be positioned anywhere:
<VoxketWidget
displayType="popup"
popupPosition="bottom-right" // top-left, top-right, bottom-left, bottom-right
popupTriggerText="Need Help?"
onPopupToggle={(isOpen) => console.log('Popup:', isOpen)}
// ... other props
/>๐ฅ๏ธ Fullscreen Mode
Immersive full-screen experience:
<VoxketWidget
displayType="fullscreen"
onDisplayTypeChange={(type) => console.log('Display changed to:', type)}
// ... other props
/>๐จ Themes & Customization
๐ญ Built-in Themes
// Dark theme
<VoxketWidget theme="dark" />
// Light theme
<VoxketWidget theme="light" />
// Voxket branded theme
<VoxketWidget theme="vox" />๐จ Custom Styling
<VoxketWidget
className="my-custom-widget"
width="500px"
height="700px"
// Custom CSS classes and dimensions
/>๐ฌ Session Events & Analytics
๐ Basic Session Tracking
<VoxketWidget
onSessionStart={(sessionId) => {
console.log('Session started:', sessionId);
analytics.track('voxket_session_started', { sessionId });
}}
onSessionEnd={(metrics) => {
console.log('Session ended:', metrics);
analytics.track('voxket_session_ended', {
duration: metrics.duration,
messageCount: metrics.messageCount
});
}}
enableSessionLogging={true}
/>๐ Advanced Session Monitoring
import { SessionLog, SessionMetrics } from '@voxket-ai/voxket-live';
function MyApp() {
const [logs, setLogs] = useState<SessionLog[]>([]);
const [metrics, setMetrics] = useState<SessionMetrics | null>(null);
return (
<VoxketWidget
onSessionLogsUpdate={(logs) => {
setLogs(logs);
// Send to your analytics service
analytics.track('session_events', { eventCount: logs.length });
}}
onSessionMetricsUpdate={(metrics) => {
setMetrics(metrics);
// Update your dashboard
updateDashboard(metrics);
}}
// ... other props
/>
);
}๐ช Interactive Components (RPC System)
๐ Agent-Triggered UI Components
Agents can trigger custom React components during conversations:
import { VoxketClient } from '@voxket-ai/voxket-live';
const client = new VoxketClient(config);
// Register a custom form component
await client.registerFrontendRPC(
'customer_survey', // Method name the agent calls
SurveyComponent, // Your React component
'modal' // Presentation mode: embedded, modal, fullscreen
);
// Your custom component
function SurveyComponent({ handler, data }) {
const [rating, setRating] = useState(0);
const handleSubmit = () => {
handler.didSuccess({
survey_response: rating,
feedback: "Great service!"
});
};
return (
<div>
<h3>Rate your experience</h3>
<StarRating value={rating} onChange={setRating} />
<button onClick={handleSubmit}>Submit</button>
<button onClick={handler.dismissView}>Skip</button>
</div>
);
}๐ฏ Interactive UI Examples
- ๐ Forms & Surveys - Collect user feedback
- ๐ Data Visualization - Show charts and graphs
- ๐ Product Catalogs - Display interactive product lists
- ๐ Appointment Scheduling - Calendar integrations
- ๐ณ Payment Flows - Secure payment processing
- ๐ฎ Custom Games - Interactive experiences
๐ก Event System
๐ Connection Events
client.on('connection.connected', () => {
console.log('โ
Connected to Voxket');
});
client.on('connection.disconnected', (reason) => {
console.log('โ Disconnected:', reason);
});
client.on('connection.error', (error) => {
console.error('๐จ Connection error:', error);
});๐ Custom Event System
๐ก Register Event Emitters
Register custom event emitters to listen for LiveKit text stream topics:
import { VoxketClient } from '@voxket-ai/voxket-live';
const client = new VoxketClient(config);
// Register an event emitter for custom events
client.registerEventEmitter('custom_event_topic', (data) => {
console.log('Custom event received:', data);
// Handle your custom business logic
handleCustomEvent(data);
});
// Register multiple event emitters
client.registerEventEmitter('user_action', (actionData) => {
console.log('User action:', actionData);
analytics.track('user_action', actionData);
});
client.registerEventEmitter('system_notification', (notification) => {
showNotification(notification);
});๐ฏ Event Listener Registration
Register event listeners for any SDK events with automatic cleanup:
// Register event listeners with automatic unsubscribe
const unsubscribe = client.registerEventListener('chat.message.received', (message) => {
console.log('New message:', message);
updateUI(message);
});
// Manual cleanup when needed
unsubscribe();
// Register multiple listeners
client.registerEventListener('connection.connected', () => {
console.log('Connected to Voxket!');
updateConnectionStatus('connected');
});
client.registerEventListener('agent.thinking', () => {
showTypingIndicator();
});๐ข Business Integration Examples
Real-time Notifications
// Listen for agent-triggered notifications
client.registerEventEmitter('agent_notification', (data) => {
// Show toast notification
showToast({
title: data.title,
message: data.message,
type: data.type
});
});
// Listen for system updates
client.registerEventEmitter('system_update', (updateInfo) => {
if (updateInfo.type === 'maintenance') {
showMaintenanceWarning(updateInfo.schedule);
}
});Custom Analytics Integration
// Track custom business events
client.registerEventEmitter('business_event', (eventData) => {
// Send to your analytics platform
analytics.track(eventData.event_name, {
...eventData.properties,
timestamp: new Date().toISOString(),
session_id: client.getCurrentSession()?.id
});
});
// Example: Track user interactions
client.registerEventEmitter('user_interaction', (interaction) => {
mixpanel.track('Voxket User Interaction', {
interaction_type: interaction.type,
interaction_data: interaction.data,
user_id: getCurrentUserId()
});
});Workflow Automation
// Trigger business workflows
client.registerEventEmitter('workflow_trigger', (workflowData) => {
switch (workflowData.workflow_type) {
case 'lead_qualification':
triggerLeadQualificationWorkflow(workflowData.lead_data);
break;
case 'support_escalation':
escalateToHumanAgent(workflowData.ticket_data);
break;
case 'appointment_booking':
processAppointmentRequest(workflowData.appointment_data);
break;
}
});๐ฌ Chat & Messaging Events
client.on('chat.message.received', (message) => {
console.log('๐ฌ New message:', message);
displayMessage(message);
});
client.on('chat.message.sent', (message) => {
console.log('๐ค Message sent:', message);
logOutgoingMessage(message);
});
client.on('transcription.received', (transcription) => {
console.log('๐ค Voice transcription:', transcription);
displayTranscription(transcription);
});๐ Rich Content & Markdown Support
The Voxket SDK automatically detects and renders rich content in chat messages, including GitHub Flavored Markdown (GFM) with full support for tables, links, code blocks, and more.
โจ Supported Markdown Features
๐ Tables with Embedded Links
Agent messages can include formatted tables with clickable links embedded within table cells:
| CRA Partner | Registration Link | Description |
|-------------|-------------------|-------------|
| **CAMS** | [Click here to register](https://app.camsnps.in/register) | Computer Age Management Services |
| **KFintech** | [Register now](https://kfintech.com/register) | Widely used platform |Renders as:
| CRA Partner | Registration Link | Description |
|---|---|---|
| CAMS | Click here to register | Computer Age Management Services |
| KFintech | Register now | Widely used platform |
๐ Links
Check out [Voxket AI](https://voxket.ai) for more information!
Visit https://voxket.ai (auto-linked)Features:
- โ
Embedded links in text:
[text](url) - โ Auto-detection of bare URLs
- โ External link icon indicator
- โ
Opens in new tab with
target="_blank" - โ
Proper security with
rel="noopener noreferrer"
๐ Lists
**Unordered Lists:**
- Item one
- Item two
- Nested item
- Another nested item
**Ordered Lists:**
1. First step
2. Second step
3. Third step๐ป Code Blocks
Inline code: `const greeting = "Hello"`
```javascript
// Syntax-highlighted code block
function greet(name) {
return `Hello, ${name}!`;
}
```Features:
- โ Syntax highlighting for 180+ languages
- โ Inline code with backticks
- โ Multi-line code blocks with language specification
- โ Theme-aware styling (dark/light modes)
๐ Headings & Formatting
# Heading 1
## Heading 2
### Heading 3
**Bold text**
*Italic text*
~~Strikethrough~~
> Blockquote for important information๐ผ๏ธ Images
Features:
- โ Automatic lazy loading
- โ Responsive sizing
- โ Rounded corners with shadow
๐จ Theming for Rich Content
All markdown elements automatically adapt to your chosen theme:
<VoxketWidget
theme="dark" // Markdown content uses dark theme styling
// ... other props
/>Theme Support:
- ๐ Dark Mode: Light text on dark backgrounds, blue links
- โ๏ธ Light Mode: Dark text on light backgrounds, darker blue links
- ๐ Custom Themes: Markdown inherits your custom theme colors
๐ค Agent-Side Markdown
For AI agents to send markdown content, simply return markdown-formatted text in the agent's response:
Example Agent Response:
{
"type": "text",
"content": "Here's the information you requested:\n\n| Feature | Status |\n|---------|--------|\n| Voice | โ
Available |\n| Chat | โ
Available |\n\nFor more details, visit [our docs](https://docs.voxket.ai)."
}The SDK will automatically detect markdown patterns and render them appropriately!
๐ Automatic Detection
The SDK intelligently detects markdown content using multiple strategies:
- โ
Explicit metadata:
{ metadata: { format: 'markdown' } } - โ Pattern matching: Headers, lists, tables, code blocks, links
- โ Structure analysis: README-like content, multiple sections
- โ Fallback: Plain text with auto-linked URLs
No configuration needed - it just works!
๐ค Agent State Events
client.on('agent.thinking', () => {
showTypingIndicator();
});
client.on('agent.speaking', () => {
showSpeakingIndicator();
});
client.on('agent.connected', () => {
console.log('๐ค Agent joined the conversation');
});๐ต Media Events
client.on('track.muted', ({ source, enabled }) => {
console.log(`๐ ${source} muted:`, !enabled);
});
client.on('track.unmuted', ({ source, enabled }) => {
console.log(`๐ ${source} unmuted:`, enabled);
});๐๏ธ Media Controls
๐ค Microphone Control
// Toggle microphone
await client.toggleMicrophone();
// Explicit control
await client.setMicrophoneEnabled(true); // Unmute
await client.setMicrophoneEnabled(false); // Mute
// Check current state
const isMuted = !client.isMicrophoneEnabled;๐ท Camera Control
// Toggle camera
await client.toggleCamera();
// Explicit control
await client.enableCamera();
await client.disableCamera();
// Check current state
const isCameraOn = client.isCameraEnabled;๐บ Screen Sharing
// Start screen share
await client.startScreenShare();
// Stop screen share
await client.stopScreenShare();
// Check if screen sharing is active
const isSharing = client.isScreenShareEnabled;๐ง Device Management
// Get available devices
const audioDevices = await client.getAudioInputDevices();
const videoDevices = await client.getVideoInputDevices();
// Switch devices
await client.setAudioInputDevice(deviceId);
await client.setVideoInputDevice(deviceId);๐ผ Business Integration Examples
๐ E-commerce Customer Support
const supportClient = new VoxketClient({
appId: "ecommerce-app",
appSecret: "your-secret",
baseUrl: "https://api.voxket.com",
agentId: "customer-support",
onMessageReceived: (message) => {
// Log customer interactions
analytics.track('customer_support_message', {
content: message.content,
timestamp: message.timestamp
});
}
});
// Add to product pages
document.getElementById('help-button').onclick = async () => {
await supportClient.connect();
supportClient.renderUI({
target: '#support-widget',
modality: ['chat'],
theme: 'light',
displayType: 'popup',
popupPosition: 'bottom-right'
});
};๐ฅ Healthcare Patient Portal
const healthcareClient = new VoxketClient({
appId: "healthcare-portal",
appSecret: "hipaa-compliant-secret",
baseUrl: "https://secure.voxket.com",
agentId: "patient-support",
participantName: getCurrentPatient().name,
onSessionStart: (sessionId) => {
// HIPAA-compliant logging
auditLogger.log({
event: 'patient_session_started',
sessionId,
patientId: getCurrentPatient().id,
timestamp: new Date()
});
}
});
// Secure patient communications
await healthcareClient.connect();
healthcareClient.renderUI({
target: '#patient-support',
modality: ['chat'], // Text-only for security
theme: 'light'
});๐ฐ Financial Services
const financeClient = new VoxketClient({
appId: "banking-app",
appSecret: "secure-secret",
baseUrl: "https://secure-api.voxket.com",
agentId: "financial-advisor",
onSessionStart: (sessionId) => {
// Compliance logging
complianceLogger.record({
type: 'customer_interaction_start',
sessionId,
customerId: getCurrentCustomer().id
});
}
});
// Financial consultation widget
await financeClient.connect();
financeClient.renderUI({
target: '#advisor-chat',
modality: ['voice', 'video'],
theme: 'dark',
displayType: 'fullscreen'
});๐ ๏ธ Advanced Usage
๐ Session Management
// Start a session with specific configuration
const session = await client.startSession("agent-id", {
participantName: "John Doe",
modalities: ['voice', 'chat'],
metadata: {
customerType: "premium",
department: "support"
}
});
// Get current session
const currentSession = client.getCurrentSession();
// End session manually
await client.endSession();๐ Custom Analytics Integration
client.on('session.created', (session) => {
analytics.track('voxket_session_created', {
sessionId: session.id,
agentId: session.agentId,
modalities: session.activeModalities
});
});
client.on('chat.message.received', (message) => {
analytics.track('voxket_message_received', {
messageType: message.sender.type,
contentLength: message.content.length,
sessionId: client.getCurrentSession()?.id
});
});๐ Multiple Widget Instances
// Support chat
const supportClient = new VoxketClient(supportConfig);
supportClient.renderUI({
target: '#support-widget',
modality: ['chat']
});
// Sales call
const salesClient = new VoxketClient(salesConfig);
salesClient.renderUI({
target: '#sales-widget',
modality: ['voice', 'video']
});๐ฏ HTML/Vanilla JavaScript Integration
Use the SDK without any framework:
<!DOCTYPE html>
<html>
<head>
<title>Voxket Integration</title>
<script src="https://unpkg.com/@voxket-ai/voxket-live@latest/dist/index.js"></script>
</head>
<body>
<div id="voxket-container"></div>
<script>
const { VoxketClient } = window.VoxketLive;
const client = new VoxketClient({
appId: 'your-app-id',
appSecret: 'your-secret',
baseUrl: 'https://api.voxket.com',
agentId: 'support-agent'
});
client.connect().then(() => {
client.renderUI({
target: '#voxket-container',
modality: ['chat'],
theme: 'light'
});
});
</script>
</body>
</html>๐ง VoxketClient API Reference
๐๏ธ Constructor Options
interface VoxketClientConfig {
// Required
appId: string; // Your Voxket App ID
appSecret: string; // Your Voxket App Secret
baseUrl: string; // Voxket API base URL
// Optional
agentId?: string; // Default agent ID
participantName?: string; // Default participant name
modalities?: SessionModality[]; // Default modalities
debug?: boolean; // Enable debug logging
// Event Callbacks
onConnected?: () => void;
onDisconnected?: (reason?: string) => void;
onError?: (error: Error) => void;
onMessageReceived?: (message: ChatMessage) => void;
onTranscriptionReceived?: (transcription: TranscriptionSegment) => void;
onSessionStateChanged?: (state: SessionState) => void;
}๐ Connection Methods
// Connect to Voxket services
await client.connect(agentId?, participantName?, modalities?);
// Disconnect and cleanup
await client.disconnect();
// Check connection status
const isConnected = client.connected;
const state = client.getConnectionState();๐ฌ Session Management
// Start a new session
const session = await client.startSession(agentId, {
participantName: "User",
modalities: ['voice', 'chat'],
metadata: { customData: "value" }
});
// Get current session
const current = client.getCurrentSession();
// End current session
await client.endSession();๐จ UI Rendering
// Render UI widget
client.renderUI({
target: '#container', // CSS selector or HTMLElement
modality: ['voice', 'chat'], // Supported modalities
theme: 'dark', // Theme selection
component: 'widget', // Component type
displayType: 'popup', // Display mode
autoStart: true, // Auto-start session
width: '400px', // Custom width
height: '600px', // Custom height
onDisplayTypeChange: (type) => console.log(type)
});
// Remove UI
client.removeUI('#container');
client.removeAllUI();๐ฌ Messaging
// Send text message
await client.sendMessage("Hello agent!");
// Send with metadata
await client.sendChatMessage("Hello", { priority: "high" });
// Send file attachments (images only)
await client.sendAttachment(imageFile);
await client.sendAttachments([file1, file2]);๐ต Media Control Methods
// Microphone control
await client.toggleMicrophone();
await client.setMicrophoneEnabled(true);
const isMuted = !client.isMicrophoneEnabled;
// Camera control
await client.enableCamera();
await client.disableCamera();
await client.toggleCamera();
const isCameraOn = client.isCameraEnabled;
// Screen sharing
await client.startScreenShare();
await client.stopScreenShare();
const isSharing = client.isScreenShareEnabled;
// Device management
const audioDevices = await client.getAudioInputDevices();
const videoDevices = await client.getVideoInputDevices();
await client.setAudioInputDevice(deviceId);
await client.setVideoInputDevice(deviceId);๏ฟฝ Event System Methods
// Register custom event emitter
client.registerEventEmitter(
topic: string,
handler: (data: string) => void
): void
// Register event listener with cleanup
client.registerEventListener<K extends keyof VoxketEvents>(
eventName: K,
callback: (data: any) => void
): () => void
// Example usage
const unsubscribe = client.registerEventListener('chat.message.received', (msg) => {
console.log('Message:', msg);
});
// Cleanup
unsubscribe();๏ฟฝ๐ฅ Participant Management
// Get participants
const localParticipant = client.getLocalParticipant();
const remoteParticipants = client.getRemoteParticipants();
const allParticipants = client.getParticipants();
// Check permissions
const permissions = client.getPublishPermissions();
const canPublish = client.canPublishSource('microphone');
// Get media tracks
const micTrack = client.getMicrophoneTrack();
const cameraTrack = client.getCameraTrack();
const screenTrack = client.getScreenShareTrack();๐ช Interactive Components Deep Dive
๐ Creating Custom Interactive Components
import React, { useState } from 'react';
import { VoxketInteractiveViewProps } from '@voxket-ai/voxket-live';
function SurveyForm({ handler, data }: VoxketInteractiveViewProps) {
const [rating, setRating] = useState(0);
const [feedback, setFeedback] = useState('');
const handleSubmit = () => {
handler?.didSuccess({
survey_rating: rating,
customer_feedback: feedback,
submitted_at: new Date().toISOString()
});
};
const handleSkip = () => {
handler?.dismissView(); // Sends decline response to agent
};
return (
<div className="p-6 bg-white rounded-lg shadow-lg">
<h3 className="text-lg font-semibold mb-4">
{data?.title || 'Rate Your Experience'}
</h3>
<div className="mb-4">
<label className="block text-sm font-medium mb-2">
How would you rate our service?
</label>
<div className="flex gap-2">
{[1,2,3,4,5].map(num => (
<button
key={num}
onClick={() => setRating(num)}
className={`w-10 h-10 rounded ${
rating >= num ? 'bg-blue-500 text-white' : 'bg-gray-200'
}`}
>
{num}
</button>
))}
</div>
</div>
<div className="mb-4">
<label className="block text-sm font-medium mb-2">
Additional feedback (optional):
</label>
<textarea
value={feedback}
onChange={(e) => setFeedback(e.target.value)}
className="w-full p-2 border rounded"
rows={3}
/>
</div>
<div className="flex gap-2 justify-end">
<button
onClick={handleSkip}
className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded"
>
Skip
</button>
<button
onClick={handleSubmit}
disabled={rating === 0}
className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
>
Submit
</button>
</div>
</div>
);
}
// Register the component
await client.registerFrontendRPC(
'customer_satisfaction_survey',
SurveyForm,
'modal' // Can be 'embedded', 'modal', or 'fullscreen'
);๐ E-commerce Product Showcase
function ProductCatalog({ handler, data }: VoxketInteractiveViewProps) {
const [selectedProduct, setSelectedProduct] = useState(null);
const products = data?.products || [];
const handleSelectProduct = (product: any) => {
handler?.didSuccess({
selected_product: product,
action: 'add_to_cart'
});
};
return (
<div className="p-4">
<h3 className="text-xl font-bold mb-4">Recommended Products</h3>
<div className="grid grid-cols-2 gap-4">
{products.map((product: any) => (
<div key={product.id} className="border rounded-lg p-4">
<img
src={product.image}
alt={product.name}
className="w-full h-32 object-cover rounded mb-2"
/>
<h4 className="font-semibold">{product.name}</h4>
<p className="text-gray-600">${product.price}</p>
<button
onClick={() => handleSelectProduct(product)}
className="mt-2 w-full bg-blue-500 text-white py-2 rounded"
>
Add to Cart
</button>
</div>
))}
</div>
</div>
);
}๐ Appointment Scheduler
function AppointmentBooker({ handler, data }: VoxketInteractiveViewProps) {
const [selectedSlot, setSelectedSlot] = useState('');
const [contactInfo, setContactInfo] = useState({ name: '', email: '' });
const availableSlots = data?.available_slots || [];
const handleBooking = () => {
handler?.didSuccess({
appointment: {
slot: selectedSlot,
contact: contactInfo,
type: data?.appointment_type,
booked_at: new Date().toISOString()
}
});
};
return (
<div className="p-6 bg-white rounded-lg">
<h3 className="text-lg font-semibold mb-4">Book Appointment</h3>
<div className="mb-4">
<label className="block text-sm font-medium mb-2">
Available Time Slots:
</label>
<div className="grid grid-cols-2 gap-2">
{availableSlots.map((slot: string) => (
<button
key={slot}
onClick={() => setSelectedSlot(slot)}
className={`p-2 rounded border ${
selectedSlot === slot
? 'bg-blue-500 text-white'
: 'bg-gray-50 hover:bg-gray-100'
}`}
>
{slot}
</button>
))}
</div>
</div>
<div className="mb-4">
<input
type="text"
placeholder="Your Name"
value={contactInfo.name}
onChange={(e) => setContactInfo({...contactInfo, name: e.target.value})}
className="w-full p-2 border rounded mb-2"
/>
<input
type="email"
placeholder="Email Address"
value={contactInfo.email}
onChange={(e) => setContactInfo({...contactInfo, email: e.target.value})}
className="w-full p-2 border rounded"
/>
</div>
<button
onClick={handleBooking}
disabled={!selectedSlot || !contactInfo.name || !contactInfo.email}
className="w-full bg-green-500 text-white py-2 rounded disabled:opacity-50"
>
Book Appointment
</button>
</div>
);
}๐ Session Analytics & Metrics
๐ Session Metrics Interface
interface SessionMetrics {
sessionId: string;
startTime: Date;
endTime?: Date;
duration?: number; // Duration in milliseconds
totalMessages: number; // Total messages exchanged
connectionIssues: number; // Network issues count
participantCount: number; // Number of participants
events: SessionLog[]; // All session events
}
interface SessionLog {
timestamp: Date;
event: string; // Event type
data?: any; // Event data
sessionId?: string; // Associated session
participantId?: string; // Participant who triggered event
}๐ Analytics Integration Examples
// Google Analytics 4
client.on('session.created', (session) => {
gtag('event', 'voxket_session_start', {
session_id: session.id,
agent_id: session.agentId,
modalities: session.activeModalities.join(',')
});
});
// Mixpanel
client.on('chat.message.received', (message) => {
mixpanel.track('Voxket Message Received', {
session_id: client.getCurrentSession()?.id,
message_type: message.sender.type,
message_length: message.content.length,
timestamp: message.timestamp
});
});
// Custom Analytics
const analyticsTracker = {
trackSession: (event: string, data: any) => {
fetch('/api/analytics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event, data, timestamp: new Date() })
});
}
};
client.on('session.ended', (session, metrics) => {
analyticsTracker.trackSession('session_completed', {
duration: metrics.duration,
message_count: metrics.totalMessages,
quality_score: calculateQualityScore(metrics)
});
});๐ ๏ธ Enterprise Features
๐ Security & Compliance
// HIPAA-compliant configuration
const healthcareClient = new VoxketClient({
appId: "healthcare-app",
appSecret: "hipaa-compliant-secret",
baseUrl: "https://secure-api.voxket.com",
agentId: "patient-support",
// Disable session logging for compliance
enableSessionLogging: false,
onSessionStart: (sessionId) => {
// HIPAA audit logging
complianceLogger.logPatientInteraction({
sessionId,
patientId: getCurrentPatient().id,
timestamp: new Date(),
actionType: 'SESSION_START'
});
}
});
// Only use secure text-based modalities
await healthcareClient.connect();
healthcareClient.renderUI({
modality: ['chat'], // Text only for security
theme: 'light',
enableSessionLogging: false
});๐ข Multi-tenant Architecture
class TenantManager {
private clients: Map<string, VoxketClient> = new Map();
async createTenantClient(tenantId: string, config: any) {
const client = new VoxketClient({
appId: config.appId,
appSecret: config.appSecret,
baseUrl: config.baseUrl,
agentId: `${tenantId}-agent`,
onMessageReceived: (message) => {
// Tenant-specific message handling
this.handleTenantMessage(tenantId, message);
}
});
this.clients.set(tenantId, client);
return client;
}
getTenantClient(tenantId: string) {
return this.clients.get(tenantId);
}
private handleTenantMessage(tenantId: string, message: any) {
// Tenant-specific analytics, logging, etc.
console.log(`Tenant ${tenantId} received message:`, message);
}
}
// Usage
const tenantManager = new TenantManager();
const client = await tenantManager.createTenantClient('acme-corp', {
appId: 'acme-app-id',
appSecret: 'acme-secret',
baseUrl: 'https://acme.voxket.com'
});๐ Advanced Session Management
// Session persistence across page reloads
class SessionManager {
private static SESSION_KEY = 'voxket_session';
static saveSession(session: VoxketSession) {
localStorage.setItem(this.SESSION_KEY, JSON.stringify({
id: session.id,
agentId: session.agentId,
startedAt: session.startedAt,
metadata: session.metadata
}));
}
static restoreSession(): VoxketSession | null {
const saved = localStorage.getItem(this.SESSION_KEY);
if (saved) {
try {
return JSON.parse(saved);
} catch {
return null;
}
}
return null;
}
static clearSession() {
localStorage.removeItem(this.SESSION_KEY);
}
}
// Restore previous session on page load
const client = new VoxketClient(config);
const previousSession = SessionManager.restoreSession();
if (previousSession) {
// Attempt to reconnect to existing session
try {
await client.connect();
// Check if session is still valid and restore UI state
} catch (error) {
SessionManager.clearSession();
// Start fresh session
}
}๐ง Troubleshooting
โ Common Issues
1. Widget Not Displaying
// Check console for errors and verify configuration
const client = new VoxketClient({
appId: "your-app-id", // โ
Make sure this is correct
appSecret: "your-app-secret", // โ
Make sure this is correct
baseUrl: "https://api.voxket.com", // โ
Check URL is correct
debug: true // โ
Enable debug logging
});2. Connection Failures
client.on('connection.error', (error) => {
console.error('Connection failed:', error);
// Common fixes:
// - Verify appId and appSecret are correct
// - Check baseUrl is accessible
// - Ensure network connectivity
// - Check for CORS issues in browser console
});
client.on('connection.disconnected', (reason) => {
console.log('Disconnected reason:', reason);
// Auto-reconnect logic
setTimeout(() => {
client.connect().catch(console.error);
}, 5000);
});3. Microphone/Camera Permission Issues
// Handle permission errors gracefully
client.on('connection.error', (error) => {
if (error.code === 'PERMISSION_DENIED') {
showUserMessage('Please allow microphone/camera access to continue');
}
});
// Request permissions explicitly
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then(() => {
console.log('Permissions granted');
}).catch((error) => {
console.error('Permission denied:', error);
});4. React Strict Mode Issues
// For React 18 Strict Mode, wrap your app properly
function App() {
const [client, setClient] = useState<VoxketClient | null>(null);
useEffect(() => {
// Only create client once
if (!client) {
const newClient = new VoxketClient(config);
setClient(newClient);
}
return () => {
// Cleanup on unmount
client?.disconnect();
};
}, []);
if (!client) return <div>Loading...</div>;
return <VoxketWidget voxketClient={client} {...props} />;
}๐ Debug Mode
// Enable comprehensive debugging
const client = new VoxketClient({
// ... config
debug: true
});
// Monitor all events
client.onAny((eventName, ...args) => {
console.log(`๐ Event: ${eventName}`, args);
});
// Check connection state
console.log('Connection state:', client.getConnectionState());
console.log('Current session:', client.getCurrentSession());
console.log('Is connected:', client.connected);๐ ๏ธ Performance Optimization
// Optimize for production
const client = new VoxketClient({
// ... config
debug: false, // Disable debug logs
});
// Lazy load the widget
const LazyVoxketWidget = lazy(() => import('@voxket-ai/voxket-live'));
function App() {
return (
<Suspense fallback={<div>Loading chat...</div>}>
<LazyVoxketWidget {...props} />
</Suspense>
);
}
// Preload on user interaction
const preloadChat = () => {
import('@voxket-ai/voxket-live').then(() => {
console.log('Voxket SDK preloaded');
});
};
// Call preloadChat() on hover or focus events๐ฏ Best Practices
๐๏ธ Application Architecture
1. Client Instance Management
// โ
Good: Single client instance
class VoxketManager {
private static instance: VoxketClient | null = null;
static getInstance(config: VoxketClientConfig): VoxketClient {
if (!this.instance) {
this.instance = new VoxketClient(config);
}
return this.instance;
}
static cleanup() {
if (this.instance) {
this.instance.disconnect();
this.instance = null;
}
}
}
// โ Bad: Multiple client instances
function BadComponent() {
const [client] = useState(() => new VoxketClient(config)); // Creates new client each render
}2. Error Handling
// โ
Comprehensive error handling
async function initializeVoxket() {
try {
await client.connect();
client.renderUI({ target: '#voxket-widget' });
} catch (error) {
if (error.code === 'AUTHENTICATION_FAILED') {
showError('Invalid credentials');
} else if (error.code === 'NETWORK_ERROR') {
showError('Connection failed - please try again');
} else {
showError('Something went wrong');
}
// Log for debugging
console.error('Voxket initialization failed:', error);
}
}3. Event Cleanup
// โ
Always cleanup event listeners
useEffect(() => {
const handleMessage = (message: ChatMessage) => {
// Handle message
};
client.on('chat.message.received', handleMessage);
return () => {
client.off('chat.message.received', handleMessage);
};
}, [client]);๐ฑ User Experience
1. Loading States
function ChatWidget() {
const [isConnecting, setIsConnecting] = useState(false);
const [connectionError, setConnectionError] = useState('');
const initChat = async () => {
setIsConnecting(true);
setConnectionError('');
try {
await client.connect();
client.renderUI({ target: '#chat' });
} catch (error) {
setConnectionError('Failed to connect. Please try again.');
} finally {
setIsConnecting(false);
}
};
return (
<div>
{isConnecting && <div>Connecting to support...</div>}
{connectionError && <div className="error">{connectionError}</div>}
<button onClick={initChat} disabled={isConnecting}>
Start Chat
</button>
<div id="chat"></div>
</div>
);
}2. Progressive Enhancement
// Start with basic features, enhance based on capabilities
const client = new VoxketClient(config);
// Check agent capabilities
const agentInfo = client.getCurrentAgentInfo();
const supportedModalities = agentInfo?.modality_supported || ['chat'];
// Render appropriate UI
client.renderUI({
modality: supportedModalities.includes('voice')
? ['voice', 'chat']
: ['chat'],
theme: userPreferences.theme || 'vox'
});3. Accessibility
// Ensure keyboard navigation and screen reader support
<VoxketWidget
className="voxket-accessible"
// Widget automatically includes ARIA labels and keyboard support
{...props}
/>
/* CSS for better accessibility */
.voxket-accessible {
/* Ensure focus indicators are visible */
--focus-ring-color: #3b82f6;
}
.voxket-accessible *:focus {
outline: 2px solid var(--focus-ring-color);
outline-offset: 2px;
}๐ Security
1. Credential Management
// โ
Use environment variables
const client = new VoxketClient({
appId: process.env.VOXKET_APP_ID,
appSecret: process.env.VOXKET_APP_SECRET,
baseUrl: process.env.VOXKET_BASE_URL
});
// โ
For browser apps, use backend proxy
async function getVoxketCredentials() {
const response = await fetch('/api/voxket-auth', {
headers: {
'Authorization': `Bearer ${userToken}`
}
});
return response.json();
}2. Content Security Policy
<!-- Add CSP headers for security -->
<meta http-equiv="Content-Security-Policy"
content="connect-src 'self' wss://*.voxket.com https://*.voxket.com;">๐ Framework Integration Examples
โ๏ธ React with TypeScript
import React, { useCallback, useEffect, useState } from 'react';
import VoxketWidget, {
VoxketWidgetProps,
VoxketClient,
SessionMetrics
} from '@voxket-ai/voxket-live';
interface Props {
agentId: string;
userId: string;
userRole: 'customer' | 'admin';
}
export function CustomerSupport({ agentId, userId, userRole }: Props) {
const [sessionMetrics, setSessionMetrics] = useState<SessionMetrics | null>(null);
const [isActive, setIsActive] = useState(false);
const handleSessionStart = useCallback((sessionId: string) => {
setIsActive(true);
console.log('Support session started:', sessionId);
}, []);
const handleSessionEnd = useCallback((metrics: SessionMetrics) => {
setSessionMetrics(metrics);
setIsActive(false);
console.log('Session ended:', metrics);
}, []);
const widgetProps: VoxketWidgetProps = {
agentId,
baseUrl: process.env.NEXT_PUBLIC_VOXKET_BASE_URL!,
appId: process.env.NEXT_PUBLIC_VOXKET_APP_ID!,
appSecret: process.env.NEXT_PUBLIC_VOXKET_APP_SECRET!,
participantName: `User-${userId}`,
theme: 'vox',
modalities: ['chat', 'voice'],
displayType: 'popup',
popupPosition: 'bottom-right',
onSessionStart: handleSessionStart,
onSessionEnd: handleSessionEnd
};
return (
<div className="customer-support">
{isActive && (
<div className="status-indicator">
๐ข Support session active
</div>
)}
<VoxketWidget {...widgetProps} />
{sessionMetrics && (
<div className="session-summary">
<h4>Session Summary</h4>
<p>Duration: {Math.round(sessionMetrics.duration! / 1000)}s</p>
<p>Messages: {sessionMetrics.totalMessages}</p>
</div>
)}
</div>
);
}๐ Vue 3 Composition API
<template>
<div class="vue-voxket">
<button @click="initializeChat" :disabled="isLoading">
Start Support Chat
</button>
<div ref="voxketContainer" class="voxket-container"></div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { VoxketClient } from '@voxket-ai/voxket-live';
const voxketContainer = ref<HTMLElement>();
const isLoading = ref(false);
let client: VoxketClient | null = null;
const initializeChat = async () => {
if (!client || !voxketContainer.value) return;
isLoading.value = true;
try {
await client.connect();
client.renderUI({
target: voxketContainer.value,
modality: ['chat'],
theme: 'light',
autoStart: true
});
} catch (error) {
console.error('Failed to initialize chat:', error);
} finally {
isLoading.value = false;
}
};
onMounted(() => {
client = new VoxketClient({
appId: import.meta.env.VITE_VOXKET_APP_ID,
appSecret: import.meta.env.VITE_VOXKET_APP_SECRET,
baseUrl: import.meta.env.VITE_VOXKET_BASE_URL,
agentId: 'vue-support-agent'
});
});
onUnmounted(() => {
if (client) {
client.removeAllUI();
client.disconnect();
}
});
</script>๐ ฐ๏ธ Angular Component
// voxket.service.ts
import { Injectable } from '@angular/core';
import { VoxketClient } from '@voxket-ai/voxket-live';
@Injectable({ providedIn: 'root' })
export class VoxketService {
private client: VoxketClient;
constructor() {
this.client = new VoxketClient({
appId: environment.voxketAppId,
appSecret: environment.voxketAppSecret,
baseUrl: environment.voxketBaseUrl
});
}
async startChat(containerId: string, agentId: string) {
await this.client.connect();
this.client.renderUI({
target: `#${containerId}`,
agentId,
modality: ['chat'],
theme: 'dark'
});
}
disconnect() {
this.client.removeAllUI();
this.client.disconnect();
}
}
// chat.component.ts
@Component({
selector: 'app-chat',
template: `
<div class="chat-container">
<button (click)="startChat()" [disabled]="isLoading">
{{ isLoading ? 'Connecting...' : 'Start Chat' }}
</button>
<div id="angular-voxket-container"></div>
</div>
`
})
export class ChatComponent implements OnDestroy {
isLoading = false;
constructor(private voxketService: VoxketService) {}
async startChat() {
this.isLoading = true;
try {
await this.voxketService.startChat('angular-voxket-container', 'support-agent');
} finally {
this.isLoading = false;
}
}
ngOnDestroy() {
this.voxketService.disconnect();
}
}๐ช Svelte Integration
<!-- VoxketChat.svelte -->
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { VoxketClient } from '@voxket-ai/voxket-live';
export let agentId: string;
export let theme: 'dark' | 'light' | 'vox' = 'vox';
let container: HTMLElement;
let client: VoxketClient;
let isConnected = false;
onMount(() => {
client = new VoxketClient({
appId: import.meta.env.VITE_VOXKET_APP_ID,
appSecret: import.meta.env.VITE_VOXKET_APP_SECRET,
baseUrl: import.meta.env.VITE_VOXKET_BASE_URL,
onConnected: () => {
isConnected = true;
},
onDisconnected: () => {
isConnected = false;
}
});
});
async function startChat() {
if (!client || !container) return;
try {
await client.connect();
client.renderUI({
target: container,
agentId,
modality: ['chat'],
theme
});
} catch (error) {
console.error('Chat initialization failed:', error);
}
}
onDestroy(() => {
if (client) {
client.removeAllUI();
client.disconnect();
}
});
</script>
<div class="svelte-voxket">
<button on:click={startChat} disabled={!client}>
{isConnected ? '๐ฌ Chat Active' : 'Start Chat'}
</button>
<div bind:this={container} class="chat-container"></div>
</div>
<style>
.chat-container {
width: 400px;
height: 600px;
border-radius: 12px;
overflow: hidden;
}
</style>๐ Deployment & Production
๐ญ Production Checklist
// โ
Production configuration
const client = new VoxketClient({
appId: process.env.VOXKET_APP_ID!, // From secure environment
appSecret: process.env.VOXKET_APP_SECRET!, // From secure environment
baseUrl: process.env.VOXKET_BASE_URL!, // Production URL
debug: false, // Disable debug logs
// Error tracking
onError: (error) => {
// Send to error monitoring service (Sentry, etc.)
console.error('Voxket error:', error);
errorTracker.captureException(error);
}
});
// โ
Health check endpoint
app.get('/health/voxket', async (req, res) => {
try {
// Test Voxket API connectivity
const response = await fetch(`${process.env.VOXKET_BASE_URL}/health`);
if (response.ok) {
res.status(200).json({ status: 'healthy' });
} else {
res.status(503).json({ status: 'unhealthy' });
}
} catch (error) {
res.status(503).json({ status: 'error', error: error.message });
}
});๐ Monitoring & Analytics
// Production monitoring setup
class VoxketMonitoring {
static setupMonitoring(client: VoxketClient) {
// Connection monitoring
client.on('connection.connected', () => {
this.trackEvent('voxket_connected');
});
client.on('connection.error', (error) => {
this.trackError('voxket_connection_error', error);
});
// Session analytics
client.on('session.created', (session) => {
this.trackEvent('voxket_session_start', {
session_id: session.id,
agent_id: session.agentId
});
});
// Performance monitoring
const startTime = Date.now();
client.on('connection.connected', () => {
const connectionTime = Date.now() - startTime;
this.trackTiming('voxket_connection_time', connectionTime);
});
}
private static trackEvent(event: string, data?: any) {
// Send to your analytics service
analytics.track(event, data);
}
private static trackError(event: string, error: Error) {
// Send to error monitoring
errorTracker.captureException(error, { tags: { component: 'voxket' } });
}
private static trackTiming(metric: string, duration: number) {
// Send to performance monitoring
performanceTracker.timing(metric, duration);
}
}
// Apply monitoring
VoxketMonitoring.setupMonitoring(client);๐ API Reference Summary
๐๏ธ Core Classes
VoxketClient- Main SDK client for programmatic controlVoxketWidget- React component for easy integrationVoxketProvider- React context provider for advanced usage
๐จ Display Types
widget- Embedded widget modepopup- Floating popup modefullscreen- Full-screen overlay mode
๐ญ Themes
vox- Default Voxket branded themedark- Dark mode themelight- Light mode theme- Custom - Create your own theme object
๐ช Modalities
voice- Voice conversations with transcriptionchat- Text-based messagingvideo- Video calls with camera supportscreen_share- Screen sharing capability
๐ก Event Categories
- Connection Events -
connection.* - Session Events -
session.* - Chat Events -
chat.* - Agent Events -
agent.* - Media Events -
track.* - RPC Events -
rpc.*
๐ค Community & Support
๐ Documentation
๐ Getting Help
๐งช Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
๐ License
MIT License - see LICENSE file for details.
๐ Ready to Get Started?
- Install the SDK:
npm install @voxket-ai/voxket-live - Get your credentials from the Voxket Dashboard
- Choose your integration method (Widget, Client SDK, or Advanced React)
- Start building amazing AI-powered experiences!
๐ก Need help?
Check out our Quick Start Guide or join our Discord community for real-time support!
Built with โค๏ธ by the Voxket team