Skip to content

Latest commit

Β 

History

22 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Same Way

The Intelligent Network for Verified Office Carpooling

Same β€” because commuting shouldn't be solitary; the same route, the same time, the same direction Way β€” the path, the method, the intelligent system that matches verified commuters and turns empty seats into shared journeys

Same Way is a self-hosted, production-grade carpool platform for verified office commuters in Bangladesh β€” combining a Flutter mobile app, a Next.js API backend with Prisma/PostgreSQL, OSRM-powered route matching, and a React admin dashboard into a single intelligent platform that transforms daily commutes.

Flutter Next.js React TypeScript Prisma PostgreSQL Redis OSRM Docker License Author


πŸ’‘ What is Same Way?

Every office commute in Bangladesh has a question it must answer for every empty seat:

"Is there a verified colleague traveling my route at my time β€” and can we share the ride safely?"

Same Way is the system that answers that question, at scale, in real time, without a commercial fleet.

It sits as an intelligent layer between commuters and their daily routes. When a user opens the app, Same Way verifies their office identity, learns their home and office locations, matches them with drivers on the same corridor using OSRM-powered routing, and carries them through the entire ride lifecycle β€” request, chat, live tracking, post-ride review β€” inside a trusted, verified community.

A commuter opens the app
↓
Same Way asks: Are you verified? Where is home? Where is office?
↓
OSRM corridor matching finds drivers on your route with seats
↓
Rider requests β†’ Driver accepts β†’ Chat opens β†’ Live tracking starts
↓
Ride completes β†’ Both rate each other β†’ Trust builds

What makes Same Way different from just a ride-sharing app?

Generic Ride-Share Same Way
Open to anyone Verified office commuters β€” email domain + employee ID verification
Random matches Corridor-based matching β€” OSRM routing with bbox pre-filter + match scoring
No identity trust Multi-layer verification β€” work email, employee ID, admin approval, office location
Consumer-grade Enterprise-ready β€” admin dashboard, audit log, maintenance mode, domain allowlist
Black-box algorithms Transparent scoring β€” gender preference, min match score, corridor overlap
Cloud-dependent Self-hosted β€” runs on your infra, your data, your control
Single platform Multi-platform β€” Flutter mobile/web + React admin + Next.js API in one monorepo

Who is Same Way for?

  • Companies in Bangladesh reducing parking pressure, fuel costs, and carbon footprint
  • Office parks & business districts (Gulshan, Banani, Motijheel, Uttara) with dense commuter populations
  • HR & Admin teams needing a turnkey carpool program with verification and reporting
  • Developers who want to understand or extend a production-grade, multi-platform carpool stack

The name

Same Way = Same (the shared route β€” the realization that hundreds of colleagues travel the same corridor daily) + Way (the intelligent path β€” the system that discovers, matches, and guides those shared journeys).

Every commuter who joins Same Way doesn't just find a ride β€” they become part of a verified mobility network, where trust is earned, routes are optimized, and empty seats become connections.


Overview

Use Same Way when you need to:

  • πŸš— Match verified commuters on shared routes with OSRM-powered corridor scoring
  • βœ… Verify office identity via company email domains + employee ID upload + admin approval
  • πŸ—ΊοΈ Optimize routes with bounding-box pre-filter, candidate capping, and rush-hour caching
  • πŸ’¬ Enable ride-day communication β€” in-app chat, live status, driver heading-out broadcasts
  • ⭐ Build trust through post-ride reviews and rating aggregation
  • πŸ›‘οΈ Administer centrally β€” dashboard for users, verifications, domains, maintenance mode
  • πŸ“± Run everywhere β€” Android, iOS, Web (Flutter) + Browser admin (React) + API (Next.js)
  • πŸ—οΈ Deploy on your infra β€” Docker Compose with PostgreSQL, Redis, OSRM, zero cloud dependency

✨ Features

πŸ” Authentication & Verification

Feature Details
JWT access + refresh tokens Secure rotating session management
Open signup + domain allowlist Anyone can sign up; company domains auto-grant the office-verified badge
Employee ID verification Upload ID card β†’ admin review β†’ verified (self-verify option available)
Profile completion Phone, vehicle, home/office, commute type (drive / ride / both / walk)
Gender preference Optional rider/driver filter for cultural comfort
Role-based access USER (commuter) vs ADMIN (dashboard) β€” enforced at API + UI
Maintenance mode One-click toggle blocks signup + ride posting globally

πŸš— Ride lifecycle & matching

Feature Details
Post a ride (drivers) Route (OSRM polyline), departure, seats, repeat (once/daily/weekdays), gender
Find rides (riders) Corridor search β€” bbox DB pre-filter β†’ capped candidates β†’ in-memory scoring β†’ pagination
Match scoring Corridor overlap % + time proximity + gender preference + min match threshold
Ride request flow Pending β†’ Accepted (chat unlocks) / Declined / Cancelled
Ride-day live status Driver: Heading out β†’ At pickup β†’ On way β†’ Late / Cancelled Β· Rider: Confirmed β†’ Boarded
Driver broadcast One-tap "Heading out" notification to all confirmed riders
Regular-route templates Save home ↔ office once, one-tap post for recurring schedules
Post-ride reviews 5-star rating + comment β†’ aggregated driver/rider rating

πŸ—ΊοΈ Maps & routing β€” free, no Google Cloud

Feature Details
OpenStreetMap tiles flutter_map + OSM β€” no API keys
Self-hosted OSRM Bangladesh extract (~15 min first boot), MLD algorithm, nearest/route/table
Nominatim geocoding Free address search for pin placement
Live route animation Animated driver marker; ready for real GPS polling (Phase 2b)
Pin-based places Tap map to set home/office β†’ reverse-geocoded labels

πŸ’¬ Communication & notifications

Feature Details
In-app chat One conversation per ride request β€” messages, read receipts, timestamps
FCM push Ride confirmed, request received, driver ETA, rate ride, verification updates
Outbox pattern Reliable delivery via DB outbox table + background worker (30s poll)
Notification feed In-app center + mark-read / mark-all-read

πŸ›‘οΈ Admin dashboard (React + Vite)

Feature Details
Dashboard stats Users, verified %, active rides, pending reviews, activity log
User management List, search, role toggle, vehicles/places/rides drill-down
Verification queue Pending employee IDs β†’ approve / reject with reason
Domain allowlist Manage company email domains for auto-verification
System config Maintenance mode, auto-verify, global settings
Activity log Audit trail of admin actions with actor + timestamp

πŸ— Infrastructure & DevOps

Feature Details
Docker Compose stack PostgreSQL 16 + Redis 7 + Next.js API + OSRM + outbox worker + db-setup
Prisma ORM Type-safe queries, migrations, seed, Prisma Studio
Rate limiting IP + user tiers (signup 8/min, auth 15/min, search 45/min, chat 60/min)
Search cache Short TTL (30s) for identical rush-hour searches
File uploads Profile photos + employee ID β†’ local volume (S3/R2 ready)
Health endpoint /api/v1/health for orchestration
PWA support Installable Flutter web app for mobile admin access

πŸ— Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Client Layer                                    β”‚
β”‚  Flutter Mobile (Android/iOS) Β· Flutter Web (PWA) Β· React Admin (Vite) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚ HTTPS / REST / JWT
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        API Layer (Next.js 16)                          β”‚
β”‚   /api/v1/* REST Β· JWT guard Β· rate limits Β· Zod validation           β”‚
β”‚   Modules: auth, users, rides, matching, chat, notifications,        β”‚
β”‚            bookings, admin, uploads, reviews                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚                               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Infrastructure              β”‚   β”‚  External Services                  β”‚
β”‚  Prisma repos Β· Redis cache  β”‚   β”‚  PostgreSQL 16 Β· Redis 7 Β· OSRM     β”‚
β”‚  OSRM client Β· FCM Β· outbox  β”‚   β”‚  (Bangladesh OSM) Β· Nominatim       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key design decisions

Layered architecture β€” Routes β†’ Modules β†’ Infrastructure β†’ Prisma/Redis/OSRM. Thin controllers, fat services, pure domain logic.

Corridor matching β€” Not radius search. OSRM computes the route polyline β†’ bbox pre-filter in Postgres β†’ candidate cap (300) β†’ in-memory corridor-overlap scoring β†’ pagination.

Verification-first β€” No ride posting without verified status. Multi-layer: email domain β†’ employee ID β†’ admin approval β†’ office location.

Self-hosted routing β€” OSRM runs locally with a Bangladesh OSM extract. No Google Maps API costs, no external dependency, full data sovereignty.

Outbox pattern β€” Notifications written to a DB outbox β†’ worker polls every 30s β†’ FCM delivery β†’ status update. At-least-once delivery.

Monorepo β€” Backend Prisma models inform frontend types. dart_defines.json injects all env config into Flutter β€” zero hardcoded values.


πŸš€ Quick Start

Prerequisites

Requirement Version
Docker + Docker Compose v2.20+
Node.js 20+
Flutter SDK 3.11+
Android Studio / Xcode Mobile builds
PostgreSQL 14+ Local-only runs

1 β€” Backend API (backend/)

Docker (recommended β€” full stack: Postgres + Redis + OSRM + API + outbox worker):

cd backend
cp .env.example .env   # set strong JWT_ACCESS_SECRET / JWT_REFRESH_SECRET
docker compose up --build -d
# API: http://localhost:3000/api/v1/health

Local Node (no Docker):

cd backend
cp .env.example .env
npm install
npm run db:push        # create tables
npm run db:seed        # seed demo admin + user + domains
npm run dev            # http://localhost:3000

Seed accounts:

Role Email Password
Admin admin@sameway.local Admin@12345
Demo user demo@sameway.local Demo@12345

First Docker boot downloads the Bangladesh OSM extract (~15 min); later starts are instant.

2 β€” Admin dashboard (web/)

cd web
npm install
npm run dev      # http://localhost:5173

Vite proxies /api to http://localhost:3000. Login with the seed admin credentials.

3 β€” Flutter app (app/)

cd app
cp dart_defines.example.json dart_defines.json
# Edit dart_defines.json β€” set API_BASE_URL:
#   physical device  : "http://<YOUR-LAN-IP>:3000/api/v1"
#   Android emulator : "http://10.0.2.2:3000/api/v1"
#   Flutter web      : "http://localhost:3000/api/v1"
flutter pub get
flutter run

QA navigation: open /catalog to jump to any of the 39+ screens.

Flutter web (user-facing):

flutter run -d chrome --web-port=7357

Config lives entirely in dart_defines.json β€” nothing is hardcoded in Dart. After editing, stop and re-run (hot reload ignores config).


πŸ—‚ Repository Layout

sameway/
β”œβ”€β”€ app/                    # Flutter mobile & web UI (39+ screens)
β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   β”œβ”€β”€ core/           # API client, session, models, maps, theme, config
β”‚   β”‚   β”œβ”€β”€ features/       # onboarding, home, offer_ride, find_ride, match, ride_day, chat, admin, web, dev
β”‚   β”‚   └── router/         # go_router setup
β”‚   β”œβ”€β”€ dart_defines.json   # Runtime config (API URL, map tiles, FCM)
β”‚   └── pubspec.yaml
β”œβ”€β”€ backend/                # Next.js API (Node.js + PostgreSQL + Prisma)
β”‚   β”œβ”€β”€ prisma/
β”‚   β”‚   β”œβ”€β”€ schema.prisma   # Full domain model (users, rides, chat, admin…)
β”‚   β”‚   └── seed.ts
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ app/api/v1/     # Thin route handlers (REST)
β”‚   β”‚   β”œβ”€β”€ modules/        # Service facades per domain
β”‚   β”‚   β”œβ”€β”€ application/    # Use-cases, DTO mappers, DI container
β”‚   β”‚   β”œβ”€β”€ domain/         # Repository + port interfaces
β”‚   β”‚   β”œβ”€β”€ infrastructure/ # Prisma repos, cache, outbox, rate limit, push, geocoding
β”‚   β”‚   └── lib/            # Auth, DB, HTTP, env, validation
β”‚   β”œβ”€β”€ docker/             # Dockerfile, entrypoint, OSRM setup
β”‚   β”œβ”€β”€ docker-compose.yml  # pg, redis, api, osrm, outbox, db-setup
β”‚   └── package.json
β”œβ”€β”€ web/                    # React admin dashboard (Vite)
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ pages/          # Dashboard, Users, Verification, Config, Login
β”‚   β”‚   β”œβ”€β”€ components/     # AdminLayout, DataTable, StatCard
β”‚   β”‚   β”œβ”€β”€ auth/           # AuthContext
β”‚   β”‚   └── api/            # client.ts
β”‚   └── package.json
└── README.md

βš™ Configuration

All backend config lives in backend/.env. Flutter config lives in app/dart_defines.json; runtime-only settings are managed in Admin β†’ Config with no restart.

Required secrets

JWT_ACCESS_SECRET=       # min 32 chars β€” signs access tokens
JWT_REFRESH_SECRET=      # min 32 chars β€” signs refresh tokens
DATABASE_URL=postgresql://user:pass@localhost:5432/sameway?schema=public
REDIS_URL=redis://localhost:6379
FIREBASE_PROJECT_ID       # FCM push (optional)
FIREBASE_CLIENT_EMAIL
FIREBASE_PRIVATE_KEY
OSRM_URL=http://osrm:5000
UPLOAD_DIR=./uploads
CORS_ORIGINS=http://localhost:7357,http://localhost:5173
RATE_LIMIT_ENABLED=true
SEARCH_CANDIDATE_CAP=300
SEARCH_CACHE_TTL_SEC=30
SEARCH_BBOX_BUFFER_KM=18

Runtime-only settings (Admin β†’ Config)

Setting Description
Maintenance mode Blocks signup + ride posting
Auto-verify Domains auto-verified on signup
Domain allowlist Company email domains
Verification method ADMIN_ONLY or SELF_VERIFY
ID visibility ADMIN_ONLY or PUBLIC_TO_RIDERS

Flutter config (app/dart_defines.json)

Key Example
API_BASE_URL http://192.168.31.47:3000/api/v1 (device)
MAP_TILE_URL https://tile.openstreetmap.org/{z}/{x}/{y}.png
DEFAULT_MAP_CENTER 23.8103,90.4254
DEFAULT_HOME 23.8759,90.3795
DEFAULT_OFFICE 23.7330,90.4172
API_ENABLED false to run UI without backend
FCM_DEV_TOKEN dev push token (optional)

πŸ“‘ API Reference

Base URL: http://localhost:3000/api/v1 β€” all authenticated endpoints use Authorization: Bearer <accessToken>.

Auth & onboarding

Method Endpoint Description
POST /auth/signup Register (any email; company domains auto-verify)
POST /auth/signin Login β†’ access + refresh tokens
POST /auth/refresh Rotate tokens
DELETE /auth/refresh Logout (invalidate refresh)
GET /auth/me Current user + vehicles + places

User profile

Method Endpoint Description
PATCH /users/me Update profile, commute type
POST /users/me/vehicles Add vehicle
PATCH /users/me/vehicles/:id Update vehicle
POST /users/me/locations Upsert home/office
POST /users/me/verification Submit employee ID
PATCH /users/me/reminder-settings Notification toggles
POST /users/me/device-tokens Register FCM token
GET /users/:id/reviews Public reviews

Rides (offer & find)

Method Endpoint Description
POST /rides Post a ride (verified users)
GET /rides My rides as driver
POST /rides/search Find rides (geo prefilter, scoring, cache)
GET /rides/:id Ride detail
POST /rides/:id/request Rider requests seat
GET /rides/:id/requests Driver: incoming requests
POST /rides/:id/requests/:requestId Accept request
DELETE /rides/:id/requests/:requestId Decline request
POST /rides/:id/heading-out Driver broadcast
GET /rides/:id/live Live participant statuses
PATCH /rides/:id/participants/:userId/status Rider status updates
POST /rides/:id/reviews Rate after ride

Regular routes & bookings

Method Endpoint Description
GET/POST /regular-routes Saved route templates
POST /regular-routes/:id/post-ride?departureAt=ISO Quick post from template
GET `/bookings/mine?status=upcoming completed`

Chat & notifications

Method Endpoint Description
GET /chat/conversations Conversation list
GET/POST /chat/conversations/:id/messages Messages / send
PATCH /chat/conversations/:id/messages Mark read
GET /notifications Notification feed
PATCH /notifications Mark all read
PATCH /notifications/:id/read Mark one read

Admin

Method Endpoint Description
GET /admin/dashboard Stats
GET /admin/activity Activity log
GET/PATCH /admin/users, /admin/users/:id User management
GET /admin/verifications/pending Pending ID reviews
POST `/admin/verifications/:id/approve reject`
GET/POST /admin/config/domains Email domain allowlist
DELETE /admin/config/domains/:domain Remove domain
GET/PATCH /admin/config/settings Maintenance mode, auto-verify

Utilities

Method Endpoint Description
GET /health Health check
POST /uploads Image upload (multipart)
GET /places/autocomplete?q= Nominatim geocoding

🌐 Production Deployment

Docker Compose (recommended)

# 1. Set production values in backend/.env
#    - Strong JWT_ACCESS_SECRET, JWT_REFRESH_SECRET (32+ random chars each)
#    - Real DATABASE_URL, REDIS_URL (managed services for multi-instance)
#    - FIREBASE_* for push notifications
#    - NODE_ENV=production
#    - CORS_ORIGINS for your domains
#    - SEED_DB=false (after first boot)

# 2. Deploy
cd backend
docker compose up -d --build

# 3. Verify
curl https://your-domain.com/api/v1/health

Reverse proxy (nginx example)

server {
    listen 443 ssl;
    server_name api.yourdomain.com;

    location /api/ {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        proxy_pass http://localhost:5173;
        proxy_set_header Host $host;
    }
}

Production checklist

  • Change the default admin password immediately after seed
  • Set strong JWT_ACCESS_SECRET / JWT_REFRESH_SECRET (32+ random chars each)
  • Use managed PostgreSQL with connection pooling
  • Use managed Redis for distributed rate limits + search cache
  • Configure FIREBASE_* for FCM push notifications
  • Set NODE_ENV=production, SEED_DB=false
  • Set CORS_ORIGINS for production Flutter web + admin domains
  • Enable HTTPS via reverse proxy
  • Move file uploads to S3/R2
  • Configure PostgreSQL connection pooling for multi-instance API
  • Verify full flow: signup β†’ verify β†’ post β†’ search β†’ request β†’ chat β†’ review

πŸ”§ Development

Local dev (no Docker for API)

# Terminal 1: Backend
cd backend && cp .env.example .env && npm install && npm run db:push && npm run db:seed && npm run dev

# Terminal 2: Admin dashboard
cd web && npm install && npm run dev

# Terminal 3: Flutter app
cd app && cp dart_defines.example.json dart_defines.json && flutter pub get && flutter run -d chrome --web-port=7357

Useful scripts

Command Description
cd backend && npm run dev Start API dev server
cd backend && npm run build Production build
cd backend && npm run db:studio Prisma Studio GUI
cd backend && npm run db:migrate Create migration
cd backend && npm run db:push Sync schema to DB (dev)
cd backend && npm run db:seed Seed demo data
cd backend && npm run docker:up Start full Docker stack
cd backend && npm run docker:down Stop stack
cd backend && npm run docker:logs Follow API logs
cd backend && docker compose down -v Wipe DB + volumes (careful)
cd web && npm run build Production build (admin)
cd app && flutter pub get Fetch Flutter dependencies
cd app && flutter analyze Static analysis

OSRM routing engine

# First run: download Bangladesh OSM + build MLD graph
docker compose up osrm-setup
# Then run the router
curl 'http://localhost:5000/nearest/v1/driving/90.4125,23.8103'
curl 'http://localhost:5000/route/v1/driving/90.4125,23.8103;90.4254,23.8103?overview=full&geometries=geojson'

🀝 Contributing

Contributions, issues, and feature requests are welcome.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/your-feature)
  3. Ensure TypeScript passes (cd backend && npm run lint)
  4. Ensure Flutter analyzes (cd app && flutter analyze)
  5. Commit with a clear conventional message
  6. Open a pull request against main

Maintainer: Md. Asiqur Rahman Khan


πŸ“„ License

Private β€” Same Way project.


Same Way β€” Verified Office Carpooling for Bangladesh, Self-Hosted

Flutter Β· Next.js Β· React Β· PostgreSQL Β· OSRM

"Same route. Same time. Same Way."

Built by Md. Asiqur Rahman Khan

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages