@buzztrail-ai/presentation
v1.4.1
Published
AI-powered slide presentations with voice interaction for any website platform.
Readme
@buzztrail-ai/presentation
AI-powered slide presentations with voice interaction for any website platform.
Overview
@buzztrail-ai/presentation enables AI-powered slide presentations with voice interaction on any website platform. Add an interactive AI-guided slide deck to your site in minutes - no complex setup required.
⚠️ Account Required: You need an active BuzzTrail account to use this package. Sign up at buzztrail.ai to get your customer ID and configure your presentations.
Features
- Interactive AI Presentations: Engage website visitors with AI-guided slide presentations
- Voice Interaction: Natural voice conversations about slide content
- Manual Controls: Optional manual slide navigation controls
- Works Everywhere: Wix, Webflow, WordPress, Shopify, or any custom website
- Simple Integration: Just call
createPresentation() - Fast Loading: Ultra-lightweight package that won't slow down your site
- Mobile-Friendly: Automatically adapts to desktop, tablet, and mobile screens
- Customizable: Match your brand with custom colors and theming
- Lead Capture: Optional forms to collect visitor information before presentations
- Real-time Sync: Slide changes sync across all viewers in real-time
- No Technical Skills: Works without coding knowledge (perfect for Wix users)
Getting Started
Prerequisites
- BuzzTrail Account: Sign up at buzztrail.ai
- Customer ID: You'll receive this after account setup
- Deck ID: Create a presentation deck in the BuzzTrail dashboard
- Supabase Credentials: You'll receive these from BuzzTrail support
Installation
NPM (for developers)
npm install @buzztrail-ai/presentationyarn add @buzztrail-ai/presentationpnpm add @buzztrail-ai/presentationCDN (for Wix, Webflow, no-code platforms)
<script src="https://cdn.jsdelivr.net/npm/@buzztrail-ai/presentation@1/buzztrail-presentation.min.js"></script>Fallback CDN (unpkg):
<script src="https://unpkg.com/@buzztrail-ai/presentation@1/buzztrail-presentation.min.js"></script>Quick Start
CDN Usage (Wix, Webflow, etc.)
<!-- 1. Add a container element to your page -->
<div id="presentation-container"></div>
<!-- 2. Add the BuzzTrail Presentation script -->
<script src="https://cdn.jsdelivr.net/npm/@buzztrail-ai/presentation@1/buzztrail-presentation.min.js"></script>
<!-- 3. Initialize the presentation -->
<script>
const presentation = createPresentation('presentation-container', {
customerId: 'your-customer-id',
deckId: 'your-deck-id',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key'
});
// Start the presentation
presentation.start();
</script>That's it! The interactive presentation will appear in your container.
With Callbacks
For more control, add callback functions:
<div id="my-presentation"></div>
<script src="https://cdn.jsdelivr.net/npm/@buzztrail-ai/presentation@1/buzztrail-presentation.min.js"></script>
<script>
const presentation = createPresentation('my-presentation', {
customerId: 'your-customer-id',
deckId: 'your-deck-id',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
onStart: () => console.log('Presentation started'),
onEnd: () => console.log('Presentation ended'),
onError: (error) => console.error('Error:', error),
onStateChange: (state) => console.log('State:', state)
});
presentation.start();
</script>NPM Usage (TypeScript/JavaScript)
import { createPresentation } from '@buzztrail-ai/presentation';
import type { PresentationConfig } from '@buzztrail-ai/presentation';
const config: PresentationConfig = {
customerId: 'acme-corp',
deckId: 'product-demo-2024',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
// Optional: Viewer configuration
viewer: {
position: 'center',
showControls: true,
controlsPosition: 'bottom',
aspectRatio: '16:9',
showLoading: true,
loadingMessage: 'Loading presentation...'
},
// Optional: Theme
theme: 'auto', // 'light', 'dark', or 'auto'
// Optional: Lead capture
gating: {
enabled: true,
fields: ['email', 'name']
},
// Lifecycle callbacks
onStart: () => {
console.log('Presentation started');
},
onEnd: () => {
console.log('Presentation ended');
},
onError: (error) => {
console.error('Error:', error);
},
onStateChange: (state) => {
console.log('State changed:', state);
}
};
const presentation = createPresentation('my-container', config);
// Start the presentation
await presentation.start();
// Later: End the presentation
await presentation.end();
// Get current state
const state = presentation.getState(); // 'idle' | 'connecting' | 'connected' | 'disconnected'
// Cleanup
presentation.destroy();Demo Experience
The createDemoExperience() function provides an automated investor demo experience with greeter agent warmup and seamless handoff to presentation.
Features:
- Automatic greeter agent (50-second warmup by default)
- Natural conversation before presentation
- Seamless transition to slide presentation
- Configurable timeline (50s or 20s for testing)
- System defaults for quick setup
Basic Usage:
import { createDemoExperience } from '@buzztrail-ai/presentation';
const demo = createDemoExperience('container', {
// Required
customerName: 'Jane Investor',
customerEmail: '[email protected]',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
});
await demo.start();With Custom Options:
const demo = createDemoExperience('container', {
// Required
customerName: 'Jane Investor',
customerEmail: '[email protected]',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
// Optional
customerCompany: 'Acme Corp',
deckUrl: 'https://example.com/custom-deck',
timelineConfig: 'investor_demo_quick', // 20s handoff for testing
// Callbacks
onHandoff: () => console.log('Transitioning to presentation!'),
onStart: () => console.log('Demo started'),
onEnd: () => console.log('Demo ended'),
});
await demo.start();Timeline Configurations:
investor_demo(default): 50-second greeter warmupinvestor_demo_quick: 20-second warmup for testing
System Defaults:
- Falls back to default investor deck if no
deckUrlprovided - Timeline defaults to
investor_demo(50s)
CDN Usage:
<script src="https://cdn.jsdelivr.net/npm/@buzztrail-ai/[email protected]/index.umd.js"></script>
<script>
const demo = BuzztrailPresentation.createDemoExperience('container', {
customerName: 'Jane Investor',
customerEmail: '[email protected]',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
});
demo.start();
</script>Wix Integration Guide
Wix requires special handling due to iframe permission restrictions. Follow these steps:
Step 1: Add a Container Element
- Open Wix Editor for your site
- Click "Add Elements" (+) → Select "Strip" or "Box"
- Position and size the element where you want the presentation (recommended: 900x600px or larger)
- Right-click the element → "View Properties" → Note the Element ID (e.g.,
comp-mfy88b7h)
Step 2: Add BuzzTrail via Custom Code
- Open Settings → Advanced → Custom Code
- Click "+ Add Custom Code"
- Paste the following code (replace credentials and element ID):
<script src="https://cdn.jsdelivr.net/npm/@buzztrail-ai/presentation@1/buzztrail-presentation.min.js"></script>
<script>
const presentation = createPresentation('comp-mfy88b7h', {
customerId: 'your-customer-id',
deckId: 'your-deck-id',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key'
});
presentation.start();
</script>- Configure the snippet:
- Name: BuzzTrail Presentation
- Add to Pages: Choose "All pages" or specific pages
- Place Code in: Select "Body - end" (recommended)
- Click "Apply"
- Publish your site
Finding the Correct Container ID
Each Wix page element has a unique ID. To find the correct container ID for your page:
- Open your published Wix page in a browser
- Open the browser's Developer Tools (F12 or right-click → Inspect)
- In the Console tab, paste this code and press Enter:
document.querySelectorAll('[id^="comp-"]').forEach(el => {
console.log(`ID: ${el.id}, Size: ${el.offsetWidth}x${el.offsetHeight}px`);
});- Look for a container with dimensions around 900x600px or larger - this is ideal for presentation display
- Copy that container's ID (e.g.,
comp-abc123xyz) and use it increatePresentation()
Why Custom Code (Not Embed HTML)?
- Wix Embed HTML wraps code in an iframe, which blocks camera/microphone permissions
- Custom Code runs directly on the page, allowing proper permissions for voice interaction
- This is the only way to enable voice-interactive presentations on Wix
TypeScript Support
This package includes full TypeScript type definitions. No need to install @types packages.
Type Imports
import type {
// Main API
Presentation,
PresentationConfig,
PresentationState,
// Configuration types
ViewerConfig,
GatingConfig,
ThemeMode,
PresentationThemeConfig,
// Session types
Session,
SessionState,
// Error types
PresentationError,
SessionError,
NetworkError,
BotError,
ConfigError,
ErrorSeverity,
ErrorCategory,
RecoveryStrategy,
} from '@buzztrail-ai/presentation';Example: Type-Safe Configuration
import { createPresentation } from '@buzztrail-ai/presentation';
import type { PresentationConfig, PresentationState } from '@buzztrail-ai/presentation';
const config: PresentationConfig = {
customerId: 'acme-corp',
deckId: 'product-demo',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
// TypeScript will autocomplete and validate these properties
viewer: {
position: 'center', // Type-checked: 'left' | 'center' | 'right'
showControls: true,
aspectRatio: '16:9' // Type-checked: '16:9' | '4:3' | '21:9'
},
theme: 'auto', // Type-checked: 'light' | 'dark' | 'auto'
// TypeScript will autocomplete and validate callbacks
onStateChange: (state: PresentationState) => {
console.log('State:', state); // Type: 'idle' | 'connecting' | 'connected' | 'disconnected'
}
};
const presentation = createPresentation('my-container', config);Configuration
createPresentation Options
interface PresentationConfig {
// Required: Your BuzzTrail customer ID
customerId: string;
// Required: Deck ID to present
deckId: string;
// Required: Supabase project URL
supabaseUrl: string;
// Required: Supabase anonymous key
supabaseKey: string;
// Optional: Backend API base URL (defaults to production)
apiUrl?: string;
// Optional: Viewer configuration
viewer?: ViewerConfig;
// Optional: Theme mode
theme?: ThemeMode; // 'light' | 'dark' | 'auto'
// Optional: Custom theme configuration
themeConfig?: PresentationThemeConfig;
// Optional: Lead capture configuration
gating?: GatingConfig;
// Optional: Customer metadata for session tracking
customerInfo?: {
name?: string;
email?: string;
[key: string]: unknown;
};
// Optional: Enable debug logging
debug?: boolean;
// Optional: Lifecycle callbacks
onStart?: () => void;
onEnd?: () => void;
onError?: (error: Error) => void;
onStateChange?: (state: PresentationState) => void;
}Viewer Configuration
interface ViewerConfig {
// Viewer position in container
position?: 'left' | 'center' | 'right'; // default: 'center'
// Show manual slide controls
showControls?: boolean; // default: false
// Controls position
controlsPosition?: 'top' | 'bottom'; // default: 'bottom'
// Video aspect ratio
aspectRatio?: '16:9' | '4:3' | '21:9'; // default: '16:9'
// Show loading state
showLoading?: boolean; // default: true
// Custom loading message
loadingMessage?: string; // default: 'Loading presentation...'
}Gating Configuration
interface GatingConfig {
// Enable lead capture form
enabled: boolean;
// Fields to collect
fields: Array<'name' | 'email' | 'phone' | 'company'>;
// Form title (optional)
title?: string;
// Form description (optional)
description?: string;
}Theme Configuration
interface PresentationThemeConfig {
// Theme mode
mode: 'light' | 'dark' | 'auto';
// Custom colors (optional)
colors?: {
background?: string;
text?: string;
accent?: string;
border?: string;
};
}API Reference
createPresentation(containerOrId, config)
Create a presentation instance in the specified container.
Parameters:
containerOrId(string | HTMLElement): DOM element or element ID to inject the presentation intoconfig(PresentationConfig): Configuration options
Returns: Presentation instance
const presentation = createPresentation('my-container', {
customerId: 'acme-corp',
deckId: 'product-demo',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key'
});endPresentation(sessionId)
End a presentation by session ID.
Parameters:
sessionId(string): The session ID to end
Returns: Promise<void>
await endPresentation('session-abc123');Presentation Instance
The object returned by createPresentation() has the following methods:
presentation.start()
Start the presentation session. Connects to LiveKit room, spawns bots, and begins the interactive presentation.
Returns: Promise<void>
await presentation.start();presentation.end()
End the presentation session. Disconnects from room, cleans up resources.
Returns: Promise<void>
await presentation.end();presentation.getState()
Get the current presentation state.
Returns: PresentationState - 'idle' | 'connecting' | 'connected' | 'disconnected'
const state = presentation.getState();
console.log(state); // 'connected'presentation.destroy()
Destroy the presentation instance and clean up all resources. Call this when removing the presentation from the page.
Returns: void
presentation.destroy();presentation.sessionId
Read-only property containing the unique session ID.
console.log(presentation.sessionId); // 'session-abc123'Configuration Scenarios
Scenario 1: Basic Presentation (Minimal Config)
const presentation = createPresentation('container', {
customerId: 'acme-corp',
deckId: 'product-demo',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key'
});
await presentation.start();Scenario 2: With Manual Controls
const presentation = createPresentation('container', {
customerId: 'acme-corp',
deckId: 'product-demo',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
viewer: {
showControls: true,
controlsPosition: 'bottom'
}
});
await presentation.start();Scenario 3: With Lead Capture
const presentation = createPresentation('container', {
customerId: 'acme-corp',
deckId: 'product-demo',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
gating: {
enabled: true,
fields: ['name', 'email', 'company'],
title: 'Get Access to Our Product Demo',
description: 'Please provide your information to continue'
}
});
await presentation.start();Scenario 4: Full Configuration with Callbacks
const presentation = createPresentation('container', {
customerId: 'acme-corp',
deckId: 'product-demo',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
apiUrl: 'https://api.buzztrail.ai',
viewer: {
position: 'center',
showControls: true,
controlsPosition: 'bottom',
aspectRatio: '16:9',
showLoading: true,
loadingMessage: 'Preparing your personalized demo...'
},
theme: 'auto',
gating: {
enabled: true,
fields: ['name', 'email']
},
customerInfo: {
name: 'Jane Smith',
email: '[email protected]',
company: 'Acme Inc'
},
debug: true,
onStart: () => {
console.log('Presentation started');
// Track analytics, show UI elements, etc.
},
onEnd: () => {
console.log('Presentation ended');
// Hide UI elements, show follow-up actions, etc.
},
onError: (error) => {
console.error('Presentation error:', error);
// Show user-friendly error message
},
onStateChange: (state) => {
console.log('State changed to:', state);
// Update UI based on state
if (state === 'connected') {
// Show "presentation is live" indicator
}
}
});
await presentation.start();Browser Support
- Chrome/Edge: Latest 2 versions
- Firefox: Latest 2 versions
- Safari: Latest 2 versions
- Mobile browsers: iOS Safari 14+, Chrome Android
Note: Voice interaction requires browser support for WebRTC and getUserMedia API.
Troubleshooting
"Domain not authorized" Error
Solution: Contact BuzzTrail support to authorize your domain. Domain authorization is managed by BuzzTrail admins for security purposes.
Camera/Microphone Not Working
- HTTPS Required: Voice interaction only works on secure (HTTPS) websites
- Wix Users: Use Custom Code (Settings → Advanced), NOT the Embed HTML element
- Browser Permissions: Users must allow microphone access when prompted
- Check Container: Ensure the container element exists before calling
createPresentation()
Presentation Not Appearing
- Check Account: Verify your BuzzTrail account is active
- Check Customer ID: Ensure you're using the correct customer ID from your dashboard
- Check Deck ID: Verify the deck ID exists and is published
- Check Supabase Credentials: Ensure your Supabase URL and key are correct
- Check Container: The HTML element with your container ID must exist on the page
- Check Console: Open browser DevTools (F12) to see any error messages
Slides Not Advancing
- Voice Commands: The AI voice agent controls slides based on conversation flow
- Manual Controls: Enable manual controls with
viewer.showControls: trueif you want user control - Database Connection: Ensure Supabase credentials are correct - slides sync via database
- Network Issues: Check browser console for network errors
Bot Spawn Failures
If you see "Bot spawn failed" errors:
- Check API URL: Verify
apiUrlis correct (or omit to use default) - Check Session Creation: Ensure the session was created successfully
- Check Logs: Enable
debug: trueto see detailed bot spawn logs - Retry: Bot spawning includes automatic retry logic, wait a few seconds
Debugging Slide Control Issues
Enable debug mode to see detailed logs:
const presentation = createPresentation('container', {
customerId: 'acme-corp',
deckId: 'product-demo',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
debug: true // Enable debug logging
});Debug logs will show:
- Session creation
- Bot spawn attempts
- LiveKit room connection
- Slide control commands
- Error details with recovery strategies
Examples
Wix Example (Copy-Paste Ready)
<!-- Add via Wix Settings → Advanced → Custom Code → Body - end -->
<script src="https://cdn.jsdelivr.net/npm/@buzztrail-ai/presentation@1/buzztrail-presentation.min.js"></script>
<script>
// Replace these values with your credentials
const CUSTOMER_ID = 'your-customer-id';
const DECK_ID = 'your-deck-id';
const SUPABASE_URL = 'https://your-project.supabase.co';
const SUPABASE_KEY = 'your-anon-key';
const CONTAINER_ID = 'comp-mfy88b7h'; // Your Wix element ID
const presentation = createPresentation(CONTAINER_ID, {
customerId: CUSTOMER_ID,
deckId: DECK_ID,
supabaseUrl: SUPABASE_URL,
supabaseKey: SUPABASE_KEY,
viewer: {
showControls: true,
aspectRatio: '16:9'
},
onStart: () => console.log('Presentation started!'),
onEnd: () => console.log('Presentation ended!'),
onError: (error) => console.error('Error:', error.message)
});
presentation.start().catch(error => {
console.error('Failed to start presentation:', error);
});
</script>Generic HTML Example (Copy-Paste Ready)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BuzzTrail Presentation Demo</title>
<style>
body {
margin: 0;
padding: 20px;
font-family: Arial, sans-serif;
background: #f5f5f5;
}
h1 {
text-align: center;
color: #333;
}
#presentation-container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
min-height: 600px;
padding: 20px;
}
.status {
text-align: center;
padding: 10px;
margin: 20px auto;
max-width: 400px;
border-radius: 4px;
background: #e3f2fd;
color: #1976d2;
}
</style>
</head>
<body>
<h1>Product Demo Presentation</h1>
<div id="status" class="status">
Initializing presentation...
</div>
<div id="presentation-container"></div>
<!-- Load BuzzTrail Presentation SDK -->
<script src="https://cdn.jsdelivr.net/npm/@buzztrail-ai/presentation@1/buzztrail-presentation.min.js"></script>
<script>
// Configuration
const config = {
customerId: 'your-customer-id',
deckId: 'your-deck-id',
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
viewer: {
position: 'center',
showControls: true,
controlsPosition: 'bottom',
aspectRatio: '16:9'
},
theme: 'auto',
debug: true,
onStart: () => {
updateStatus('Presentation is live!', 'success');
},
onEnd: () => {
updateStatus('Presentation ended. Thank you!', 'info');
},
onError: (error) => {
updateStatus('Error: ' + error.message, 'error');
console.error('Presentation error:', error);
},
onStateChange: (state) => {
console.log('State:', state);
if (state === 'connecting') {
updateStatus('Connecting...', 'info');
} else if (state === 'connected') {
updateStatus('Connected!', 'success');
} else if (state === 'disconnected') {
updateStatus('Disconnected', 'info');
}
}
};
// Helper function to update status
function updateStatus(message, type = 'info') {
const statusEl = document.getElementById('status');
statusEl.textContent = message;
statusEl.style.background = {
success: '#e8f5e9',
error: '#ffebee',
info: '#e3f2fd'
}[type];
statusEl.style.color = {
success: '#2e7d32',
error: '#c62828',
info: '#1976d2'
}[type];
}
// Create and start presentation
const presentation = createPresentation('presentation-container', config);
presentation.start()
.then(() => {
console.log('Presentation started successfully');
})
.catch(error => {
updateStatus('Failed to start: ' + error.message, 'error');
console.error('Failed to start presentation:', error);
});
// Cleanup on page unload
window.addEventListener('beforeunload', () => {
presentation.destroy();
});
</script>
</body>
</html>Changelog
See CHANGELOG.md for version history.
License
Proprietary - BuzzTrail AI
Built with TypeScript • AI-Powered Presentations • Made for modern web platforms
