Skip to content
JeffreyHamilton6399Public

About

Beam files between any two devices — peer-to-peer. No uploads, no sign-up, no size limits.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

FileBeam

Open it on two devices. One picks files and gets a 6-digit code and a QR. The other enters the code or scans it. The files stream straight between the two over a WebRTC data channel.

Works iPhone to Android to Windows to Mac to Linux, across networks. The two devices don't need to be on the same Wi-Fi.

The shape of it

Device A (sender)  ◄──── WebRTC data channel ────►  Device B (receiver)
        │                                            │
        └────── signaling relay (6-digit code) ──────┘
                    handshake only
  1. Sender picks files, gets a 6-digit code and a QR.
  2. Receiver enters or scans it. The WebRTC handshake goes through the relay.
  3. Sender sends file metadata over the data channel; the receiver accepts.
  4. Files stream in 16 KiB chunks, device to device.
  5. Channel closes, signaling room is abandoned.

Files are read with file.stream() and sent in 16 KiB chunks, so memory stays flat no matter how big the file is. There is no size cap.

What the signaling server does and doesn't see

It carries the 6-digit code and the WebRTC SDP/ICE exchange between two peers. A few KB, once, at the start. It never sees file bytes, file names, or sizes, and nothing is stored on it. Rooms are ephemeral and destroy themselves on disconnect.

The 6-digit code gives a million possibilities against a room that exists for the length of one handshake. Transfers themselves are encrypted by WebRTC's DTLS, which is part of the protocol rather than something bolted on.

Running it

Needs bun.

bun install
bun run dev

The signaling server starts inside the Next.js dev process via src/instrumentation.ts, so there's no second process to run. Open two tabs, send from one, receive in the other.

NAT traversal uses public STUN servers. On a restrictive network (symmetric NAT) you'll need a TURN server added to ICE_SERVERS in src/lib/filebeam/signaling.ts.

Built with

Next.js 16 (App Router), TypeScript, Tailwind CSS 4, shadcn/ui, RTCPeerConnection and a data channel for the transfer, and socket.io for signaling.

Deploying

Two pieces: the frontend on Vercel, and the signaling relay somewhere it can hold a socket. Files always go peer to peer regardless.

Signaling relay. It's a ~130-line socket.io app in mini-services/signaling/. On Render: New → Web Service → Public Git repository → https://github.com/JeffreyHamilton6399/filebeam, with root directory mini-services/signaling, build npm install, start npm start. You get back a URL like https://filebeam-signaling.onrender.com.

It's stateless, so a free tier is fine. Render's free tier sleeps after 15 minutes idle, which costs a one-second cold start on the first connection.

Frontend. Import the repo on Vercel, set NEXT_PUBLIC_SIGNALING_URL to the relay URL, deploy.

Local development needs none of this.

Privacy

Files go directly between devices. The relay sees only the code and the handshake. Nothing is stored on any server, there's no analytics, and localStorage holds a theme preference and nothing else.

Contributing

PRs welcome against main. Run bun run lint first.

License

MIT © Jeffrey Hamilton

About

Beam files between any two devices — peer-to-peer. No uploads, no sign-up, no size limits.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages