A casual, real-time ride-sharing marketplace — grab a ride from someone already heading your way.
Not a taxi app, not ride-hailing. Everyone can both post and join rides. You're already going there — someone can simply come along and split the fuel cost.
Flutter · Supabase · PostGIS · OpenStreetMap · UPI
OnTheWay connects people who are already travelling with others going the same way. Open the app, see nearby rides on a map, book a seat, coordinate a safe meet point, travel, and settle a small fuel contribution over UPI or cash after the ride. It is not ride-hailing: drivers are not taxis; they are people already on the route.
Discovery
- Rides around you — location-scoped discovery fetches only nearby rides using the
rides_nearbyPostGIS RPC, with a user-adjustable 5-60 km radius. The feed refreshes on pull-to-refresh, radius changes, and meaningful location/provider updates rather than a timer that resets the review session. - Live OpenStreetMap map with theme-aware dark/light tiles, route polylines, vehicle-aware markers, and cancellable tile requests for web performance.
- Filters for leaving soon, cheapest, women-only, verified, plus live ride count and distance-aware sorting.
- First-run onboarding explains the product model: not a taxi app, trust first, and one-tap commutes.
Post a ride
- Pick a vehicle you own (or add one on the spot: type, model, plate, mileage).
- Origin & destination via address autocomplete (OpenRouteService geocoding), drop a pin on the map, or explicitly use current location. The Create Ride page does not auto-request browser location on open, so web preview remains responsive.
- Save regular commutes and reuse them for one-tap route setup; saved commutes sync through Supabase when using the real backend.
- Real routed distance/ETA and an intelligent fare (distance x mileage x fuel price x traffic) with an enforced allowed range — drivers can't over-charge.
- Seats, departure window, luggage, gender preference, and a note for riders.
Book & coordinate
- First-come-first-serve seat reservation; rides close automatically when full or after departure.
- Smart meet-point suggestions (metro, bus stop, petrol pump, mall…).
- Participant-only chat for accepted/completed bookings, backed by
chat_messagesRLS. - UPI or cash after the ride — the app records payment status (pending / paid) but never processes money.
Trust & profile
- Post-ride ratings feed a trust score recalculated server-side from real ratings.
- Trust badges show tier, rating, completed rides, and verification signals on ride cards, booking, and profile.
- Editable profile — change your name, UPI, phone, emergency contact, college/company, and upload a profile photo (Supabase Storage). Email is locked to your login.
- Verification document submission for ID, licence, college, and company proof. Documents are stored privately in Supabase Storage and recorded as review requests.
- Money saved / earned and CO2 saved stats.
Brand & platform
- Custom OnTheWay logo mark and generated Android, iOS, web, and PWA icons.
- Realtime-ready rides, bookings, chat, notifications, and a mock backend mode for offline UI work.
- Dark-mode-first Material 3 UI with Riverpod state management.
| Layer | Choice |
|---|---|
| App | Flutter (Material 3), Riverpod DI/state, feature-first + clean architecture |
| Backend | Supabase — Auth, Postgres + PostGIS, RLS, Realtime, Storage, Edge Functions |
| Maps | OpenStreetMap via flutter_map, OpenRouteService for routing/ETA/geocoding |
| Location | geolocator |
| Payments | UPI deep links (+ cash) — status tracked, no gateway |
Route matching uses real polyline/PostGIS overlap (search_matched_rides), not straight-line distance. The map layer sits behind a MapService abstraction so a different provider can be swapped in without touching business logic.
lib/
main.dart # bootstrap: load .env, init Supabase, run app
app.dart # MaterialApp + theme + AuthGate
core/
brand/ # custom OnTheWay logo widgets
config/app_config.dart # typed env access
theme/ # colors, spacing, typography, dark/light themes
errors/
data/
models/ # UserProfile, Ride, Booking, Vehicle, TrustScore, ChatMessage, SavedCommute, …
repositories/ # RideRepository (abstract) + Mock + Supabase impls
services/ # map_service, open_route_service, location_service
features/
auth/ # auth gate + email/password screen
onboarding/ # first-run product onboarding
home/ # bottom-nav shell + ride feed + map
create_ride/ # saved commutes, vehicle picker, autocomplete, map pin, fare preview
profile/ # editable profile, avatar upload, verification submission
rides/
application/ # Riverpod providers
domain/ # pricing_engine, route_matcher
presentation/ # booking sheet, chat screen, ratings, trust badges
supabase/
migrations/ # full schema, RLS, RPCs, views, storage buckets
functions/ # Edge Functions (matching, pricing, notify, trust…)
seed.sql, *.sql # demo data + repair helpers
Prerequisites: Flutter (stable, 3.44+), a Supabase project, and a free OpenRouteService API key (optional — the app falls back to offline estimates without it).
# 1. Configure environment (public values only — never commit real keys)
cp .env.example .env
# then edit .env with your SUPABASE_URL, SUPABASE_ANON_KEY and ORS_API_KEY
# 2. Install packages
flutter pub get
# 3. Run
flutter run
.envis intentionally git-ignored and is bundled as a Flutter asset, so you must create it before building. SetUSE_MOCK_BACKEND=trueto run entirely on in-memory data (great for UI work, demos, and tests — no Supabase or network needed). For Flutter web preview, if the debugger says the main isolate is paused, press Resume in DevTools; that is a debugger state, not an app crash.
| Key | Purpose |
|---|---|
SUPABASE_URL |
Your Supabase project URL |
SUPABASE_ANON_KEY |
Publishable/anon key (safe for the client) |
ORS_API_KEY |
OpenRouteService key for routing & geocoding (optional) |
USE_MOCK_BACKEND |
true = in-memory backend, false = Supabase |
The service-role key never goes in the client .env — it lives only in supabase/.env.local (git-ignored) for migrations/function deploys.
supabase login
supabase link --project-ref <your-project-ref>
# Schema, RLS, RPCs, views, storage buckets
supabase db push --linked
# Optional: seed demo users/profiles/vehicles/rides
supabase db push --linked --include-seed --yes
# Edge Functions
supabase functions deploy match-rides
supabase functions deploy recommend-price
supabase functions deploy generate-recurring-rides
supabase functions deploy calculate-trust-score
supabase functions deploy notifyFor rapid local testing, supabase/config.toml disables email confirmations (enable_confirmations = false) so signup isn't blocked by the hosted email quota. Enable confirmations + custom SMTP before production.
Demo ride times are relative; if the feed goes quiet after a long session, refresh them:
supabase db query --linked --file supabase/refresh_demo_rides.sqlThe feed never downloads every ride in the country. The client sends its
location + a radius (default 15 km, user-adjustable 5–60 km) to the
rides_nearby(lng, lat, radius_m, limit) RPC, which uses PostGIS ST_DWithin
against the GiST index on rides.origin and returns only nearby, open,
non-expired rides ordered by distance and hard-capped. The query re-runs as the
user moves (a location stream that emits every ~300 m), when the radius changes,
and on pull-to-refresh — without global realtime fan-out or timer-based UI
resets. This keeps payloads and DB work bounded no matter how many rides exist
nationwide.
The migrations create profiles, vehicles, rides, meet points, bookings, ride locations, chat, notifications, ratings, saved commutes, verification requests, recurring templates, payment events, reports, and cache tables; enums for every status; RLS protecting participant-only data; PostGIS indexes; RPCs for matching/booking/cancellation/payment/trust; storage buckets (avatars, vehicle-photos, verification-docs); and a realtime publication.
riya@example.com / password123 (driver)
arjun@example.com / password123 (driver)
meera@example.com / password123 (rider — browse & book the seeded Delhi ride)
flutter analyze # static analysis — should report no issues
flutter test # unit + widget testsRide lifecycle rules enforced server-side:
- Passengers pick UPI-after-ride or cash-after-ride at booking; payment is only recorded, never collected.
- No two overlapping requested/accepted bookings per passenger.
- Passengers can cancel upcoming bookings (seats auto-restore); drivers can cancel their rides (bookings auto-cancel); cancelled bookings can't be marked paid.
- Chat messages are readable/writable only by ride participants through RLS.
- Saved commutes and verification requests are scoped to the signed-in user.
Admin review for verification requests · live trip tracking · richer realtime chat notifications · recurring ride generation UI · shareable ride groups · campus/company mode gating · gamified eco dashboard.
Released under the MIT License.