Inspiration

Nexum was inspired by a real-world gap: when disasters, congestion, censorship, or simple outages happen, the internet becomes a single point of failure. We wanted communication that still works with no infrastructure—something you can use with just nearby devices.

What it does

Nexum is an offline-first mesh communication PWA that lets people: Create critical updates (alerts, routes, news, general messages) with priority, lifespan (TTL), and network reach (max hops). Store messages locally in the browser (IndexedDB) so they persist offline. Exchange messages peer-to-peer in two ways: QR bundles: generate a scannable QR containing recent local messages; other devices scan to import and merge. Live sync: establish a WebRTC DataChannel connection and sync directly device-to-device after a lightweight handshake. Propagation is controlled so information spreads but doesn’t spiral: messages expire automatically and only forward while hopCount<maxHops.

How we built it

Frontend: React + TypeScript + Vite, styled with Tailwind. Offline/PWA: Service worker caches the app shell; manifest enables installable “app-like” behavior. Storage: Dexie over IndexedDB for local persistence, expiry cleanup, and storage limits (with prioritization). Message safety rules: sanitize incoming messages, dedupe by ID, and resolve conflicts by newest timestamp. QR pipeline: bundle → JSON → compress (when beneficial) → QR; plus payload byte caps and content trimming for scan reliability. Sync protocol: a simple, efficient handshake: Inventory (metadata only) Request (ask only for missing/newer IDs) Messages (send only what was requested, incrementing hop count once for forwarding) Relay server: a small WebSocket service for signaling (offers/answers/ICE), room pairing, heartbeat, and queued signals for briefly-offline peers.

Challenges we ran into

Dense QR codes failing to scan: large payloads create high QR versions that many cameras struggle with. We solved this by capping bytes, trimming message content, increasing QR render size/margins, and adding compression with fallback decoding. WebRTC race conditions: ICE candidates can arrive before the remote SDP is set. We buffered candidates until setRemoteDescription() completed, then flushed safely. “Connected” but not actually usable: WebRTC connection state can look connected before the DataChannel is open. We treated “connected” as DataChannel open and added timeouts/watchdogs to avoid stuck UI states. Free-tier relay cold starts: Render services can sleep. We added a health “wake” request before attempting the WebSocket connect.

Accomplishments that we're proud of

A practical offline-first app that still functions when connectivity is zero. A working peer-to-peer sync protocol that is bandwidth-efficient (inventory/request/messages). QR transfer that is engineered for real camera constraints, not just “it works on my laptop.” Robustness details: TTL expiry, hop-limited propagation, dedupe, storage limits, and clear status reporting.

What we learned

Reliability is mostly about constraints: byte budgets, timeouts, and defensive parsing matter more than “perfect-network” features. WebRTC requires explicit state management—treating transport state separately from sync activity prevents confusing UX. Offline UX isn’t just caching; it’s data lifecycle (expiry), conflict handling, and graceful recovery.

What's next for Nexum

Add a real “Nearby Devices” flow (Bluetooth-assisted discovery) and wire the existing Bluetooth module into the UI. Multi-peer syncing improvements and better session management for groups. Optional encryption and authenticity (signing) so users can verify trusted sources. Smarter propagation policies (e.g., topic-based forwarding, priority-based bandwidth limits) while keeping the core simple and reliable.

Built With

  • bluetooth
  • css-frameworks/libraries:-react
  • dexie-(indexeddb-wrapper)
  • html
  • html5-qrcode-(camera-qr-scanning)
  • javascript-(node.js-for-the-relay-server)
  • languages:-typescript
  • lz-string-(qr-payload-compression)-platforms:-web-(browser)
  • mediadevices/getusermedia-(camera)
  • plus-localstorage-for-device-id-+-recently-scanned-peers-apis-/-web-standards:-webrtc-datachannels
  • pwa-(service-worker-+-web-app-manifest)-cloud/hosting:-render-(static-site-hosting-for-the-frontend-+-node-web-service-for-the-relay)-database/storage:-indexeddb-(via-dexie)
  • qrcode-(qr-generation)
  • service-worker-cache-api
  • tailwind-css
  • vite
  • web
  • web-speech-api-(voice-to-text)
  • websocket-(for-relay-signaling)
Share this project:

Updates

Submission history