Beamly is a modern, production-quality, open-source peer-to-peer (P2P) file transfer application. Built with Flask, Jinja2, TailwindCSS (Neo-Brutalism), and native browser WebRTC DataChannels, it enables 100% free, end-to-end encrypted (E2EE), fast, and serverless transfers directly between two devices.
The Flask backend acts strictly as a signaling coordinator—file data is encrypted using DTLS-SRTP and transferred directly browser-to-browser. Files never touch or store on the server.
"100% Free Peer-to-Peer Transfer. Securely Encrypted. No Cloud. No Account."
Beamly adopts a striking Neo-Brutalist design language:
- 🖋️ Huge, bold typography
- 🔳 Thick 3px borders
- 🎨 Flat saturated colors (Yellow, Pink, Blue, Green)
- 🚫 No gradients or soft shadows
- 🧱 Hard offset shadows and animated lifts on hover
- Secure Room Creation: UUID room endpoints utilizing a clean
XXXX-XXXXformat. - Dynamic QR Code Generation: Scan QR codes on mobile to connect instantly.
- WebRTC Signaling: Multi-protocol signaling (SDP & ICE exchange) run via Flask-SocketIO.
- Drag & Drop Uploads: Native browser drag-drop interface for files.
- Multi-File Queuing: Transmit multiple files in a sequential, race-condition-safe queue.
- Clipboard Paste: Paste screenshots directly from your clipboard to send immediately.
- Backpressure Handling: Tracks data channel
bufferedAmountto pause sending before buffer overflow, resuming onbufferedamountlowevent. - Real-time Metrics: Active speed (KiB/s, MiB/s) and ETA calculations.
- Cancel Transfers: Cancel individual queued or active transfers dynamically.
- Mobile Responsive: Styled with Tailwind for both mobile and desktop screens.
- Connected Device Signatures: Direct handshake displays the peer's OS and Browser information.
The signaling process occurs via WebSockets (Flask-SocketIO), but the file transfer payload passes directly through a secure WebRTC DataChannel (SRTP/SCTP) browser-to-browser.
sequence-frame
actor Sender as Sender Browser
participant Flask as Flask Server
actor Receiver as Receiver Browser
Note over Sender, Receiver: 1. SIGNALING HANDSHAKE (WebSocket)
Sender->>Flask: Join Room (initiator)
Receiver->>Flask: Join Room (joiner)
Flask->>Sender: notify 'peer_joined'
Sender->>Flask: Send SDP Offer
Flask->>Receiver: Relay SDP Offer
Receiver->>Flask: Send SDP Answer
Flask->>Sender: Relay SDP Answer
loop ICE Candidate Exchange
Sender->>Flask: Send ICE Candidate
Flask->>Receiver: Relay ICE Candidate
Receiver->>Flask: Send ICE Candidate
Flask->>Sender: Relay ICE Candidate
end
Note over Sender, Receiver: 2. DIRECT WebRTC CONNECTION (P2P SCTP DataChannel)
Sender->>Receiver: Handshake Metadata (Browser, OS info)
Note over Sender, Receiver: 3. FILE STREAMING (Sequential Chunks)
Sender->>Receiver: Send JSON Metadata (filename, size, mimetype)
loop Chunks (64 KiB each)
Sender->>Receiver: Send Binary Chunk (ArrayBuffer)
Note over Sender: Check bufferedAmount\n(Backpressure applied)
end
Sender->>Receiver: Send JSON "Completed"
Note over Receiver: Assemble Chunks -> Download Blob
beamly/
├── app/
│ ├── models/ # Python data models package
│ │ └── __init__.py
│ ├── services/ # Core business services
│ │ ├── __init__.py
│ │ └── room_manager.py # In-memory room manager and cleaner
│ ├── static/
│ │ ├── css/
│ │ │ ├── src/
│ │ │ │ └── main.css # Input CSS with Tailwind directives
│ │ │ └── style.css # Compiled and minified Tailwind CSS
│ │ └── js/
│ │ ├── connection.js # Coordinates RTCPeerConnection and SDP
│ │ ├── receiver.js # Assembles chunks and triggers downloads
│ │ ├── rtc.js # Peer connection creation with STUN servers
│ │ ├── sender.js # Handles file reading, chunking, and backpressure
│ │ ├── signaling.js # Socket.IO connection client
│ │ └── ui.js # Direct DOM binding, clipboard, drag-drop
│ ├── templates/
│ │ ├── base.html # Global wrapper with SEO and layout
│ │ ├── landing.html # Join/Create room landing page
│ │ └── room.html # Dynamic WebRTC transfer panel
│ ├── utils/
│ │ ├── __init__.py
│ │ └── helpers.py # Room code and sanitization helpers
│ ├── __init__.py # Flask application factory
│ └── routes.py # HTTP routes and QR generator
├── config.py # App environment configurations
├── run.py # Server entrypoint (eventlet launcher)
├── requirements.txt # Python application dependencies
├── package.json # Node.js Tailwind compiler scripts
├── tailwind.config.js # Neo-Brutalist styling configuration
├── Dockerfile # Multi-stage container script
├── docker-compose.yml # Dev/Prod orchestration composition
├── LICENSE # MIT License
├── CONTRIBUTING.md # Guidelines for open-source contributors
└── README.md # This file
- Python 3.9+
- Node.js & npm (for compiling Tailwind CSS assets)
-
Activate Python Virtual Environment:
python3 -m venv venv source venv/bin/activate # On Windows use: venv\Scripts\activate pip install -r requirements.txt
-
Install and Compile Assets:
npm install npm run build:css
-
Start the Flask Application:
python run.py
The application will boot on
http://localhost:5001.
Beamly features a multi-stage Dockerfile that compiles the CSS in Node and launches the application using Python 3.11-slim.
-
Spin up using Docker Compose:
docker-compose up --build
-
Access the Container: The application will run on
http://localhost:5001. You can pass environment variables indocker-compose.ymlto tune room timers and file limitations.
Contributions are open for the following roadmap features (labeled TODO in codebase):
- Folder Transfer: Support uploading and downloading directory tree structures.
- End-to-End Verification: Implement SHA-256 integrity checksum matches post-assembly.
- Clipboard Sync: Secure clipboard copy-paste text sharing between tabs.
- Text Messaging: Integrated text transfers for quick link exchanges.
- Resumable Transfers: Slice chunk ranges dynamically and request missing parts.
- LAN Discovery: Discover active rooms on the local network (mDNS/IP scans).
- PWA Support: Offline caching and native mobile installs.
- Previews: Inline rendering for image and video transfers prior to save.
- Password-Protected Rooms: Salted hashes exchanged during signaling.
A: Theoretically unlimited. Because files are sliced on-the-fly from disk via the HTML5 File API and transferred directly browser-to-browser, the server is never a bottleneck. However, the browser's RAM buffers chunks for file reconstruction on the receiving end.
A: Public Google STUN servers are bundled by default for NAT traversal, which works for most home networks. If both users are behind strict symmetric enterprise firewalls, they will require a TURN server. You can configure a TURN list in config.py.
A: No. The signaling server (Flask) only routes signaling metadata (SDP/ICE descriptions). Once the direct P2P link is established, files are sent directly and encrypted out-of-band using DTLS-SRTP.
We welcome open-source contributions of all kinds! Whether you are fixing bugs, improving the Neo-Brutalist UI, or implementing features from the roadmap, we'd love your help.
- Review the CHECKLIST.md progress tracker to find active tasks and open ideas.
- Read the CONTRIBUTING.md guide for step-by-step setup instructions.
- Open a Pull Request or create an Issue to discuss your planned changes.
Beamly is open-source software licensed under the MIT License.