7K3M9Q3 onlineB2W8XRIdlePush your screen to everyone in the room — with OBS, or with nothing but a browser. Each room is bound to its own LiveKit credentials, so its media traffic and free tier burn on that node and nobody competes for anyone else's.
7K3M9Q3 onlineB2W8XRIdleQF4L2N1 onlineM9ZP6T5 onlineA room lives on exactly one node — its traffic and its free tier are charged there.
The browser route touches this site exactly once — to get a token; after that the video goes straight to LiveKit. The OBS route needs an ingress created on the server first. That's why turning off "OBS publishing" leaves browser sharing working.
One click, nothing to install. 1920×1080@15fps — desktop sharing favours resolution over frame rate. The video passes through neither Vercel nor Ingress.
In the room, click "Generate publish URL", then put the Server and Bearer Token into OBS's stream settings (service: WHIP). Passthrough means no transcoding, so it barely touches the machine and never eats the 60-minute quota.
LiveKit Cloud's free Build plan is metered per project; over the limit, requests simply fail and nothing is billed — and multiple free projects on one account share a single allowance.
| Publish bitrate | Viewer minutes on 50 GB | In viewer hours |
|---|---|---|
4 Mbps1080p high bitrate | 1,667 | ≈ 28 h |
2.5 Mbps1080p typical | 2,667 | ≈ 44 h |
1.5 Mbps720p | 4,444 | ≈ 74 h |
0.8 MbpsLow bitrate | 5,000 | ≈ 83 h |
About 1.33 Mbps is the dividing line: above it the 50 GB of bandwidth runs out first, below it the 5,000 minutes do. Viewer hours still get divided by the number of viewers — one person sharing to three at 1080p is roughly 15 hours a month.
So this project makes nodes a first-class citizen: everyone connects their own project, and the allowance goes from "one for the whole site" to "one each". The built-in node is only there as a fallback — remember to cap its room count.
A check you can bypass in the client is not a check. All of the following happen where tokens are signed and ingresses are created.
Not in the member table → no token → no connection → no track subscription. The grant's room field holds exactly one room name, so the token physically cannot open another one. Non-members always get a 404, so a room code reveals nothing.
Connect your own LiveKit Cloud project and pick which set to use per room. Before saving, this site runs a real API health check with those credentials — wrong ones are never stored — and it also probes whether Ingress works and marks that on the node.
enableTranscoding: false — it doesn't eat the 60 transcode minutes a month. One publish URL per person, rotatable and revocable; stream keys are encrypted at rest and only decrypted back to their owner.
When the owner turns it off, anything currently publishing drops: the ingress is deleted so old keys can never connect again, and the obs: participant is removed from the room. Not a flag that says "off" while the stream keeps flowing.
The owner opens a player and the whole room watches the same source. Position is broadcast over LiveKit's data channel, aligned after estimating the clock offset between machines with ping/pong; video bytes never touch this service.
Only the hash of a token is stored; links can carry an expiry, a usage cap, and be revoked at any time. Redemption claims a slot atomically with a conditional UPDATE, so concurrency can't punch through max_uses; opening one while signed out routes through sign-in and then joins automatically.
DATABASE_URL and ADMIN_PASSWORD. The admin account is created on first start, the credential encryption key generates itself into the database if unset, and LiveKit is configured in the web UI rather than in env vars. There is no install wizard.
Rooms have an expandable audit log (it never records a secret). /api/health needs no sign-in and reports item by item: database reachability, whether all 12 tables exist, whether bootstrap ran — it lists exactly which tables are missing so you don't have to guess from a stack trace.
This site ships no media server, so all you really need is a database and one set of LiveKit credentials.
Copy .env.example to .env.local — Next doesn't read the former, so editing the wrong file does nothing at all.
DATABASE_URL=postgresql://…@ep-xxx-pooler…/neondb?sslmode=require ADMIN_PASSWORD=pick-your-own-password
npm install npm run db:migrate # creates 12 tables npm run dev
Then sign in with admin@localhost and the password above: the admin account is created on first start, and there is no install wizard. On Vercel the migration is already wired into the build, so you don't run this by hand.
Sidebar "LiveKit nodes" → "Connect a node", then fill in the wss:// URL and the API Key / Secret. LiveKit Cloud's free Build plan needs no card and takes about three minutes to get those three values; before saving, this site verifies them for real and refuses to store wrong ones.
Self-hosted LiveKit works too (the URL field accepts ws://), but publishing from OBS then requires deploying Ingress and Redis yourself.
Self-hosted, end-to-end encrypted chat that can also share your screen — this site is only the screen half; the chat half can't be done cleanly in a browser.
Every answer below can be traced to the code or the README. For anything not covered here, use the two links in the previous section.
ws://, but publishing from OBS then means deploying Ingress and Redis yourself.getDisplayMedia, 1920×1080@15fps — desktop sharing favours resolution over frame rate). The OBS route is for people who want multiple scenes, transitions and overlays; it uses WHIP passthrough and eats no transcode quota.obs: participant from the room. It is not a flag that flips the label to "off" while the stream keeps flowing. Browser sharing is a separate route and is unaffected.CREDENTIAL_ENCRYPTION_KEY. No endpoint returns a plaintext secret; the admin UI shows a mask.Signing up gives you your own workspace, where you can connect your own LiveKit nodes. If you were sent an invite link, just open it and sign in — you'll join the room automatically.