A full-stack ride-booking demo with separate rider and captain apps, a Hono API, Prisma/PostgreSQL persistence, Redis-backed captain location storage, and Socket.IO infrastructure for live trip updates.
This repository is optimized as a portfolio/showcase project: the core ride lifecycle is complete and buildable, while production concerns such as automatic nearest-driver dispatch, rate limiting, monitoring, and broad test coverage are intentionally left as future work.
- Rider app for sign up, sign in, location selection, fare estimate, ride request, trip tracking, cancellation, and history.
- Captain app for sign up, sign in, online/offline state, available ride list, manual ride acceptance, OTP pickup verification, trip completion/cancellation, location sharing, and history.
- Backend API with JWT authentication, bcrypt password hashing, Prisma models, Hono routes, structured validation with Zod, and central error handling.
- Trip lifecycle:
REQUESTED -> ACCEPTED -> ON_TRIP -> COMPLETED, with cancellation support. - Redis helpers for captain geolocation and trip/captain location lookups.
- Monorepo setup with Bun workspaces and Turborepo.
| Area | Tools |
|---|---|
| Monorepo | Bun, Turborepo |
| Rider app | Next.js 16, React 19, Tailwind CSS, TanStack Query, Axios, MapLibre/Leaflet |
| Captain app | Next.js 16, React 19, Tailwind CSS, TanStack Query, Axios, Leaflet |
| Backend | Bun, Hono, Socket.IO, Prisma 7, PostgreSQL, Redis, Zod |
| Shared packages | TypeScript config, ESLint config, reusable UI package |
uber/
apps/
user/ Rider-facing Next.js app
captain/ Captain-facing Next.js app
server/ Hono API, Prisma schema, Socket.IO integration
packages/
ui/ Shared UI package
eslint-config/
typescript-config/
- Bun 1.3+
- Node.js 18+
- PostgreSQL database
- Redis instance
Hosted PostgreSQL/Redis services work fine for demo usage. Keep real secrets in .env files only; .env is ignored by Git.
Create apps/server/.env:
DATABASE_URL="postgresql://user:password@localhost:5432/uber_db"
REDIS_URL="redis://localhost:6379"
JWT_SECRET="replace-with-a-long-random-secret"
PORT=3000The frontend API clients currently expect the backend at http://localhost:3000:
apps/user/lib/api.tsapps/captain/lib/api.ts
If you change the backend port, update both clients or introduce a public environment variable.
bun installGenerate the Prisma client and apply migrations:
cd apps/server
bunx --bun prisma generate
bunx --bun prisma migrate devStart all apps from the repository root:
bun run devThe dev scripts use portless hostnames:
- Rider app:
http://uber.localhost - Captain app:
http://captain.uber.localhost - Backend API:
http://localhost:3000by default
- Start the backend, rider app, and captain app with
bun run dev. - Sign up or sign in as a rider in the user app.
- Choose pickup/drop locations, select vehicle capacity, and request a ride.
- Sign up or sign in as a captain in the captain app.
- Go online, open available trips, and accept the rider's request.
- Ask the rider for the OTP, start the trip, then complete it.
- Confirm both rider and captain history pages show the completed trip.
Trip matching is currently manual: online captains choose from available requested trips. Redis location support is present, but automatic nearest-captain dispatch is future work.
bun run dev # Start all apps
bun run check-types # Run type checks across the monorepo
bun run lint # Run lint checks across the monorepo
bun run build:user # Build the rider app
bun run build:captain # Build the captain app
bun run build # Build all configured build targetsDirect checks used for verification:
cd apps/server && bunx tsc --noEmit
cd apps/user && bunx tsc --noEmit
cd apps/captain && bunx tsc --noEmit
cd packages/ui && bunx tsc --noEmitAuth:
POST /auth/signupPOST /auth/signinGET /auth/signoutPOST /auth/forgotPOST /auth/reset?token=...
Rider:
GET /userGET /user/verifyPOST /user/verifyPOST /user/requestPOST /user/cancelGET /user/trip/:idGET /user/historyGET /user/ongoingPOST /price
Captain:
POST /captain/onlinePOST /captain/offlinePOST /captain/locationGET /captain/trips/availablePOST /captain/trips/:id/acceptPOST /captain/pickupPOST /captain/completePOST /captain/cancelGET /captain/history
Done:
- Demo-ready rider/captain trip lifecycle.
- JWT auth for both roles.
- Manual ride acceptance.
- OTP-based pickup verification.
- Redis-backed captain location updates.
- Type checks and frontend builds passing.
Future improvements:
- Automatic nearest-captain matching.
- Rate limiting and stronger security hardening.
- Admin dashboard and analytics.
- More complete unit/integration tests.
- Production deployment configuration and monitoring.
This is a learning/showcase implementation, not a production ride-hailing system. The intent is to demonstrate full-stack ownership across frontend apps, backend routes, persistence, authentication, real-time architecture, and pragmatic monorepo tooling.