Skip to content
All projects
Full Stack2025 · Full-stack design and implementation

RideConnect

An Uber-style ride-sharing platform where a request reaches a driver and status flows back to the passenger live — built on WebSockets, secured with JWT.

Transport
WebSockets
Auth
JWT, role-aware
Actors
Passenger & driver

Overview

RideConnect is an Uber-style ride-sharing platform with JWT-based authentication and a real-time ride-request and dispatch flow built on WebSockets, delivering live status updates between passengers and drivers.

Problem

Ride-sharing is the clearest case where request/response breaks down. A passenger who has to refresh to find out whether a driver accepted has already lost trust in the product. Two different user roles are watching the same ride object change state — pending, accepted, in progress, completed — and both need to see every transition the moment it happens, from opposite sides of the transaction.

Solution

Model the ride as a single authoritative state machine on the server, and push every transition to both parties over a persistent connection. Next.js serves the passenger and driver interfaces; Node.js owns the ride lifecycle and the socket layer; MongoDB persists users, drivers and ride documents. JWTs authenticate the REST surface and are verified again during the socket handshake, so a connection can’t subscribe to a ride it has no business seeing. Role determines which transitions a client is even allowed to request.

Architecture

REST for everything that can wait, sockets for everything that can’t, and one shared state machine so the two never disagree.

  1. Layer 01

    Clients

    • Passenger app (Next.js)

      Request, track, complete

    • Driver app (Next.js)

      Accept, update, finish

  2. Layer 02

    API layer

    • Node.js REST API

      Auth, profiles, ride history

    • JWT middleware

      Verify + role check

  3. Layer 03

    Realtime layer

    • WebSocket server

      Authenticated handshake

    • Ride rooms

      Scoped per ride, per role

    • Dispatch events

      request → accept → progress → complete

  4. Layer 04

    Data

    • MongoDB

      Users, drivers, rides

    • Ride state machine

      Server is the only authority

Tech Stack

Next.jsNode.jsMongoDBWebSocketsJWTREST APIs

Screenshots

Screenshot slot 1

Screenshot slot 2

Interface captures for RideConnect aren’t published here yet — the architecture and decisions above are the substance. Available on request, or in the repository.

Challenges

  • 01

    Authenticating a socket, not just a route

    HTTP middleware doesn’t protect a WebSocket. An authenticated REST session means nothing if any client can open a socket and listen. I moved JWT verification into the connection handshake and re-checked role and ride ownership before allowing a client to join a ride room.

  • 02

    Two clients, one truth

    Optimistic UI on both sides produced states that disagreed — a driver seeing 'accepted' while the passenger still saw 'searching'. Fixing it meant making the server the sole authority on ride state and treating every client view as a projection of a broadcast event, never as a local guess.

  • 03

    Reconnection without losing the ride

    Mobile connections drop constantly, and a dropped socket cannot mean a dropped ride. Clients resubscribe on reconnect and pull current ride state from the API, so the persistent connection carries updates while the database — not the socket — remains the source of truth.

  • 04

    Dispatch races

    When a request goes out to multiple drivers, two can accept in the same instant. The accept transition had to be a guarded, conditional state change so exactly one driver wins and the rest receive a clean 'no longer available' event.

Lessons Learned

  • 01

    Realtime isn’t a transport swap — it’s a different consistency problem. Deciding who owns state matters more than which library moves it.

  • 02

    Authentication has to be enforced at every entry point. A socket is an entry point.

  • 03

    Design for reconnection from the first commit. Retrofitting it means rewriting the client’s assumptions.

  • 04

    Any concurrent accept, claim or book action needs a guarded transition, not a read-then-write.

Want the deeper version of this?

I’m happy to walk through the code, the trade-offs, or the parts that didn’t make the write-up.