Adeptly Live widget - AI voice guidance with screen sharing (nightly/unstable)
npm install adeptly-live-widgetEmbeddable AI voice guidance widget with screen sharing capabilities. Creates a floating Picture-in-Picture window that follows users across tabs and windows.
``bash`
npm install adeptly-live-widgetor
pnpm add adeptly-live-widgetor
yarn add adeptly-live-widget
Make sure your project has these peer dependencies:
`bash`
npm install react react-dom three
This widget requires a running WebSocket server. You can either:
Option A: Use the Adeptly Live Server (Local Development)
`bash`Clone the adeptly-live repo
git clone
cd adeptly-live/server
npm install
npm run dev # Runs on ws://localhost:8080
Option B: Use Production Server
``
wss://adeptly-live-production.up.railway.app
Create a .env.local file in your project root:
`envREQUIRED: WebSocket URL (must use ws:// or wss:// protocol)
⚠️ IMPORTANT:
- Use
ws:// for local development (HTTP)
- Use wss:// for production (HTTPS)
- Do NOT use http:// or https:// - WebSockets require ws:// or wss://Usage
$3
`tsx
'use client'; // Required for Next.js App Routerimport { useState } from 'react';
import { AdeptlyWidget } from 'adeptly-live-widget';
export default function MyPage() {
const [isActive, setIsActive] = useState(false);
return (
<>
wsUrl={process.env.NEXT_PUBLIC_WS_URL || 'ws://localhost:8080'}
autoStart={isActive}
onSessionStart={() => console.log('Session started')}
onSessionEnd={() => setIsActive(false)}
onError={(error) => {
console.error('Widget error:', error);
setIsActive(false);
}}
/>
>
);
}
`$3
`tsx
wsUrl={process.env.NEXT_PUBLIC_WS_URL!}
autoStart={isActive}
logoPath="/custom-logo.png"
exrPath="/custom-environment.exr" // Optional 3D environment map
onSessionEnd={() => setIsActive(false)}
/>
`$3
Track widget usage in your own PostHog instance:
`tsx
import { AdeptlyWidget, EVENTS, PROPERTIES } from 'adeptly-live-widget'; wsUrl={process.env.NEXT_PUBLIC_WS_URL!}
autoStart={isActive}
posthog={{
apiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY!,
apiHost: 'https://us.i.posthog.com', // Optional, defaults to US
source: 'my-app-name' // Optional, identifies your implementation
}}
onSessionEnd={() => setIsActive(false)}
/>
`Events Tracked:
-
session_started / session_ended / session_error
- widget_activated / widget_deactivated
- websocket_connected / websocket_disconnected / websocket_error
- screen_share_started / screen_share_ended
- pip_opened / pip_closed
- conversation_phase_changed
- media_permission_granted / media_permission_deniedProperties Included:
-
session_id - Unique identifier for each session
- source - Your app name (from config)
- ws_url - WebSocket server URL
- timestamp - Event timestamp
- current_status - AI status (idle/listening/thinking/speaking)All events are automatically enriched with session context.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
|
wsUrl | string | ✅ Yes | WebSocket server URL (must start with ws:// or wss://) |
| autoStart | boolean | No | Auto-trigger screen sharing when true |
| position | 'bottom-right' \| 'bottom-left' | No | Widget position (currently not used with PiP) |
| onSessionStart | () => void | No | Callback when session starts |
| onSessionEnd | () => void | No | Callback when session ends |
| onError | (error: string \| null) => void | No | Callback for errors (null to clear) |
| logoPath | string | No | Custom logo path for PiP window |
| exrPath | string | No | Custom EXR environment map for 3D visualization |
| posthog | PostHogConfig | No | PostHog analytics config (optional) |$3
`typescript
interface PostHogConfig {
apiKey: string; // Your PostHog API key
apiHost?: string; // PostHog API host (defaults to 'https://us.i.posthog.com')
source?: string; // Source identifier (e.g., 'my-company-app')
}
`How It Works
1. User clicks button → Triggers
setIsActive(true)
2. Widget auto-starts → Requests microphone and screen sharing permissions
3. PiP window opens → Floating window with 3D animated orb
4. WebSocket connects → Streams audio (16kHz) and video (1fps JPEG)
5. AI responds → Voice guidance plays through PiP window
6. Window follows user → PiP stays visible across tabs/windowsFeatures
- 🎤 Real-time voice conversation - Bidirectional audio streaming
- 🖥️ Screen sharing - AI can see what you're doing
- 🎨 Animated 3D orb - Real-time audio visualization with Three.js
- 📊 Live status indicators - Ready/Listening/Thinking/Speaking
- 💬 Real-time transcription - Shows user and AI messages
- 🪟 Picture-in-Picture - Floating window that follows you everywhere
Browser Compatibility
$3
- Chrome/Edge - Document Picture-in-Picture API
- Modern browsers - getUserMedia, getDisplayMedia APIs$3
`typescript
if ('documentPictureInPicture' in window) {
// PiP supported ✅
} else {
// Show fallback UI ❌
}
`Troubleshooting
$3
Problem:
WebSocket connection to 'ws://localhost:8080/' failedSolutions:
1. Check server is running:
lsof -i:8080
2. Verify .env.local has correct URL with ws:// protocol
3. Restart your dev server to pick up env changes
4. Check browser console for CORS errors$3
Problem: Button clicks but nothing happens
Solutions:
1. Check browser console for errors
2. Verify browser supports Document PiP (Chrome/Edge only)
3. Ensure
autoStart prop is being set to true
4. Check WebSocket connection is established first$3
Problem: Microphone/screen sharing permission denied
Solutions:
1. Must use HTTPS in production (or localhost for dev)
2. User must click button (can't auto-start without user gesture)
3. Check browser permission settings
$3
Problem: Widget uses default
ws://localhost:8080 instead of your URLSolutions:
1. File must be named
.env.local (not .env)
2. Variable must start with NEXT_PUBLIC_ for client-side access
3. Restart dev server after creating/editing .env.local
4. Use process.env.NEXT_PUBLIC_WS_URL not process.env.WS_URLQuick Start Checklist
- [ ] Install package:
pnpm add @adeptly/live-widget
- [ ] Install dependencies: pnpm add three
- [ ] Create .env.local with NEXT_PUBLIC_WS_URL=ws://localhost:8080
- [ ] Start WebSocket server on port 8080
- [ ] Import and add to your component
- [ ] Test button triggers autoStart={true}
- [ ] Grant microphone + screen sharing permissions
- [ ] Verify PiP window appearsDirect PiP Link Pattern
Want a shareable link that immediately launches the PiP experience? Create a dedicated route:
`tsx
// app/pip/page.tsx
'use client';import { useState, useEffect } from 'react';
import { AdeptlyWidget } from 'adeptly-live-widget';
export default function PiPPage() {
const [isActive, setIsActive] = useState(false);
useEffect(() => {
// Auto-activate on first click anywhere
const handleClick = () => {
setIsActive(true);
document.removeEventListener('click', handleClick);
};
document.addEventListener('click', handleClick);
return () => document.removeEventListener('click', handleClick);
}, []);
if (isActive) {
return (
<>
Launching PiP Experience...
wsUrl={process.env.NEXT_PUBLIC_WS_URL!}
autoStart={true}
onSessionEnd={() => setIsActive(false)}
/>
>
);
} return (
setIsActive(true)} className="min-h-screen cursor-pointer">
Click to Launch PiP
);
}
`Now you can share:
https://your-site.com/pipUsers click the link → Click anywhere → PiP launches immediately!
Use cases:
- Add to Canva presentations
- Embed in Google Slides
- Share via email or social media
- Include in documentation
- Generate QR codes
Example Projects
See integration examples:
- Direct PiP Link:
/adeptly-lp/app/pip/page.tsx
- Enterprise LP: /adeptly-enterprise-lp/app/page.tsx
- Original App: /adeptly-live/client/app/page.tsxSupport
For issues:
1. Check browser console for
[WebSocket], [MediaCapture], or [PiP]` errorsMIT