Conduit
Encrypted realtime messaging app — socket-based, persistent conversation history, JWT auth, and mobile-native gestures.
The Problem
Building a chat app is a classic full-stack rite of passage, but I wanted to build one that felt like a production-grade product, not a tutorial. This meant going beyond simple socket broadcasts. I needed to implement persistent storage, secure JWT-based authentication, read receipts, typing indicators, and a completely seamless mobile-native gesture experience.
Architecture
The system is split into three core layers:
Real-Time Socket Layer
Built using Socket.io over a Node.js backend, the real-time layer handles message delivery, typing states, and online presence. To prevent unauthorized broadcasts, every socket connection undergoes a JWT handshake during the initial upgrade request. If the token is invalid or expired, the connection is instantly rejected.
Data Persistence
Messages are written to a MongoDB cluster. Instead of blocking the socket event to wait for database confirmation, Conduit uses optimistic UI updates. The frontend instantly renders the message with a "sending" state. Asynchronously, the backend writes to the DB, assigns a permanent ID, and broadcasts the delivery receipt back to the client.
Mobile-Native Frontend
The frontend was built with React Native. I focused heavily on gesture-based interactions, like swipe-to-reply and smooth keyboard-avoiding views. All animations are offloaded to the native UI thread using Reanimated, ensuring 60fps performance even on mid-range Android devices.
The Hardest Problems
1. Offline State Syncing
Handling dropped connections was incredibly tricky. If a user loses internet, sends a message, and reconnects, the message needs to sync. I built a local SQLite queue on the device. When the WebSocket emits a "connect" event, the app flushes the local queue, sending any pending messages to the server in chronological order.
2. JWT Security & Refresh Rotation
Standard JWTs are vulnerable if stolen. I implemented a strict short-lived access token (15 mins) and long-lived refresh token (7 days) architecture. Refresh tokens are stored in secure, HttpOnly cookies (on web) and encrypted keystores (on mobile), ensuring the app remains secure against XSS attacks.