Real-time stage monitoring system for theater and stage crews.
Stage Link is a multi-tenant web app that provides real-time video monitoring for live productions. A host (stage manager or director) broadcasts a camera feed; crew members watch it from anywhere to stay coordinated during a performance. Access is organized around teams — each company or production is a Clerk organization, and what a member can do is gated by their role.
- Live video streaming — low-latency WebRTC, routed through a Cloudflare Realtime SFU
- Host control panel (
/host) — start/manage the broadcast and stream settings - Viewer interface (
/viewer) — clean, responsive feed for crew - Organizations & roles — admin, stage manager, and a host permission control access per org
- Billing — tiered plans (Crew, Production, Showtime) via Clerk billing
- Stream statistics — FPS, resolution, quality, and latency
- Responsive design and theme customization
- Framework: Next.js 16 (App Router) + React 19
- Auth & multi-tenancy: Clerk (organizations, roles/permissions, billing)
- Realtime signaling: PartyKit (
partysocket) - Video transport: WebRTC over a Cloudflare Realtime SFU (Calls API), with Cloudflare TURN for NAT traversal
- Styling: Tailwind CSS v4 + shadcn/ui (Radix UI)
- Hosting: Vercel
- Package manager: npm (PartyKit deployed separately)
| Route | Purpose | Access |
|---|---|---|
/ |
Landing page | Public |
/host |
Broadcast control panel | Admin, stage manager, or org:stream:host permission |
/viewer |
Watch the live feed | Any member of an org |
/org-select |
Choose/switch active organization | Authenticated |
/org-settings |
Manage the organization | Org admin only |
/pricing |
Plans and billing | Authenticated |
/sign-in, /sign-up |
Authentication | Public |
Route protection lives in src/proxy.ts (Next.js Proxy convention, formerly middleware.ts), backed by Clerk.
- Node.js 18+ (Node 24 LTS recommended)
- A Clerk application with organizations and billing enabled
- A Cloudflare Realtime app (for the SFU) and a TURN key
- A PartyKit project for signaling
- A webcam for hosting
-
Clone and install:
git clone [repository-url] cd stage-link npm install -
Create
.env.local(see.env.example) and provide:# Clerk NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= CLERK_SECRET_KEY= # Clerk billing plan IDs NEXT_PUBLIC_PLAN_ID_CREW= NEXT_PUBLIC_PLAN_ID_PRODUCTION= NEXT_PUBLIC_PLAN_ID_SHOWTIME= # PartyKit signaling host NEXT_PUBLIC_PARTY_HOST= # Cloudflare Realtime (SFU) CALLS_APP_ID= CALLS_APP_SECRET= # Cloudflare TURN TURN_KEY_ID= TURN_KEY_API_TOKEN= # Site NEXT_PUBLIC_SITE_URL=
-
Run the app:
npm run dev
The app runs at
http://localhost:3000. -
Run the PartyKit signaling server (separate process):
npm run party:dev
- Sign in and select your organization (
/org-select). - Go to
/host(requires admin, stage manager, or host permission). - Configure the camera and start the broadcast.
- Sign in as a member of the organization.
- Go to
/viewerto watch the live feed.
- App: deploy to Vercel (
next build). Set all environment variables in the Vercel project. - Signaling: deploy the PartyKit server with
npm run party:deploy.
| Script | Description |
|---|---|
npm run dev |
Start Next.js (Turbopack) on 0.0.0.0 |
npm run build |
Production build |
npm run start |
Run the production build |
npm run lint |
ESLint |
npm run party:dev |
Run the PartyKit signaling server locally |
npm run party:deploy |
Deploy the PartyKit signaling server |
MIT
Created by Christian Furr.