@voxket-ai/voxket-live
v1.1.30
Published
A React widget for embedding Voxket-powered audio/video/chat experiences.
Maintainers
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-liveyarn add @voxket-ai/voxket-live🎯 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);
});🤖 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
