BYOC turns a browser tab into a small real-time server. One person hosts from their tab, friends open a link, and everyone connects peer to peer. No backend to write, nothing to deploy, no account. The LAN party for the web.
Call host() and you get a link. The room's logic runs right there in that tab, the way a game server would.
Their tab calls connect() and gets a WebSocket-like connection to the host. Chat, moves, cursors, files: whatever you send.
Introductions, NAT traversal, fallbacks, reconnecting after reloads, and errors that say what went wrong in plain English.
The operator only makes introductions. After that, the app's traffic goes straight between browsers.
The secret in the link never leaves the browsers, so the operator relays sealed envelopes it can't read.
Messages go browser to browser over an encrypted WebRTC data channel. The host signs its end, so nobody can sit in the middle.
Peer to peer, found with STUN. Fastest, and nothing in between.
Still WebRTC, bounced off a TURN server. Encrypted end to end.
The operator's WebSocket relay. It only ever sees ciphertext, and upgrades to direct when it can.
Most of the web happens on platforms: everyone connects to someone else's servers, and whatever you say lives there. BYOC is an attempt to bring back something closer to a physical place. We're still connected over the web, but a room has local properties: it belongs to the person hosting it, it exists while they're there, and what happens in it stays between the people in it.
The room runs in the host's tab. Close it and the lights go off. Nothing keeps running somewhere you can't see.
The link is the key, and its secret never touches a server. Only people you hand it to can find the door.
Presence is built in. People arrive, are there, and leave, and everyone notices within seconds.
Messages go person to person. There's no central copy to leak, sell, or train on, unless someone in the room saves one.
A handful of people, not an audience. Small enough that the host's own computer is plenty.
The host runs the room's code and decides who's welcome. It's their place, the way a living room is.
Less like visiting a website, more like going over to a friend's place, even when they're on the other side of the world.
Any static host works, or localhost. The same page is the host or a guest, depending on the link:
<script type="module">
import { host, connect } from 'https://byoc.infinitefun.com/v0/byoc.js';
if (location.hash.includes('byoc=')) {
// Guest: the link is in the URL
const conn = await connect();
conn.onmessage = (e) => console.log(e.data);
conn.send('hi!');
} else {
// Host: this tab is the server
const room = await host();
room.onconnection = (conn) => {
conn.onmessage = (e) => room.broadcast(e.data); // your room logic
};
console.log('Share this link:', room.link);
}
</script>
A Connection works like a WebSocket
(send, onmessage, onclose,
readyState), so WebSocket code ports with few changes.
The whole API fits on one page: llm.md.
Building with an AI assistant? Point it at /llms.txt.
Each one is a single HTML file you can read in a few minutes. Open one, then send the link to a friend or open it on your phone.
A little chat room with who's-here, backlog for late arrivals, and a history that survives the host reloading.
Open a room →Draw together with live cursors. The host keeps the drawing and catches up anyone who arrives late.
Start drawing →A whole early-2000s desktop where every app is peer to peer: TetriNET, Winamp and SHOUTcast, FTP, AIM, watch parties.
Boot it up →Checks the operator, WebRTC, and the direct and TURN paths from this browser. Takes about five seconds.
The protocol, operator and SDK work end to end and are tested in Chromium, Firefox and WebKit. Expect rough edges.
| What | Where |
|---|---|
| SDK (ES module, ~19 KB gzipped, no dependencies) | https://byoc.infinitefun.com/v0/byoc.js |
| Public operator (the default) | wss://api-byoc.infinitefun.com/v1, with STUN and TURN at api-byoc.infinitefun.com |
| API reference | /llm.md, /llms.txt |
| Wire protocol | /protocol.md |
The public operator is free and rate-limited, with no uptime promise
yet, and its TURN and relay are capped. You can run your own operator
and pass host({ operators: ['wss://your-operator/v1'] }).