A real-time video broadcasting application built with WebRTC, Cloudflare Workers, and XState state machines. Experience multi-participant video calls with seamless screen sharing capabilities.
π Live Demo: https://calls.nivekithan.com/
π State Machine Visualization: View XState Machine
- Real-time Video Broadcasting: Share your webcam feed with multiple participants in real-time
- Screen Sharing: Broadcast your screen to all participants with a single click
- Adaptive Video States: Pause/resume video broadcasting with automatic peer notification
- Room Synchronization: Automatic syncing of participants joining and leaving
- Featured Stream View: Click any participant to view them in full-screen mode
- Permission Management: Intelligent camera permission handling with user-friendly UI
- State Machine Architecture: Complex state management powered by XState v5
- Real-time Signaling: WebSocket-based signaling using Cloudflare Durable Objects
Frontend (web/)
- React Router v7: Full-stack React framework with SSR
- XState v5: Type-safe state machines for complex UI flows
- WebRTC: Browser-native peer-to-peer video/audio streaming
- Tailwind CSS + shadcn/ui: Modern UI components and styling
- Neverthrow: Functional error handling
- OpenTelemetry: Distributed tracing with Honeycomb integration
Backend (backend/)
- Cloudflare Workers: Edge compute platform
- Durable Objects: Stateful serverless coordination
- Drizzle ORM: Type-safe SQL with SQLite
- Hono: Lightweight web framework
- PartyServer: WebSocket abstraction layer
- Cloudflare Calls API: WebRTC infrastructure
Shared (packages/signaling-messages/)
- Zod: Runtime type validation for WebSocket messages
- Type-safe message schemas shared between client and server
The application uses a complex XState state machine to manage:
- Permission states (granted, denied, pending)
- Broadcasting states (camera, screen share, remote tracks)
- Room synchronization with version-based conflict resolution
- WebRTC connection lifecycle
Main states:
determiningPermission β permissionGranted/Denied/Pending
β joiningRoom
β broadcasting (parallel states):
- localTracks: broadcastVideo β· pauseVideo
- screenShareTracks: noScreenShare β· screenShare
- remoteTracks: syncWithRoom β· roomInSync
Durable Object that manages:
- Track registration (video/screen share)
- Participant lifecycle
- Room state versioning
- Real-time signaling between peers
Uses Cloudflare Calls API for:
- Session management
- SDP offer/answer negotiation
- Track publishing and subscription
- ICE candidate handling
- Node.js 20+
- pnpm 9.1.1+
- Cloudflare account (for deployment)
# Clone the repository
git clone <repository-url>
cd fireside-events
# Install dependencies
pnpm install# Start all services (recommended)
pnpm dev
# or with Turbo TUI
turbo dev --ui tui
# Start frontend only
cd web
pnpm dev
# Start backend only
cd backend
pnpm devBackend (.env in backend/)
JWT_SECRET=<your-jwt-secret>
CALLS_APP_SECRET=<cloudflare-calls-app-secret>cd web
pnpm typecheckcd backend
pnpm test
# Run specific test
pnpm test -- -t "test name"fireside-events/
βββ backend/ # Cloudflare Workers backend
β βββ migrations/ # Drizzle ORM migrations
β β βββ roomManager/ # Room state migrations
β βββ src/
β β βββ features/
β β β βββ broadcast/ # Broadcasting logic
β β β βββ roomManager/ # Durable Object for room state
β β β βββ callsProxy.ts # Cloudflare Calls API client
β β β βββ signaling.ts # WebSocket signaling (deprecated)
β β βββ index.ts # Worker entry point
β β βββ server.ts # Hono HTTP routes
β βββ wrangler.toml # Cloudflare configuration
β
βββ web/ # React Router frontend
β βββ app/
β β βββ components/ui/ # shadcn/ui components
β β βββ lib/
β β β βββ features/
β β β βββ broadcast/
β β β βββ state.ts # XState machine
β β β βββ signaling.ts # WebSocket client
β β β βββ calls.ts # Calls API integration
β β β βββ rtc.ts # WebRTC utilities
β β βββ routes/
β β βββ home.tsx # Main broadcasting UI
β βββ wrangler.toml # Frontend deployment config
β
βββ packages/
βββ signaling-messages/ # Shared WebSocket message types
βββ message.ts # Zod schemas
cd backend
pnpm deploycd web
pnpm deploy- User lands on the page
- App checks camera permissions
- If granted, requests media stream
- If pending, shows permission prompt
- Creates a new Cloudflare Calls session
- Establishes RTCPeerConnection
- Publishes local video track via SDP negotiation
- Connects to Room Manager Durable Object via WebSocket
- Room Manager tracks all participants and their video/screen tracks
- Each state change increments a version number
- Clients poll for version changes
- On version mismatch:
- Fetches latest tracks from other peers
- Negotiates new SDP offers/answers
- Subscribes to new remote tracks
- Local video displayed in grid
- Remote tracks appear as they're published
- Click any stream for full-screen view
- Toggle video on/off (sends pause/resume signals)
- Start screen share (adds additional track)
- WebSocket messages notify peers of:
- Video pause/resume states
- Room version changes (poke)
- New participants joining