This example demonstrates how to create a custom meeting UI using Cloudflare RealtimeKit with vanilla HTML, CSS, and JavaScript. It showcases custom components for setup screen, in-meeting experience, control bar, sidebar, and media preview functionality.
- Custom Setup Screen: Participant preview with media settings
- Media Preview Modal: Audio and video device selection with preview
- Custom Control Bar: Meeting controls with custom sidebar toggle
- Custom Sidebar: Standard tabs (chat, participants, polls, plugins) plus custom "warnings" tab
- Custom Meeting Header: Logo, indicators, meeting title, and controls
- Responsive Design: Built with Tailwind CSS for modern UI
- State Management: Uses simple reactive state implementation
- No Build Steps: Pure HTML/CSS/JS implementation
- A valid Cloudflare RealtimeKit auth token
- A local web server (like
serveorlive-server)
- Clone or download this repository
- Navigate to the
html-examplesdirectory - Install dependencies (optional, for development server):
npm install
-
Start a local server:
npx serve examples/create-your-own-ui
-
Open your browser and navigate to:
http://localhost:3000/?authToken=<your-auth-token>Replace
<your-auth-token>with your actual Cloudflare RealtimeKit auth token.
create-your-own-ui/
├── index.html # Main HTML file
├── store.js # Simple reactive state management
├── utils.js # Utility functions
├── types.js # Type definitions
├── components/ # Component files
│ ├── setup-screen.js/css # Custom setup screen
│ ├── custom-rtk-meeting.js/css # Main meeting wrapper
│ ├── in-meeting.js/css # In-meeting layout
│ ├── meeting-header.js/css # Meeting header
│ ├── meeting-control-bar.js/css # Control bar
│ ├── meeting-sidebar.js/css # Custom sidebar
│ ├── media-preview-modal.js/css # Media preview
│ ├── audio-preview.js/css # Audio device preview
│ └── video-preview.js/css # Video device preview
└── README.md # This file
- Participant tile with avatar and name tag
- Audio visualizer
- Mic/camera toggles
- Media preview modal access
- Name editing (if permitted)
- Join button
- Tabbed interface for audio/video settings
- Device selection dropdowns
- Audio visualizer for microphone
- Video preview tile
- Speaker test functionality
- Left: Fullscreen, settings, screen share
- Center: Mic, camera, stage, leave, more menu
- Right: Chat, polls, participants, plugins, custom sidebar toggle
- Standard RTK tabs: chat, participants, polls, plugins
- Custom "warnings" tab with example content
- Responsive design
- Create
.jsand.cssfiles in thecomponents/directory - Add script and link tags to
index.html - Implement the component using the module pattern
- Ensure proper cleanup in the component's cleanup function
- Use
window.StatesStore.statesStorefor RTK states - Use
window.StatesStore.customStatesStorefor custom states - Subscribe to state changes using
window.StatesStore.subscribe()
- Uses Tailwind CSS via CDN
- Component-specific styles in individual CSS files
- Dark theme with consistent color scheme
- Cloudflare RealtimeKit: Core meeting functionality
- Cloudflare RealtimeKit UI: Pre-built UI components
- Simple Reactive State: Custom reactive state implementation
- Tailwind CSS: Utility-first CSS framework
All dependencies are loaded via CDN, no build process required.
This example works in modern browsers that support:
- ES6 modules
- Custom elements
- WebRTC
- Modern CSS features
- Auth Token Error: Ensure you're passing a valid
authTokenin the URL - Components Not Loading: Check browser console for script loading errors
- State Not Updating: Verify reactive state subscriptions are properly set up
- Media Devices: Ensure browser permissions for camera/microphone access
The meeting object is exposed on window.meeting for debugging purposes. Open browser dev tools and inspect the meeting object to troubleshoot issues.
If components aren't updating when states change, ensure you're subscribing to the store object, not the nested states:
- ✅
window.StatesStore.subscribe(statesStore, callback) - ❌
window.StatesStore.subscribe(statesStore.states, callback)
This example is provided as-is for demonstration purposes.