Holo
Feb 2026Minimalist peer-to-peer style file sharing web app.
Tech Stack
Overview
Holo is a minimal file sharing app that uses a Go WebSocket relay with no persistence. Files are streamed in chunks and only relayed in memory, so rooms and connections are ephemeral and auto-expire after inactivity.

The Problem
I needed a way to move files from my personal device to college or public PCs, but privacy was the blocker. I wanted something that felt instant, private, and did not leave files sitting on a server.
Iteration 1 was Toraje: https://github.com/moroii69/toraje. Users uploaded files (20 MB max), which were AES-encrypted client-side with a random key and stored in Firebase behind a short access code with a 69-minute expiry. Recipients entered the code to decrypt and download once, then the file was deleted. It was secure, but upload and download were slow on large files or poor networks. The flow was also clunky, and it failed for many file types (docx and others).
Iteration 2 was Rive: https://github.com/moroii69/rive. Files were encrypted in the browser using AES-256-GCM, with the key derived from a 6-digit code. Only encrypted data hit the server, so storage was blind. It was simpler, but still had issues with certain files and did not feel as private as I wanted.
The Solution
While learning Go and channels, and reading about BitTorrent ideas like P2P, trackers, and room coordination, I decided to build a P2P-styled transfer rather than a direct P2P connection.
Holo lets two or more clients join a room with an ID. The Go server spins up an in-memory relay (a channel between participants), and files stream in chunks over WebSockets. No database, no disk storage, and no long-lived artifacts, just a fast, temporary tunnel for transfer. https://github.com/moroii69/holo
Technical Details
- •Go WebSocket relay server (memory-only, no persistence)
- •Next.js + TypeScript frontend with HTML5 File APIs
- •Chunked streaming over WebSockets to avoid RAM spikes
- •Room-based sessions with auto-expiry on inactivity
- •Configurable WebSocket URL via NEXT_PUBLIC_WS_URL