Inspiration

Natural disasters, conflict zones, mass protest events — the first thing that fails is always the network. Cell towers get overloaded. Routers go down. And suddenly the people who need to communicate the most are the ones who can't.

We kept asking one question: what if the phone in your pocket was enough? Not dependent on a tower, a router, or a server — just the device itself and the people physically around you. That question became MeshNet.

What it does

MeshNet turns every phone into a temporary local node in an offline mesh network. Users compose emergency messages — safe routes, medical aid locations, urgent alerts — and relay them to nearby devices with no internet, no infrastructure, and no backend.

Messages propagate hop by hop:

$$A \rightarrow B \rightarrow C \rightarrow \cdots$$

Each relay increments a hop counter. Normal messages travel up to 3 hops. Urgent emergency alerts travel up to 10 hops, ensuring critical information reaches further without flooding the network. Messages also carry an expiry timestamp and are pruned automatically, keeping storage lean on resource-limited devices.

Two relay modes cover every device:

  • QR Visual Relay — works on any phone or laptop with a camera. No pairing, no permissions, no infrastructure. The sender's message cache is split into rotating QR frames; the receiver scans and reassembles them.
  • Android Native P2P — inside the installed APK, the same sync protocol hands off to Google Nearby Connections for true Bluetooth + Wi-Fi Direct device-to-device transfer.

How we built it

The stack is intentionally minimal — everything had to work offline once loaded.

Layer Technology
UI React 19, Tailwind CSS
Build & PWA Vite 8, vite-plugin-pwa, Workbox
QR qrcode.react, @zxing/browser
Native Android Capacitor 8, @capacitor-trancee/nearby-connections
Storage localStorage — no backend, no account, no server

Messages are serialized as compact arrays rather than verbose JSON objects, keeping QR payload sizes within reliable scan limits and multi-hop transfers fast. The core sync logic — getSyncPayload(), parseSyncPayload(), mergeMessages() — lives entirely in src/store.js with no network calls anywhere.

The PWA service worker caches the full app on first visit, so every subsequent load is completely offline.

Challenges we ran into

Browsers have no real offline P2P. WebRTC requires a signalling server, which immediately breaks the offline-first constraint. Wi-Fi Direct has no stable browser API. We had to design around this — which led us to QR visual relay, which turned out to be more universally compatible anyway.

QR codes have hard payload limits. A standard QR code tops out around 1,200 characters at high error correction. We had to design a compact serialization format, enforce a conservative payload budget, and implement a rotating multi-frame protocol for larger transfers — essentially a slow, camera-based data channel.

HTTPS is required for camera access, even on a local network. Getting a trusted local certificate working across multiple physical devices during testing added unexpected friction before we moved to the deployed PWA.

Android Nearby Connections runtime permissions vary by Android version. Mapping the right permission requests to the right API levels, and handling user rejections gracefully, took significantly longer than expected.

Accomplishments that we're proud of

  • Built a fully functional offline mesh relay that works on any device with a browser — no app install required for the core use case.
  • Designed a sync protocol simple enough to fit in a QR code but robust enough to handle deduplication, hop limiting, and expiry across an arbitrary chain of devices.
  • The hop + expiry rule is elegant in its simplicity:

$$\text{relay if} \quad h < h_{max} \quad \text{and} \quad t_{now} < t_{expiry}$$

No coordination, no central authority. Every node decides independently.

  • Shipped a real Android native P2P path using Nearby Connections — the same message store, the same merge logic, upgraded to radio transport with zero changes to the application layer.
  • Zero backend. Zero accounts. Zero infrastructure dependency. The app is fully self-contained.

What we learned

Offline-first is an architectural constraint, not a feature you add later. Every decision — storage format, sync protocol, message size, expiry window, hop limits — flows from that single constraint. The moment you design for offline from the start, a lot of complexity disappears because you simply cannot reach for a server.

We also learned that visual relay is underrated. QR-based transfer is slower than radio P2P, but it works across every device with a camera, requires zero pairing, and is trivially debuggable.

What's next for MeshNet

  • Real-device testing and verification of Android Native P2P across three physical phones
  • iOS support via a macOS + Xcode build pipeline
  • Message threading — allow newer alerts to supersede older ones on the same topic
  • A privacy mode that rotates node IDs automatically each session
  • Compressed QR payloads to carry more messages per scan
  • Exploring audio-based relay (ultrasonic data transfer) as a third fallback channel

Built With

  • android
  • capacitor
  • css3
  • githubpages
  • googlenearbyconnections
  • html5
  • html5-qrcode
  • javascript
  • localstorage
  • progressivewebapp(pwa)
  • qrcode.react
  • react
  • serviceworkers
  • tailwindcss
  • vite
  • vite-plugin-pwa
  • webmanifest
  • workbox
  • zxing
Share this project:

Updates

Submission history