The first time someone hits one of my p2claw apps their browser opens a peer-to-peer connection to the mac mini in my basement, through their NAT and through mine, and starts speaking HTTP over a WebRTC data channel. Once the connection is established there's no server in between.
Here's how it works.
The setup
I've got an app running on my mini at localhost:3000, the agent may have kicked it off with something like npm run start & or equivalent. It doesn't matter we just need something listening on localhost. I also have a small daemon running on the mini that I installed via the p2claw skill, we call this daemon the box agent. The box agent does four things:
- Generates a keypair on first run. The public key is my "peer ID." Everything that identifies my box as mine flows from this.
- Registers with the p2claw coordination service, which assigned me the subdomain purplecrab.p2claw.com
- Opens a long-lived control connection to the coordination service so it can be told when someone wants to talk to it.
- Exposes port 3000 and gives the app a name. This makes it available at dog-purplecrab.p2claw.com. The name of the exposed app is sent over the control connection so the service can route.
That's the steady state. The box is online, has an identity, is reachable for handshakes, it exposes apps.
What happens when someone visits
Now my wife taps the link to the app from her phone via sim:
- DNS. Her browser resolves dog-purplecrab.p2claw.com. It points at our edge which handles TLS termination for the parent domain.
- Edge serves a bootstrap. The edge doesn't know anything about the dog app. What it knows is "this is a peer subdomain, return the bootstrap." The bootstrap is a tiny HTML page with about 50KB of JS. The bootstrap is the same for every p2claw URL. Static, public, identical for everyone.
- Bootstrap parses the URL. From dog-purplecrab.p2claw.com, it extracts the alias (purplecrab) and the app name (dog). It calls a small endpoint on our coordination service: "I want to talk to peer purplecrab."
- Signaling. The coordination service notifies my mini (via the control connection) that someone wants to connect. It also gives my wife's browser TURN info in case the direct path fails. Both sides start exchanging WebRTC handshake messages, SDP offers and answers, ICE candidates, through the coordination service. The coordination service is just a relay for these blobs.
- Hole-punching. Each side has a list of possible network addresses where the other might be reachable. They start firing UDP packets at each other simultaneously. With high probability, both NATs see outbound packets first, open mappings, and then accept the inbound packets that follow. Most of the time on residential connections, this just works. When it doesn't, traffic falls back through a TURN relay (we use Cloudflare's), which forwards encrypted bytes it cannot read.
- WebRTC data channel opens. Now my wife's browser and my mini have a reliable, ordered, encrypted byte stream between them. Think of it as a TCP socket that happens to traverse NATs. WebRTC handles encryption automatically with DTLS; the keys are negotiated peer-to-peer.
- But what happens when the app makes a request back to the server? We need something to intercept and route these through webrtc. The bootstrap installs a Service Worker scoped to dog-purplecrab.p2claw.com. Then it reloads the page.
- Reload navigates "into" the app. Her browser tries to fetch dog-purplecrab.p2claw.com/. The Service Worker intercepts the fetch. Instead of going to the network, it sends an HTTP-shaped frame over the WebRTC data channel: "GET /, here are my headers."
- The box translates and serves. On my mini, the box agent receives the frame, makes a local HTTP request to localhost:3000/, gets the response, frames it, sends it back over the data channel. The app on :3000 doesn't know anything about p2claw it's just a regular web app.
- Service Worker returns the response. The browser thinks it just made a normal HTTP request. React renders. The dog app loads.
Subsequent fetches [JS bundles, for /api/puppy/name, for an image] get intercepted the same way. The whole app behaves as if served from a normal origin. The transport underneath is a WebRTC data channel running over hole-punched UDP between my computer and her phone.
The economics
Here's why this matters beyond the technical novelty. In the conventional app hosting model [Vercel, Netlify, Cloudflare Tunnel, etc.] every byte of your app's traffic flows through the host's infrastructure. They pay for that bandwidth. As your app gets popular, their costs go up linearly. This is why every host has bandwidth caps, fair-use policies, and overage bills.
p2claw doesn't have this property. The data flows from the visitor's browser to your box, directly, over your residential ISP's bandwidth (which you're paying for anyway), or through your VPS's network [Hetzner VPSs give up to 20TB of free egress!]. Our infrastructure serves a bootstrap, brokers the handshake, and that's it. Our cost per active app is low and fixed. This makes permanent free URLs a thing. From an economics perspective p2claw's architecture is closer to Tailscale which can also support N free VPNs because of the way its costs are structured.
What our infrastructure sees and doesn't
If privacy is important to you:
- The edge sees: the bootstrap fetch (static, public, identical for everyone). No app code, no app data.
- The coordination service sees: signaling metadata. Which peer is connecting to which, when, how often. Not the contents.
- TURN (used in a small % of sessions): encrypted bytes it cannot decrypt. The DTLS keys are between the two endpoints; TURN is a dumb pipe.
- The visitor's browser, the visitor's network, your network, your box: the actual traffic. Encrypted in transit, decrypted only at the endpoints.
Because of the architecture, we couldn't read your app traffic if we wanted to.

LOL, the future
WebRTC has been in browsers since 2013. Service Workers since 2014. Hole-punching since the early 2000s. TURN since forever.
We associate webrtc with video calls. Service workers were built for offline apps. We think of NAT punch through in relation to BitTorrent and games.
The pieces have all been there for a while, p2claw just brings them together suit the needs of AI coding agents or the modern vibecoder.
In the words of Justin Uberti [one of the creators of webrtc] on x.com last week:
LOL, the future is hard to predict.

So that's what p2claw is, a thing that uses a bunch of standards slightly off-label to give us: standard web apps talking to standard browsers, with no install for the visitor, via a peer-to-peer data path, with permanent URLs, for free.