Hrishikesh Sonawane

legen-dary

Building a Peer-to-Peer File Sharing App with WebRTC and Firebase

In June 2025, I built a browser-based peer-to-peer (P2P) file sharing application that enables users to transfer files directly between devices without routing them through a server. The project combines WebRTC for real-time communication and Firebase Firestore for signaling. This post outlines the architecture, technologies used, and some key technical decisions made along the way.

Check it out here - Still a WIP!

Project Overview

The goal was to create a lightweight, privacy-focused file sharing web app where users could connect using a shared room code and transfer files over a direct peer-to-peer connection. The app is entirely browser-based and does not rely on third-party file storage or centralized servers to relay files.

Key features include:

  • Secure, direct P2P connection using WebRTC
  • File chunking and reassembly for handling large files
  • Real-time UI updates with transfer progress and bitrate tracking
  • Support for aborting transfers mid-way
  • Automatic resource cleanup on transfer completion

Technology Stack

  • JavaScript (vanilla, no frontend frameworks)
  • WebRTC (RTCPeerConnection, RTCDataChannel)
  • Firebase Firestore for signaling
  • STUN servers for NAT traversal
  • HTML/CSS for responsive UI

Architecture

Signaling with Firebase

WebRTC requires a signaling mechanism to exchange Session Description Protocol (SDP) offers and ICE candidates between peers before a connection can be established. I used Firebase Firestore for this purpose due to its real-time capabilities and ease of use.

Each peer joins a room using a room code. The initiating peer (caller) creates an SDP offer and writes it to the Firestore under the given room code. The receiving peer (callee) listens for this document, creates an SDP answer, and writes it back. Both peers exchange ICE candidates via Firestore subcollections.

Peer Connection and Data Channels

Once signaling is complete, the application uses a RTCDataChannel to transfer files directly between peers. The data channel is configured for binary data to support efficient file transfer.

Chunked File Transfer

Files are read in chunks (16 KB) using the FileReader API. Each chunk is sent over the data channel sequentially. On the receiving side, the application buffers incoming chunks and reconstructs the original file using the Blob API.

To manage large files effectively, the app transmits metadata first, including the file name and expected size. This allows the receiving peer to display progress, calculate bitrate, and prepare the file download UI in advance.

Progress Tracking and Abort

Progress elements display real-time transfer status for both sending and receiving. The app also includes an "Abort" button that allows the sender to stop a transfer mid-way by calling fileReader.abort().

Bitrate is calculated periodically and displayed to the user, giving feedback on transfer performance. Once the entire file is received, a download link is generated using a Blob URL.

Cleanup and Resource Management

To prevent orphaned documents in Firestore, the app automatically deletes the room document and associated ICE candidate subcollections after the file transfer is complete.

Challenges and Solutions

NAT Traversal

Since WebRTC operates on a peer-to-peer basis, establishing a connection across different networks can be difficult. This was addressed by configuring STUN servers (stun:stun.l.google.com:19302) to assist with NAT traversal.

Metadata and File Validation

To avoid misinterpreting string messages on the data channel, I implemented a metadata prefix to identify JSON-based metadata objects before starting file transfer. This ensured clean separation between control messages and binary data.

Robustness and Edge Cases

The app handles cases like no file selected, no room code entered, or unexpected disconnections. File input is disabled during transfers to prevent UI conflicts, and fallback messages guide the user when waiting for peers to connect.

Conclusion

The full source code is available on GitHub and the live demo is deployed under a subdomain of my portfolio.

Here -- again its a WIP!

tl;dr p2p is cool, file sharing is cool.