I built a P2P file sharing app using Nostr for peer discovery.
How it works: Log in with your Nostr extension, pick a recipient by npub, select a file, and send. WebRTC signaling goes through Nostr relays (encrypted with NIP-44), then files transfer directly browser-to-browser. The relay never sees your files.
Try it: https://k4lb1.github.io/Zoop/Code: https://github.com/k4lb1/Zoop
Relays only handle tiny encrypted signaling messages - the actual file goes peer-to-peer.
What I learned: Nostr’s event system works surprisingly well for WebRTC coordination. NIP-44 encryption keeps signaling private. ICE negotiation on mobile networks is still brutal though.
Thinking about a desktop version with persistent transfer history and contact management.
Feedback welcome - especially if you find bugs.
That's great, forked! Not sue which kind of issue I'm facing and it is not loading properly. Anything should I set to fix?
Thanks for forking! Can you tell me a bit more? do you see any errors in the browser console?
Sure, I simply forked and deployed in GH pages using the existing
workflows/deploy.ymlhere a screenshot
Hey, sorry for the hassle.
The 404 happens when Pages is set to “Deploy from a branch” with the main branch and the root (/) folder. In that case GitHub serves the raw repo (your source code), but the actual site is built by Vite into a dist/ folder. The root only has things like src/, package.json, etc., and no index.html, so the browser gets a 404.
What to do: In your fork go to Settings → Pages. Under Build and deployment, set Source to GitHub Actions (instead of “Deploy from a branch”). Then the workflow runs on every push to main: it runs npm run build and deploys the built dist/ folder. Give it a minute or two after a push, then https://4g0r4.github.io/Zoop/ should load.
I’m not that experienced with Git and GitHub myself, so I only figured this out with some help. We’ve added a “Quick Start for Forks” section in the README with these steps so it’s easier next time. Hope that fixes it for you.
Nice work — using Nostr relays for WebRTC signaling is clever. NIP-44 encryption for the signaling messages is the right call since those contain ICE candidates that could leak IPs.
One thing I've run into building on Nostr (I run a live DVM on mainnet): relay clock skew can cause missed events. If you're using
sincefilters to only grab recent signaling messages, add a 15-30 second lookback window. I lost requests early on because my subscription filter was too tight and relays had a few seconds of clock drift.For the mobile ICE issues — have you tried including a TURN fallback? Symmetric NAT on cell networks blocks most peer-to-peer connections. Metered.ca has a free TURN tier that works well enough for signaling-only setups.
Thanks for the detailed feedback. I already using NIP-44 for signaling and a TURN fallback (Metered). I'll look into adding a short lookback window for the since filter to handle relay clock skew. Appreciate it.