Send files directly to another browser. No accounts, no cloud storage, no size-gouging, no ads. Two people, a pair of 64-character codes, and an end-to-end encrypted connection between them.
YOU PEER
┌─────────────┐ ┌─────────────┐
│ your code │╌╌╌╌╌ bond ╌╌╌╌╌╌╌╌╌╌│ their code │
└─────────────┘ └─────────────┘
│ │
└──────── encrypted transfer ────────┘
(direct when possible, streamed
through the relay when it isn't)
- One page, one action. Load the site and you get a fresh 64-character code. Give it to someone (or paste theirs in) and you're bonded.
- Send up to 500 files, 10 GB total, per batch. No folders, drop individual files. Send another batch right after if you need to.
- End-to-end encrypted. Every file chunk is encrypted in your browser with a key your peer's browser derives independently. The server never sees a key, a filename, or a byte of plaintext, see docs/SECURITY.md.
- Real peer-to-peer when your networks allow it. The app tries a direct WebRTC connection first, so in the best case your files never touch the server at all. When a direct route isn't possible, it falls back to a streaming relay that never buffers more than a small, fixed window of a transfer, see docs/ARCHITECTURE.md.
- Nothing stored. No database, no file ever touches a disk on the server, no accounts, no logs of who sent what to whom, see docs/PRIVACY.md.
- Free and open source, licensed AGPL-3.0. Run the public instance or self-host your own, see docs/DEPLOY.md.
- Load the page. The server hands you a random 64-character code and holds a WebSocket connection open for you.
- Give your code to someone, or type in theirs. Whoever's code gets entered by the other person, both sides get notified they're bonded.
- Both browsers generate a one-time encryption keypair, swap public keys through the server (which never sees the private halves), and attempt a direct WebRTC connection.
- Pick files, hit Send. Your peer sees an incoming-transfer prompt and hits Receive. Bytes start flowing, encrypted, chunked, and either straight between your browsers or streamed through the relay.
- Refresh the page, close the tab, or lose your connection, and the bond is gone. Nothing persisted; nothing to clean up.
For the full technical picture (the wire protocol, the encryption scheme, why chunking and backpressure exist, and the deliberate tradeoffs), read docs/ARCHITECTURE.md.
pear-to-pear/
├── client/ Svelte + TypeScript + Vite single-page frontend
├── server/ Node.js + TypeScript signaling & relay server
└── docs/ Everything below
Requires Node.js 20 or newer.
# terminal 1: signaling/relay server
cd server
npm install
cp .env.example .env
npm run dev # http://localhost:8787
# terminal 2: frontend
cd client
npm install
cp .env.example .env # point VITE_SIGNALING_URL at the server above
npm run dev # http://localhost:5173Open two browser windows (or a normal window plus a private one) at
http://localhost:5173 to try bonding two "peers" against yourself.
cd client && npm install && npm run build # outputs client/dist
cd ../server && npm install && npm run build # outputs server/dist
cd server && STATIC_DIR=../client/dist npm start(Or, as a shortcut from the repo root: npm run install:all && npm run build.)
The server can serve the built client itself (as above) or you can host
the static client/dist output separately (a CDN, static hosting, etc.)
and point it at the signaling server via VITE_SIGNALING_URL. Full,
detailed self-hosting instructions, including Docker, systemd, and
reverse-proxy configuration, are in docs/DEPLOY.md.
Full documentation lives in docs/. Start at
docs/README.md for a guide to what's there and where
to look first.
AGPL-3.0. Pear-to-Pear is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The Affero clause matters here specifically because this is server software: if you run a modified version of it for others to use over a network, the AGPL requires you to make your modified source available to them too.