Self-hosting
Run it locally
Serve a checkout of Pooled from your own machine, with an optional local signaling server.
Pooled is a static site: plain HTML and JavaScript modules, with no build step. Any static server works, as long as it applies two rewrites.
Serve a checkout
Section titled “Serve a checkout”git clone https://github.com/Nehanth/pooled && cd poolednpx -y serve -l 8080 .Open http://localhost:8080/room. npm run serve runs the same command.
serve reads serve.json for the rewrites:
{ "rewrites": [ { "source": "/room", "destination": "/p2p.html" }, { "source": "/r/:code", "destination": "/p2p.html" } ]}Production uses the same two rewrites in vercel.json, so keep the two files in step.
Using another server
Section titled “Using another server”If you use nginx, Caddy or something else, map /room and /r/<code> to /p2p.html. For example, with Caddy:
:8080 { root * /path/to/pooled rewrite /room /p2p.html rewrite /r/* /p2p.html file_server}Signaling
Section titled “Signaling”A local checkout uses the public PeerJS server by default, the same as pooled.run. That works from localhost. To keep everything on your machine, run a local PeerServer and point the room at it:
npx peer --port 9000 --path /http://localhost:8080/room?signal=127.0.0.1:9000On an http page a bare host:port uses ws://. ?signal= opens the room in dev mode; add &dev=0 if you don’t want that. Every device must use the same server. See Signaling servers.
What still comes from the internet
Section titled “What still comes from the internet”The page still loads PeerJS from cdn.jsdelivr.net, model files from Hugging Face (unless a device in the room has them), and STUN from Google’s public servers. Browser caches are per site, so weights cached on pooled.run download again on your origin (and localhost and 127.0.0.1 are different sites).
Other devices on your network
Section titled “Other devices on your network”WebGPU needs a secure context. http://localhost counts; http://192.168.1.20:8080 on another device does not, so that device gets no GPU and can only ask.
Serve the checkout over https with a certificate the devices trust, for example Caddy with a real domain name. Then run the signaling server behind TLS too: an https page can only open wss://. See Put it behind TLS.
Keep the computers on their own checkout at http://127.0.0.1:8080/room, and open https://pooled.run/room on phones. Use the public PeerJS server on every device (don’t add ?signal=), so they all meet on the same server.
Run the same commit as pooled.run (main) so both speak the same room protocol.
On Chrome for desktop and Android, chrome://flags/#unsafely-treat-insecure-origin-as-secure lets you list http://192.168.1.20:8080 as secure. Use it only on test devices.
Code mode previews
Section titled “Code mode previews”Previews run on a second site so a runaway app can’t freeze the room. Locally that is the other loopback name (localhost ↔ 127.0.0.1), with nothing to set up. On a LAN address there is no second site, so previews run in the room’s tab and run_js is off.
Next steps
Section titled “Next steps”- Run the tests: see Testing. Many of them need no GPU.
- Deploy your copy: see Deploying the site.