carpooling-ride

byyogss rockes

Build a **production-ready real-time carpooling web app** called **PRAYOMSH CARPOOL**. Tagline: **“Share the Ride. Split the Cost. Travel Smarter.”** Footer:** © 2026 PRAYOMSH. All rights reserved.** Build a real functional product, not a static/demo website. Use real database, secure backend, authentication, realtime updates and responsive premium UI. ### 1. USER ROLES Support: **Driver:** offers available car seats. **Passenger:** searches and requests rides. One user can be both. ### 2. DRIVER — OFFER RIDE Create **Offer a Ride**. Fields: - Name - Mobile - Email - Pickup - Drop - Date - Time - Car model/type - Available passenger seats Seat selector: **− 1 +** Example: 4 seats → booking → 3 → 2 → 1 → 0. When seats reach **0**, automatically set ride: **FULL** FULL rides must disappear from passenger search but remain in database. Ride statuses: **ACTIVE / FULL / CANCELLED / COMPLETED / EXPIRED** Automatically expire past rides. ### 3. PASSENGER — FIND RIDE Create **Find a Ride**. Search: - From - To - Date - Time - Seats required Example: **Ahmedabad → Sankheda** Show only rides that are active, match route/date/time and have enough seats. ### 4. LOCATION Use location autocomplete for city, area, landmark, airport, railway station and map locations. Store latitude/longitude and support nearby matching with configurable radius: **5 / 10 / 25 km** Use **Google Maps, Mapbox or OpenStreetMap**. Recommended: **PostgreSQL + PostGIS** ### 5. RIDE CARD Premium card: **Ahmedabad → Sankheda** 📅 10 Oct 2026 | 🕐 10:00 AM 👤 Driver Name | 🚗 Car Model ⭐ 4.8 | 💺 **2 Seats Available** Button: **Request Seat** Full ride: **FULL / No Seats Available** Never show FULL rides in available search. ### 6. CRITICAL SEAT LOGIC Seat count must be controlled by backend. Example: **4 → 3 → 2 → 1 → 0** At 0: - status = FULL - hide from search - disable booking - preserve history Prevent overbooking using an **atomic database transaction/locking**. If only one seat remains and two passengers book simultaneously, only one succeeds. Never trust frontend seat count. Show: **“Sorry, this ride is no longer available. The last seat was just booked.”** ### 7. BOOKING Passenger clicks **Request Seat**. Validate: - Logged-in user - Ride exists - Ride ACTIVE - Valid date - Seats available - Passenger ≠ driver - No duplicate booking Booking statuses: **PENDING / ACCEPTED / REJECTED / CANCELLED / COMPLETED** Driver can accept/reject. Accepted booking updates seats atomically. Passenger cancellation returns seats. Driver cancellation notifies passengers. ### 8. PRIVACY Never publicly expose driver's personal phone number. Before approval show: **Request Seat / Contact Driver** After approval reveal appropriate contact details. Use masked numbers where required. Never expose private data through public APIs. ### 9. AUTHENTICATION & PROFILE Implement: - Registration - Login/logout - Password reset - Email verification - Mobile/OTP verification Profile: Name, photo, verified mobile/email, rating, completed rides. Show: **✓ Mobile Verified | ✓ Email Verified** ### 10. DASHBOARDS **Driver Dashboard:** My rides, route, date/time, car, total/booked/available seats, status and passenger requests. **Passenger Dashboard:** Requested, accepted, rejected, cancelled and completed rides with booking status. ### 11. REALTIME Seat availability must update without refresh. Example: User A sees **1 Seat Available**. User B books final seat. User A automatically sees **FULL**. Use **WebSockets, Supabase Realtime or Firebase Realtime**. Do not fake realtime with timers. ### 12. NOTIFICATIONS Driver: - New request - Accepted/rejected request - Passenger cancellation - Ride reminder - Ride cancellation Passenger: - Request confirmation - Accepted/rejected - Driver cancellation - Ride changes - Reminder Support in-app and optional Email/WhatsApp/SMS. ### 13. RATINGS & REVIEWS After completed ride, both parties can rate each other: **1–5 stars + optional review** Prevent duplicate reviews. Display average rating and completed rides. ### 14. SEARCH FILTERS Filters: - Date - Time - Seats - Vehicle - Pickup radius - Driver rating Sort: **Recommended / Earliest / Nearest / Most Seats / Highest Rated** ### 15. SAFETY Include: - Mobile/email verification - Report user/ride - Block user - Help/Emergency option Reports: Fake profile, fraud, harassment, unsafe behaviour, incorrect ride. ### 16. ADMIN PANEL Secure admin dashboard with RBAC. Admin can: - View/search users - Suspend users - Manage rides - Cancel rides - View bookings - Handle reports/reviews - View statistics Statistics: Users, active rides, full rides, completed/cancelled rides, bookings and available seats. ### 17. DATABASE Use **PostgreSQL + PostGIS**. Tables: **users:** id, name, email, phone, password_hash, photo, verification status, rating, timestamps. **rides:** id, driver_id, pickup/drop + coordinates, date, time, car, total_seats, available_seats, status, timestamps. **bookings:** id, ride_id, passenger_id, seats_requested, status, timestamps. **reviews:** id, ride_id, reviewer_id, reviewee_id, rating, comment, timestamp. ### 18. TECHNOLOGY Recommended: **Frontend:** Next.js + React + TypeScript + Tailwind CSS **Backend:** Node.js + NestJS/Express + TypeScript **Database:** PostgreSQL + PostGIS **Realtime:** WebSockets/Supabase Realtime **Maps:** Google Maps/Mapbox/OpenStreetMap Keep API keys/secrets in environment variables. ### 19. SECURITY Implement: - Server-side validation - Secure password hashing - Authentication/authorization - RBAC - Rate limiting - CORS - XSS/SQL injection protection - Secure headers - Error handling - Logging Never expose passwords, tokens, hashes or private contact information. ### 20. UI/UX Create a **premium, modern, minimal, trustworthy mobility-startup design**. Use clean typography, premium cards, rounded components, subtle shadows, modern icons, map UI, smooth micro-interactions and strong CTAs. Hero: # PRAYOMSH CARPOOL **Share the Ride. Split the Cost. Travel Smarter.** “Find available rides, share your journey and connect with drivers and passengers.” Buttons: **Find a Ride** | **Offer a Ride** Fully responsive for desktop, tablet and mobile. ### 21. SEO & ACCESSIBILITY Add: - SEO title/meta - Open Graph - Sitemap - Robots.txt - Semantic HTML - Structured data where useful Title: **PRAYOMSH Carpool — Find & Share Rides** Description: **Find and share available carpool rides with PRAYOMSH. Search routes, request seats and travel smarter.** Follow WCAG: keyboard navigation, labels, accessible forms/errors, screen-reader support and good contrast. ### 22. EDGE CASES & TESTING Handle: - Driver/passenger cancellation - Duplicate booking - Final-seat race condition - Full/expired ride - Invalid date/location/seats - Unauthorized access - Network failure - Duplicate API requests - Route/time changes Test authentication, ride creation, search, booking, concurrency, realtime updates and security. ### 23. FINAL ACCEPTANCE TEST Driver: Login → Offer Ride → **Ahmedabad → Sankheda** → Date/Time → Car → **4 seats** → Publish. Passenger: Login → Find Ride → **Ahmedabad → Sankheda** → Search → Ride appears. Bookings: **4 → 3 → 2 → 1 → 0** At 0: **ACTIVE → FULL** Ride immediately disappears from available search and booking is disabled. Concurrent final-seat requests must allow only one successful booking. The final product must be **fully functional, secure, realtime, responsive, scalable and production-ready**, with no fake hardcoded production data. **PRAYOMSH CARPOOL** **© 2026 PRAYOMSH. All rights reserved.**

No preview

Comments (0)

No comments yet. Be the first!

System Requirements

Page 1 of 25

System Requirements Document for carpooling-ride

1. Introduction

PRAYOMSH CARPOOL is a production-ready, real-time carpooling web application. Its tagline is “Share the Ride. Split the Cost. Travel Smarter.” and its footer reads © 2026 PRAYOMSH. All rights reserved.

The product exists so that everyday commuters can find and share car journeys: a Driver offers available car seats on a published route, and a Passenger searches matching rides and requests a seat. The whole promise of the product is that a number — seats available — is always true, and that a stranger is verified. The system must be a real functional product, not a static or demo website: it uses a real database, a secure backend, authentication, realtime updates, and a responsive premium UI, with no fake hardcoded production data.

The audience is everyday Indian commuters on mobile plus drivers managing seat inventory — practical, price-aware, and slightly anxious about safety and reliability. The interface must therefore read as trustworthy, fast, and warm rather than corporate-neutral.

Page 2 of 25

2. System Overview

PRAYOMSH CARPOOL is a web application with three active human roles — Driver, Passenger, and Admin — where one user can be both Driver and Passenger. Drivers publish rides with pickup, drop, date, time, car model/type, and available passenger seats. Passengers search for rides by from, to, date, time, and seats required, apply filters and sorting, and request a seat. The backend owns the seat count absolutely: seat allocation happens inside an atomic database transaction with locking, so that when only one seat remains and two passengers book simultaneously, only one succeeds.

Rides carry the statuses ACTIVE / FULL / CANCELLED / COMPLETED / EXPIRED. When seats reach 0 the ride automatically becomes FULL, disappears from passenger search, disables booking, and remains in the database with its history preserved. Past rides expire automatically. Seat availability updates without refresh over WebSockets/Supabase Realtime — never faked with timers.

The product also covers authentication and profile (registration, login/logout, password reset, email verification, mobile/OTP verification), privacy (driver phone numbers never publicly exposed; contact details revealed only after approval, masked where required), notifications (in-app required; Email/WhatsApp/SMS optional), ratings and reviews after completed rides, search filters and sorting, safety (report, block, help/emergency), and a secure RBAC admin panel with platform statistics.

Page 3 of 25

2a. Product Interpretation and Delivery Boundary

Current delivery. Everything described in this document is current: the public landing entry, self-service enrollment and returning verification, driver ride publishing, passenger search and booking, both dashboards, profile, reviews, safety, and the RBAC admin panel. All of it is first-party application surface backed by a first-party secure backend and a PostgreSQL + PostGIS database.

Identity and access ownership. The application owns identity. Drivers, Passengers, and Admins establish their own accounts through self-service enrollment, then verify themselves on return. Protected ride, booking, profile, review, safety, and administrative work is reachable only after identity is established; the anonymous entry surfaces (Landing, Sign Up, Login, Account Recovery) are reachable without identity. Administrative capability is governed by RBAC, provisioned rather than self-selected.

Provider and external ownership. Map rendering and location autocomplete are owned by the chosen map provider (Google Maps, Mapbox, or OpenStreetMap) and are embedded, not reimplemented. Email, WhatsApp, and SMS notification delivery are optional external channels; in-app notification is the required channel and is application-owned. Realtime transport is provided by WebSockets or Supabase Realtime; the authoritative seat state remains application-owned in PostgreSQL.

Explicit exclusions and non-current items. No fake hardcoded production data. No timer-based fake realtime. No public exposure of driver personal phone numbers or of passwords, tokens, hashes, or private contact information through public APIs. No blue or indigo anywhere in the interface. No stock photography of people, no decorative illustration, no gradient-blob or glassmorphism treatment. Nothing in this document is deferred to a future horizon; there is no accepted future-phase requirement in the source.

Page 4 of 25

2b. Source Content Inventory

Not applicable — no reference directive in this project declares a content_source.

2c. Page Content and Component Coverage

Landing

  • Information and state. Anonymous public entry. Displays the wordmark PRAYOMSH CARPOOL, the tagline “Share the Ride. Split the Cost. Travel Smarter.”, the supporting line “Find available rides, share your journey and connect with drivers and passengers.”, and the two entry actions Find a Ride and Offer a Ride. Carries the footer © 2026 PRAYOMSH. All rights reserved.
  • Primary actions. Find a Ride (routes toward passenger search), Offer a Ride (routes toward driver ride publishing), and navigation to Sign Up / Login.
  • Supporting actions. A live “Right now” panel showing real rides as ruled rows (route in ink, date/time in muted, available seats as a large tangerine tabular numeral), headed by a small uppercase label with a pulsing 6px green dot. The seat-logic strip 4 → 3 → 2 → 1 → 0 sits on a full-bleed hairline rule directly beneath the hero, with the final 0 outlined in tangerine and tagged FULL.
  • Domain entities. Ride (route, date, time, available seats), Driver (name, car model, rating).
  • Component responsibilities. Split hero (left 7 columns: stacked wordmark with the second line indented one grid column, tagline, supporting line, two buttons on one baseline; right 5 columns: live rides panel). Seat-count rail. Footer.
  • States. Loading: the live panel shows its last server-confirmed values with a timestamp rather than a skeleton. Empty: when no rides are currently available, the panel states that plainly and offers Find a Ride. Success: real rides render as ruled rows. Error: if the live feed is unreachable, the panel shows the last confirmed values and a muted note that the feed is stale. Recovery: the panel reconnects and refreshes on the next confirmed server update.

Sign Up

  • Information and state. Anonymous enrollment surface. Collects the identity information needed to create an account and begin verification.
  • Primary actions. Create account; proceed to email verification and mobile/OTP verification.
  • Supporting actions. Navigate to Login; navigate to Account Recovery.
  • Domain entities. User (name, email, phone, password, photo, verification status).
  • Component responsibilities. Enrollment form with labeled fields and accessible inline errors; verification entry points for email and mobile OTP.
  • States. Loading: submit control shows in-progress state and prevents duplicate submission. Empty: initial blank form. Success: account created, verification steps presented. Error: field-level and form-level accessible errors for invalid or already-used details. Recovery: the user can correct fields and resubmit; verification can be re-requested.
Page 5 of 25

Login

  • Information and state. Anonymous returning-verification surface for Drivers, Passengers, and Admins.
  • Primary actions. Sign in; sign out is available from authenticated surfaces.
  • Supporting actions. Navigate to Sign Up; navigate to Account Recovery.
  • Domain entities. User, session.
  • Component responsibilities. Credential form with labeled fields; accessible error region; rate-limited submission.
  • States. Loading: submit in progress, duplicate submission blocked. Empty: initial blank form. Success: session established and the user continues to the destination they were seeking. Error: accessible message for invalid credentials without revealing which factor failed. Recovery: retry, or move to Account Recovery.

Account Recovery

  • Information and state. Anonymous password-reset surface.
  • Primary actions. Request a reset; set a new password.
  • Supporting actions. Return to Login.
  • Domain entities. User, reset token.
  • Component responsibilities. Request form; reset form; accessible confirmation and error regions.
  • States. Loading: request/submit in progress. Empty: initial request form. Success: confirmation that reset instructions were sent, and confirmation that the password was changed. Error: accessible error for invalid or expired reset token. Recovery: request a new reset link.

Offer a Ride

  • Information and state. Driver ride-publishing surface. Fields: Name, Mobile, Email, Pickup, Drop, Date, Time, Car model/type, Available passenger seats. Pickup and Drop use location autocomplete covering city, area, landmark, airport, railway station, and map locations, and store latitude/longitude.
  • Primary actions. Publish the ride. Seat selector uses the − 1 + control.
  • Supporting actions. Adjust the seat count with the circular − and + buttons; select pickup and drop from autocomplete suggestions; pick date and time.
  • Domain entities. Ride (driver_id, pickup/drop + coordinates, date, time, car, total_seats, available_seats, status), User.
  • Component responsibilities. Ride form; location autocomplete inputs with map assistance; seat stepper; publish control; accessible validation region.
  • States. Loading: autocomplete queries and publish submission show in-progress state. Empty: blank form with the seat stepper at its starting value. Success: the ride is published as ACTIVE with its seat count, and appears in the Driver Dashboard. Error: accessible errors for invalid date, invalid location, invalid seats, or unauthorized access. Recovery: correct the field and republish; duplicate API requests do not create duplicate rides.
Page 6 of 25

Find a Ride

  • Information and state. Passenger search surface. Search fields: From, To, Date, Time, Seats required. Filters: date, time, seats, vehicle, pickup radius, driver rating. Pickup radius is a configurable 5 / 10 / 25 km segmented control. Sort options: Recommended / Earliest / Nearest / Most Seats / Highest Rated. Results are a dense single-column list of ride cards with a sticky map panel on desktop and a full-width collapsible sheet on mobile.
  • Primary actions. Search; apply filters; change sort; Request Seat on a ride card.
  • Supporting actions. Select From/To via location autocomplete; set the pickup radius; open the map panel; read the ride card.
  • Domain entities. Ride, User (driver name, car model, rating), Booking.
  • Component responsibilities. Single-rail search bar (From, To, Date, Time, Seats as five inline fields divided by 1px vertical rules, black Search block pinned right, radius segmented control beneath); filter and sort controls; ride card list; sticky map panel with ink route polylines, tangerine pickup pin, black drop pin, muted grey tiles.
  • Ride card content. Route (e.g. Ahmedabad → Sankheda), date and time (e.g.\x20\xf0\x9f\x93\x85 10 Oct 2026 |\x20\xf0\x9f\x95\x90 10:00 AM), driver name, car model, rating (e.g.\x20\xe2\xad\x90 4.8), and seats available (e.g.\x20\xf0\x9f\x92\xba 2 Seats Available), with a Request Seat button. A full ride shows FULL / No Seats Available.
  • States. Loading: the search rail and results show in-progress state; the ride card always shows the last server-confirmed integer with its timestamp rather than hiding the seat truth behind a skeleton after first paint. Empty: no matching rides — a plain statement plus a suggestion to widen the radius or change the date. Success: only rides that are active, match route/date/time, and have enough seats are listed; FULL rides never appear. Error: accessible error for invalid date, invalid location, or invalid seats; network failure surfaces a retry. Recovery: retry the search; when the last seat is taken the message “Sorry, this ride is no longer available. The last seat was just booked.” is shown and the card updates to FULL.

Driver Dashboard

  • Information and state. Driver's operational surface. Shows my rides, route, date/time, car, total/booked/available seats, status and passenger requests. Rows are ruled data rows — label left, monospace value right, 1px rule between rows — not floating tiles. Ride status is rendered as text plus a 6px dot.
  • Primary actions. Accept or reject a passenger request; cancel a ride; mark a ride completed.
  • Supporting actions. Review passenger requests; read ride status; read notifications.
  • Domain entities. Ride, Booking, User, Notification.
  • Component responsibilities. Ruled ride rows with total/booked/available seat figures; passenger request list with accept/reject controls; status indicator; notification area.
  • States. Loading: rows show last confirmed values. Empty: no rides yet — a plain statement plus a link to Offer a Ride. Success: accepted requests update seats atomically and the available-seat numeral flips; rejected requests leave seats unchanged. Error: accessible error when a request can no longer be accepted (ride full, cancelled, or expired). Recovery: refresh from server-confirmed state; the driver is notified of passenger cancellations and ride changes.

Passenger Dashboard

  • Information and state. Passenger's booking surface. Shows requested, accepted, rejected, cancelled and completed rides with booking status. Booking statuses are PENDING / ACCEPTED / REJECTED / CANCELLED / COMPLETED.
  • Primary actions. Cancel a booking; rate a completed ride; open approved contact details.
  • Supporting actions. Read booking status; read notifications; navigate to Find a Ride.
  • Domain entities. Booking, Ride, User, Notification, Review.
  • Component responsibilities. Ruled booking rows with status text plus 6px dot; cancellation control; approved-contact panel; notification area.
  • States. Loading: rows show last confirmed values. Empty: no bookings yet — a plain statement plus a link to Find a Ride. Success: cancellation returns seats and the ride's available count updates; approved bookings reveal appropriate contact details. Error: accessible error when a booking can no longer be cancelled. Recovery: refresh from server-confirmed state; the passenger is notified of driver cancellations, ride changes, and reminders.
Page 7 of 25

Profile

  • Information and state. Shows Name, photo, verified mobile/email, rating, completed rides, and displays ✓ Mobile Verified | ✓ Email Verified. Driver avatars are initials in a 1px-bordered square, not a circle.
  • Primary actions. Update profile details and photo; complete mobile/OTP verification; complete email verification.
  • Supporting actions. Read rating and completed-ride count.
  • Domain entities. User (id, name, email, phone, password_hash, photo, verification status, rating, timestamps).
  • Component responsibilities. Profile header with initials square; verification badges; rating and completed-rides figures in monospace tabular numerals; verification entry points.
  • States. Loading: last confirmed profile values. Empty: unverified state shows the verification prompts instead of the check marks. Success: verified badges render as ✓ Mobile Verified | ✓ Email Verified. Error: accessible error when a verification code is invalid or expired. Recovery: re-request verification.

Reviews

  • Information and state. Post-completion reciprocal rating surface. After a completed ride, both parties can rate each other 1–5 stars + optional review. Displays average rating and completed rides.
  • Primary actions. Submit a rating and optional review.
  • Supporting actions. Read the counterparty's average rating and completed rides.
  • Domain entities. Review (id, ride_id, reviewer_id, reviewee_id, rating, comment, timestamp), Ride, User.
  • Component responsibilities. Star selector; optional review field; submitted-review display; duplicate-prevention state.
  • States. Loading: submission in progress. Empty: no completed rides awaiting review. Success: review recorded and the counterparty's average rating updates. Error: accessible error when a review already exists for that ride and counterparty. Recovery: the existing review is shown instead of a new form.

Safety

  • Information and state. Reporting, blocking, and help/emergency surface. Report categories: fake profile, fraud, harassment, unsafe behaviour, incorrect ride.
  • Primary actions. Report a user or ride; block a user; open the help/emergency option.
  • Supporting actions. Select a report category; add detail.
  • Domain entities. Report, Block, User, Ride.
  • Component responsibilities. Report form with category selection; block control; help/emergency entry point.
  • States. Loading: submission in progress. Empty: no reports filed. Success: confirmation that the report was received. Error: accessible error on failed submission. Recovery: retry submission.
Page 8 of 25

Admin Panel

  • Information and state. Secure administrative surface governed by RBAC. Provides user search and viewing, ride management, booking viewing, report and review handling, and statistics. Statistics are a single editorial band of large monospace numerals separated by vertical rules: Users · Active · Full · Completed · Cancelled · Bookings · Seats Open.
  • Primary actions. Suspend users; manage rides; cancel rides; handle reports and reviews.
  • Supporting actions. View/search users; view bookings; read statistics.
  • Domain entities. User, Ride, Booking, Report, Review, statistics aggregates.
  • Component responsibilities. User search and list; ride management controls; booking list; report and review queues; statistics band.
  • States. Loading: last confirmed values. Empty: empty queues state that plainly. Success: suspension, cancellation, and moderation actions take effect and statistics update. Error: accessible error when an action is not permitted by the admin's role. Recovery: the action is refused with an explanation and the panel returns to confirmed state.
Page 9 of 25

3. Functional Requirements

Each requirement is a distinct story point with provenance, lifecycle facts, and observable acceptance.

FR-1 — Product identity and footer. As a visitor I should see the product named PRAYOMSH CARPOOL with the tagline “Share the Ride. Split the Cost. Travel Smarter.” and the footer © 2026 PRAYOMSH. All rights reserved., so that I know what the product is and who owns it. Provenance: explicit. Trigger: any page render. Observable result: the wordmark, tagline, and footer text are present. Failure/recovery: none material. Continuation: the visitor proceeds to Find a Ride or Offer a Ride.

FR-2 — Real functional product. As a user I should use a real product backed by a real database, secure backend, authentication, realtime updates, and a responsive premium UI, so that my rides and bookings are real. Provenance: explicit. Constraint: no fake hardcoded production data. Observable result: all ride, booking, review, and user data is persisted and retrieved from the database. Failure/recovery: database unavailability surfaces an error rather than fabricated data.

FR-3 — Dual roles. As a user I should act as a Driver who offers available car seats and as a Passenger who searches and requests rides, so that one account can do both. Provenance: explicit. Observable result: the same account can publish rides and request seats on other rides. Constraint: a passenger must not be the driver on their own booking.

FR-4 — Offer a Ride. As a Driver I should create an Offer a Ride with Name, Mobile, Email, Pickup, Drop, Date, Time, Car model/type, and Available passenger seats, so that passengers can find my journey. Provenance: explicit. Trigger: driver opens Offer a Ride. Observable result: the ride is published with status ACTIVE. Failure/recovery: invalid date, invalid location, or invalid seats produce accessible errors and no ride is created. Continuation: the ride appears in the Driver Dashboard.

FR-5 — Seat selector. As a Driver I should set available passenger seats with a − 1 + control, so that the offered seat count is exact. Provenance: explicit. Example: 4 seats → booking → 3 → 2 → 1 → 0. Observable result: the stepper value is the ride's total seat count at publish time.

FR-6 — Automatic FULL at zero. As the system I should automatically set a ride to FULL when seats reach 0, so that no further booking is possible. Provenance: explicit. Observable result: status becomes FULL. Constraint: FULL rides must disappear from passenger search but remain in the database.

FR-7 — Ride statuses and expiry. As the system I should maintain ride statuses ACTIVE / FULL / CANCELLED / COMPLETED / EXPIRED and automatically expire past rides, so that stale rides never appear as available. Provenance: explicit. Observable result: a ride whose date/time has passed becomes EXPIRED without manual action.

FR-8 — Find a Ride search. As a Passenger I should search Find a Ride by From, To, Date, Time, and Seats required, so that I find a matching journey. Provenance: explicit. Example: Ahmedabad → Sankheda. Observable result: matching rides are listed.

FR-9 — Search result eligibility. As a Passenger I should see only rides that are active, match route/date/time, and have enough seats, so that every listed ride is bookable. Provenance: explicit. Constraint: never show FULL rides in available search.

FR-10 — Location autocomplete and coordinates. As a Driver or Passenger I should use location autocomplete for city, area, landmark, airport, railway station, and map locations, so that I can specify real places. Provenance: explicit. Observable result: latitude/longitude are stored for pickup and drop.

FR-11 — Nearby matching with configurable radius. As a Passenger I should match nearby rides within a configurable radius of 5 / 10 / 25 km, so that I can widen or narrow my search. Provenance: explicit. Observable result: results respect the selected radius.

FR-12 — Map provider. As a user I should see map and location services from Google Maps, Mapbox, or OpenStreetMap, so that routes and places are visualized. Provenance: explicit. Constraint: PostgreSQL + PostGIS is the recommended spatial store.

FR-13 — Ride card. As a Passenger I should see a premium ride card showing route, date and time, driver name, car model, rating, and seats available with a Request Seat button, so that I can evaluate and act on a ride. Provenance: explicit. Example content: Ahmedabad → Sankheda,\x20\xf0\x9f\x93\x85 10 Oct 2026 |\x20\xf0\x9f\x95\x90 10:00 AM,\x20\xf0\x9f\x91\xa4 Driver Name |\x20\xf0\x9f\x9a\x97 Car Model,\x20\xe2\xad\x90 4.8 |\x20\xf0\x9f\x92\xba 2 Seats Available. Full ride shows FULL / No Seats Available.

FR-14 — Backend-owned seat count. As the system I should control seat count in the backend, so that the displayed number is always true. Provenance: explicit. Constraint: never trust frontend seat count.

FR-15 — Zero-seat consequences. As the system I should, at 0 seats, set status = FULL, hide the ride from search, disable booking, and preserve history, so that the ride is closed but auditable. Provenance: explicit.

FR-16 — Atomic overbooking prevention. As the system I should prevent overbooking using an atomic database transaction/locking, so that if only one seat remains and two passengers book simultaneously, only one succeeds. Provenance: explicit. Observable result: exactly one booking succeeds; the other receives the last-seat message.

FR-17 — Last-seat message. As a Passenger I should see “Sorry, this ride is no longer available. The last seat was just booked.” when the last seat is taken, so that I understand why my request failed. Provenance: explicit.

FR-18 — Request Seat validation. As a Passenger I should click Request Seat and have the system validate logged-in user, ride exists, ride ACTIVE, valid date, seats available, passenger ≠ driver, and no duplicate booking, so that only valid requests are created. Provenance: explicit. Failure/recovery: each failed validation produces an accessible explanation and no booking is created.

FR-19 — Booking statuses and driver decision. As a Driver I should accept or reject a request, and bookings should carry statuses PENDING / ACCEPTED / REJECTED / CANCELLED / COMPLETED, so that both parties know where the booking stands. Provenance: explicit.

FR-20 — Atomic seat update on acceptance. As the system I should update seats atomically when a booking is accepted, so that the seat count never drifts. Provenance: explicit.

FR-21 — Passenger cancellation returns seats. As a Passenger I should cancel a booking and have the seats returned, so that the seat becomes available again. Provenance: explicit. Observable result: available seats increase and the ride may return from FULL to ACTIVE when seats become available.

FR-22 — Driver cancellation notifies passengers. As a Driver I should cancel a ride and have passengers notified, so that nobody is left waiting. Provenance: explicit. Observable result: the ride becomes CANCELLED and each affected passenger receives a notification.

FR-23 — Phone privacy. As a Driver I should never have my personal phone number publicly exposed, so that my privacy is protected. Provenance: explicit. Constraint: never expose private data through public APIs.

FR-24 — Pre-approval and post-approval contact. As a Passenger I should see Request Seat / Contact Driver before approval and have appropriate contact details revealed after approval, so that contact happens only when the driver has accepted. Provenance: explicit. Constraint: use masked numbers where required.

FR-25 — Authentication. As a user I should register, log in, log out, reset my password, verify my email, and verify my mobile by OTP, so that my account is real and recoverable. Provenance: explicit.

FR-26 — Profile. As a user I should see Name, photo, verified mobile/email, rating, and completed rides, displayed as ✓ Mobile Verified | ✓ Email Verified, so that I can judge and be judged on trust. Provenance: explicit.

FR-27 — Driver Dashboard. As a Driver I should see my rides, route, date/time, car, total/booked/available seats, status, and passenger requests, so that I can run my seat inventory. Provenance: explicit.

FR-28 — Passenger Dashboard. As a Passenger I should see requested, accepted, rejected, cancelled, and completed rides with booking status, so that I can track every request. Provenance: explicit.

FR-29 — Realtime seat availability. As a user I should see seat availability update without refresh, so that I never act on a stale number. Provenance: explicit. Example: User A sees 1 Seat Available; User B books the final seat; User A automatically sees FULL. Constraint: use WebSockets, Supabase Realtime, or Firebase Realtime; do not fake realtime with timers.

FR-30 — Driver notifications. As a Driver I should receive notifications for new request, accepted/rejected request, passenger cancellation, ride reminder, and ride cancellation, so that I can respond in time. Provenance: explicit.

FR-31 — Passenger notifications. As a Passenger I should receive notifications for request confirmation, accepted/rejected, driver cancellation, ride changes, and reminder, so that I know the state of my journey. Provenance: explicit.

FR-32 — Notification channels. As a user I should receive in-app notifications and optionally Email/WhatsApp/SMS, so that I am reachable on the channel I prefer. Provenance: explicit. Constraint: in-app is required; Email/WhatsApp/SMS are optional.

FR-33 — Ratings and reviews. As a Driver or Passenger I should rate the other party 1–5 stars with an optional review after a completed ride, so that trust accumulates. Provenance: explicit. Constraint: prevent duplicate reviews. Observable result: average rating and completed rides are displayed.

FR-34 — Search filters. As a Passenger I should filter by date, time, seats, vehicle, pickup radius, and driver rating, so that I narrow results to what I need. Provenance: explicit.

FR-35 — Sort options. As a Passenger I should sort by Recommended / Earliest / Nearest / Most Seats / Highest Rated, so that the best ride for me comes first. Provenance: explicit.

FR-36 — Safety features. As a user I should have mobile/email verification, report user/ride, block user, and a help/emergency option, so that I can protect myself. Provenance: explicit. Report categories: fake profile, fraud, harassment, unsafe behaviour, incorrect ride.

FR-37 — Admin panel with RBAC. As an Admin I should use a secure admin dashboard with RBAC to view/search users, suspend users, manage rides, cancel rides, view bookings, handle reports/reviews, and view statistics, so that platform integrity is maintained. Provenance: explicit.

FR-38 — Admin statistics. As an Admin I should see statistics for users, active rides, full rides, completed/cancelled rides, bookings, and available seats, so that I can judge platform health. Provenance: explicit.

FR-39 — Database schema. As the system I should store data in PostgreSQL + PostGIS with the tables users (id, name, email, phone, password_hash, photo, verification status, rating, timestamps), rides (id, driver_id, pickup/drop + coordinates, date, time, car, total_seats, available_seats, status, timestamps), bookings (id, ride_id, passenger_id, seats_requested, status, timestamps), and reviews (id, ride_id, reviewer_id, reviewee_id, rating, comment, timestamp), so that all product state is durable and spatially queryable. Provenance: explicit.

FR-40 — Security controls. As the system I should implement server-side validation, secure password hashing, authentication/authorization, RBAC, rate limiting, CORS, XSS/SQL injection protection, secure headers, error handling, and logging, so that the platform is safe. Provenance: explicit. Constraint: never expose passwords, tokens, hashes, or private contact information.

FR-41 — Premium responsive UI. As a user I should use a premium, modern, minimal, trustworthy mobility-startup interface with clean typography, premium cards, rounded components, subtle shadows, modern icons, map UI, smooth micro-interactions, and strong CTAs, fully responsive for desktop, tablet, and mobile, so that the product feels dependable. Provenance: explicit.

FR-42 — Hero. As a visitor I should see the hero PRAYOMSH CARPOOL with the tagline “Share the Ride. Split the Cost. Travel Smarter.”, the line “Find available rides, share your journey and connect with drivers and passengers.”, and the buttons Find a Ride | Offer a Ride, so that I can start immediately. Provenance: explicit.

FR-43 — SEO and accessibility. As a visitor I should get SEO title/meta, Open Graph, sitemap, robots.txt, semantic HTML, and structured data where useful, with title “PRAYOMSH Carpool — Find & Share Rides” and description “Find and share available carpool rides with PRAYOMSH. Search routes, request seats and travel smarter.”, and WCAG-following keyboard navigation, labels, accessible forms/errors, screen-reader support, and good contrast, so that the product is findable and usable by everyone. Provenance: explicit.

FR-44 — Edge cases. As the system I should handle driver/passenger cancellation, duplicate booking, final-seat race condition, full/expired ride, invalid date/location/seats, unauthorized access, network failure, duplicate API requests, and route/time changes, so that the product stays correct under stress. Provenance: explicit.

FR-45 — Testing. As the team I should test authentication, ride creation, search, booking, concurrency, realtime updates, and security, so that the product is verifiably production-ready. Provenance: explicit.

FR-46 — Final acceptance test. As the team I should verify: Driver login → Offer Ride → Ahmedabad → Sankheda → Date/Time → Car → 4 seats → Publish; Passenger login → Find Ride → Ahmedabad → Sankheda → Search → ride appears; bookings 4 → 3 → 2 → 1 → 0; at 0 ACTIVE → FULL; the ride immediately disappears from available search and booking is disabled; concurrent final-seat requests allow only one successful booking. Provenance: explicit.

FR-47 — Production readiness. As the team I should deliver a fully functional, secure, realtime, responsive, scalable, and production-ready product with no fake hardcoded production data. Provenance: explicit.

FR-48 — Self-service enrollment. As a Driver or Passenger I should be able to start independently by creating my own account, so that I can use the product without an invitation. Provenance: required_inference. Trigger: anonymous visitor chooses to start. Observable result: an account exists and verification can begin. Continuation: verification, then protected work.

FR-49 — Returning verification. As a returning Driver, Passenger, or Admin I should verify myself before protected ride, booking, profile, review, safety, or administrative work, so that my durable state stays bound to me. Provenance: required_inference. Observable result: a session is established and the user reaches the destination they were seeking. Failure/recovery: invalid credentials produce an accessible error and the user can retry or recover the account.

FR-50 — Verification completion. As a user I should complete password recovery, email verification, and mobile OTP verification, so that my account is recoverable and my trust signals are real. Provenance: required_inference. Observable result: the profile shows ✓ Mobile Verified | ✓ Email Verified.

FR-51 — RBAC provisioning. As the system I should provision and enforce role-based access for Admin responsibilities, so that administrative capability is not self-selected. Provenance: required_inference. Observable result: only an Admin reaches the Admin Panel; other roles are refused with an accessible explanation.

FR-52 — Transactional seat allocation. As the system I should perform seat allocation and duplicate-booking prevention inside a backend transaction with locking, so that concurrent requests cannot both succeed. Provenance: required_inference. Observable result: exactly one of two simultaneous final-seat requests succeeds.

FR-53 — Realtime backend updates. As the system I should push availability and ride-status changes from the backend, so that every connected client converges on the same confirmed state. Provenance: required_inference. Observable result: the seat numeral and status change on all affected surfaces without refresh.

FR-54 — Automatic expiry processing. As the system I should process past rides automatically, so that EXPIRED rides never appear as available. Provenance: required_inference. Observable result: a ride past its date/time becomes EXPIRED without manual action.

FR-55 — Approved booking state gates contact. As the system I should require an approved booking state before revealing appropriate driver contact details, so that contact is never exposed before approval. Provenance: required_inference. Observable result: before approval the passenger sees Request Seat / Contact Driver; after approval the appropriate details are revealed, masked where required.

Page 10 of 25

4. User Personas

Page 11 of 25

Driver

Product context. The Driver offers available car seats. They publish a journey they are already making and manage the seat inventory on it. They are practical and price-aware: the point of offering seats is to split the cost of a trip they are taking anyway.

Primary goal. Fill the offered seats correctly — without overbooking, without a stale seat number, and without being contacted by strangers before they have accepted a request.

Distinct accepted responsibilities. Publishing a ride through Offer a Ride with Name, Mobile, Email, Pickup, Drop, Date, Time, Car model/type, and Available passenger seats, using the − 1 + seat selector. Managing that ride's seat count and status across ACTIVE / FULL / CANCELLED / COMPLETED / EXPIRED. Accepting or rejecting passenger requests. Cancelling a ride when plans change. Marking a ride completed. Rating the passenger after a completed ride.

Relevant inputs and decisions. Pickup and drop chosen through location autocomplete; date and time; car model/type; the number of seats to offer; which requests to accept when seats are scarce; whether to cancel.

Interactions with other accepted participants. With Passengers, whose requests the Driver accepts or rejects and whose cancellations return seats to the ride. With the system, which owns the seat count and flips the ride to FULL at zero. With the Admin, who can manage or cancel rides and suspend users.

Observable success. Seats are filled correctly with no overbooking; the available-seat figure is always the server-confirmed integer; past rides expire automatically; the Driver Dashboard shows my rides, route, date/time, car, total/booked/available seats, status, and passenger requests; the Driver is notified of new requests, cancellations, reminders, and ride changes; and completed rides can be rated.

Source-backed constraints. The Driver's personal phone number is never publicly exposed; contact details are revealed only after approval, masked where required. The Driver cannot be the passenger on their own ride.

Page 12 of 25

Passenger

Product context. The Passenger searches for a ride that matches a journey they need to make and requests a seat on it. They are slightly anxious about safety and reliability: they want to know the ride is real, the driver is verified, and the seat they are requesting actually exists.

Primary goal. Secure a seat on a matching ride, know exactly where the request stands, and reach the driver only once the request has been approved.

Distinct accepted responsibilities. Searching Find a Ride by From, To, Date, Time, and Seats required. Applying filters for date, time, seats, vehicle, pickup radius, and driver rating, and sorting by Recommended / Earliest / Nearest / Most Seats / Highest Rated. Reading ride cards and clicking Request Seat. Tracking requested, accepted, rejected, cancelled, and completed rides with booking status in the Passenger Dashboard. Cancelling a booking, which returns seats. Rating the driver after a completed ride. Reporting or blocking a user or ride, and using the help/emergency option.

Relevant inputs and decisions. From and To chosen through location autocomplete; date and time; seats required; pickup radius of 5 / 10 / 25 km; which ride to request; whether to cancel.

Interactions with other accepted participants. With the Driver, who accepts or rejects the request and whose contact details are revealed only after approval. With the system, which validates the request and owns the seat count. With the Admin, who handles reports and reviews.

Observable success. A seat is secured on a matching ride; the seat count the Passenger saw was true at the moment of booking; FULL rides never appeared in search; contact details were revealed only after approval; the Passenger is notified of request confirmation, accept/reject outcomes, driver cancellations, ride changes, and reminders; and the completed ride can be rated.

Source-backed constraints. The Passenger must be logged in to request a seat, must not be the driver of the ride, and cannot create a duplicate booking.

Page 13 of 25

Admin

Product context. The Admin operates the secure admin dashboard with RBAC. Their work is governance rather than travel: they keep the marketplace honest so that Drivers and Passengers can trust each other.

Primary goal. Maintain platform safety and integrity through moderation of users, rides, reports, and reviews.

Distinct accepted responsibilities. Viewing and searching users. Suspending users. Managing rides and cancelling rides. Viewing bookings. Handling reports and reviews. Viewing statistics for users, active rides, full rides, completed/cancelled rides, bookings, and available seats.

Relevant inputs and decisions. Which users to suspend; which rides to cancel; how to resolve a report in the categories fake profile, fraud, harassment, unsafe behaviour, or incorrect ride; which reviews require action.

Interactions with other accepted participants. With Drivers and Passengers, whose accounts, rides, bookings, reports, and reviews the Admin moderates. With the system, which enforces RBAC and supplies the statistics.

Observable success. Reports and reviews are handled, abusive or fraudulent accounts are suspended, problematic rides are cancelled, and the statistics band reflects the true state of the platform.

Source-backed constraints. Administrative capability is governed by RBAC and is not self-selected. The Admin never sees passwords, tokens, hashes, or private contact information.

5. Core User Flows

Page 14 of 25

Flow 1 — Driver publishes a ride (Driver)

  1. The Driver opens Login and signs in with their credentials. The system establishes a session and returns the Driver to the destination they were seeking.
  2. The Driver opens Offer a Ride.
  3. The Driver enters Name, Mobile, Email.
  4. The Driver types a Pickup and selects a suggestion from location autocomplete (city, area, landmark, airport, railway station, or map location). Latitude/longitude are captured. The Driver does the same for Drop.
  5. The Driver selects Date and Time.
  6. The Driver enters the Car model/type.
  7. The Driver sets Available passenger seats with the − 1 + seat selector — for example 4 seats.
  8. The Driver publishes. The ride is created with status ACTIVE and appears in the Driver Dashboard with its route, date/time, car, total/booked/available seats, and status.
  9. Failure and recovery. If the date is invalid, a location is unresolved, or the seat count is invalid, the form shows accessible errors and no ride is created. If the network fails or the request is duplicated, no duplicate ride is created; the Driver retries and the single ride stands.
  10. Continuation. The Driver waits for passenger requests, which arrive as notifications and appear in the Driver Dashboard.

Flow 2 — Passenger finds a ride and requests a seat (Passenger)

  1. The Passenger opens Login and signs in. The system establishes a session.
  2. The Passenger opens Find a Ride.
  3. In the single-rail search bar the Passenger enters From and To using location autocomplete — for example Ahmedabad → Sankheda — plus Date, Time, and Seats required.
  4. The Passenger optionally sets the pickup radius to 5 / 10 / 25 km and applies filters for date, time, seats, vehicle, and driver rating, and chooses a sort: Recommended / Earliest / Nearest / Most Seats / Highest Rated.
  5. The Passenger searches. The system returns only rides that are ACTIVE, match route/date/time, and have enough seats. FULL rides never appear.
  6. The Passenger reads a ride card: route, date and time, driver name, car model, rating, and seats available, with a Request Seat button. The map panel shows the route with an ink polyline, a tangerine pickup pin, and a black drop pin.
  7. The Passenger clicks Request Seat. The backend validates that the user is logged in, the ride exists, the ride is ACTIVE, the date is valid, seats are available, the passenger is not the driver, and no duplicate booking exists.
  8. The booking is created with status PENDING. The Passenger receives a request confirmation notification, and the booking appears in the Passenger Dashboard as requested.
  9. Failure and recovery. If the last seat was taken between the search and the request, the Passenger sees “Sorry, this ride is no longer available. The last seat was just booked.” and the card updates to FULL / No Seats Available. If the ride has expired or been cancelled, the request is refused with an accessible explanation. If the network fails, the Passenger retries without creating a duplicate booking.
  10. Continuation. The Passenger waits for the Driver's decision, watching the booking status in the Passenger Dashboard.
Page 15 of 25

Flow 3 — Driver accepts or rejects a request (Driver and Passenger)

  1. The Driver receives a new request notification and opens the Driver Dashboard.
  2. The Driver reviews the passenger request against the ride's total/booked/available seats and status.
  3. The Driver accepts. The system updates the seats atomically inside a transaction: the available count moves 4 → 3, and the ride remains ACTIVE while seats remain.
  4. The Passenger receives an accepted notification and the booking status becomes ACCEPTED in the Passenger Dashboard. Appropriate contact details are now revealed to the Passenger, masked where required.
  5. Alternative — the Driver rejects. The booking becomes REJECTED, seats are unchanged, and the Passenger receives a rejected notification.
  6. Failure and recovery. If the ride has become FULL, cancelled, or expired before the Driver acts, the accept is refused with an accessible explanation and the request cannot be accepted.
  7. Continuation. The Driver continues accepting requests until seats reach 0.

Flow 4 — Seats reach zero and the ride becomes FULL (Driver, Passenger, and system)

  1. The Driver accepts the final request on a ride with one seat remaining. The system updates seats atomically: 1 → 0.
  2. At 0 seats the system automatically sets the ride status to FULL, hides it from passenger search, disables booking, and preserves the ride's history in the database.
  3. Every connected client converges without refresh: a Passenger who was looking at 1 Seat Available automatically sees FULL. The available-seat numeral flips like a mechanical counter and the affected card takes a brief tangerine hairline flash.
  4. The ride remains visible in the Driver Dashboard with status FULL and its full booking history.
  5. Failure and recovery. If two Passengers request the final seat simultaneously, the atomic transaction with locking allows exactly one to succeed; the other receives “Sorry, this ride is no longer available. The last seat was just booked.”
  6. Continuation. The Driver proceeds toward the journey; the ride later becomes COMPLETED or EXPIRED.

Flow 5 — Passenger cancels a booking (Passenger and Driver)

  1. The Passenger opens the Passenger Dashboard and finds the booking.
  2. The Passenger cancels it. The booking becomes CANCELLED and the seats are returned to the ride atomically.
  3. The Driver receives a passenger cancellation notification, and the Driver Dashboard's available-seat figure increases. If the ride had been FULL, it returns to ACTIVE and reappears in passenger search.
  4. Failure and recovery. If the booking can no longer be cancelled, the Passenger sees an accessible explanation and the booking stays in its confirmed state.
  5. Continuation. The Passenger can search again from Find a Ride.
Page 16 of 25

Flow 6 — Driver cancels a ride (Driver and Passenger)

  1. The Driver opens the Driver Dashboard and cancels a ride.
  2. The ride becomes CANCELLED and disappears from passenger search.
  3. Every affected Passenger receives a driver cancellation notification, and the booking statuses reflect the cancellation in their Passenger Dashboards.
  4. Failure and recovery. If the cancellation cannot be applied, the Driver sees an accessible explanation and the ride stays in its confirmed state.
  5. Continuation. Affected Passengers return to Find a Ride to find another ride.

Flow 7 — Ride changes and reminders (Driver and Passenger)

  1. The Driver changes a ride's route or time. The system records the change and the ride's status and seat figures remain authoritative.
  2. Passengers on that ride receive a ride changes notification.
  3. Before departure, both the Driver and the Passengers receive a ride reminder.
  4. Failure and recovery. If a change makes a ride invalid (for example an invalid date or location), the change is refused with an accessible error and the previous confirmed values stand.
  5. Continuation. The journey proceeds; afterwards the ride becomes COMPLETED.

Flow 8 — Ratings and reviews after a completed ride (Driver and Passenger)

  1. A ride reaches COMPLETED.
  2. The Passenger opens Reviews and rates the Driver 1–5 stars with an optional review.
  3. The Driver opens Reviews and rates the Passenger 1–5 stars with an optional review.
  4. The system records each review and updates the counterparty's average rating and completed-rides count, which are displayed on Profile and on ride cards.
  5. Failure and recovery. If a review already exists for that ride and counterparty, the system prevents the duplicate and shows the existing review instead of a new form.
  6. Continuation. The updated rating appears on future ride cards and profiles.
Page 17 of 25

Flow 9 — Verification and profile (Driver and Passenger)

  1. A new user opens Sign Up and creates an account with the required identity information.
  2. The user completes email verification and mobile/OTP verification.
  3. The user opens Profile and sees Name, photo, verified mobile/email, rating, completed rides, displayed as ✓ Mobile Verified | ✓ Email Verified.
  4. Failure and recovery. An invalid or expired verification code produces an accessible error and the user can re-request verification.
  5. Continuation. The verified user publishes rides or requests seats with real trust signals attached.

Flow 10 — Account recovery (Driver, Passenger, or Admin)

  1. A user who cannot sign in opens Account Recovery from Login.
  2. The user requests a reset and receives reset instructions.
  3. The user sets a new password and returns to Login.
  4. Failure and recovery. An invalid or expired reset token produces an accessible error and the user requests a new link.
  5. Continuation. The user signs in and resumes their work.

Flow 11 — Safety: report, block, and help (Driver and Passenger)

  1. A user opens Safety.
  2. The user reports a user or ride by selecting a category: fake profile, fraud, harassment, unsafe behaviour, or incorrect ride, and adds detail.
  3. The user blocks a user, or opens the help/emergency option.
  4. The system confirms that the report was received.
  5. Failure and recovery. A failed submission produces an accessible error and the user retries.
  6. Continuation. The report enters the Admin's moderation queue.
Page 18 of 25

Flow 12 — Admin moderation and statistics (Admin)

  1. The Admin opens Login and signs in. RBAC determines that the Admin Panel is reachable.
  2. The Admin opens the Admin Panel and reads the statistics band: Users · Active · Full · Completed · Cancelled · Bookings · Seats Open.
  3. The Admin searches and views users, and suspends a user where warranted.
  4. The Admin manages rides, cancels a problematic ride, and views bookings.
  5. The Admin handles reports and reviews from the moderation queues.
  6. Failure and recovery. An action not permitted by the Admin's role is refused with an accessible explanation and the panel returns to confirmed state.
  7. Continuation. The statistics band reflects the updated platform state.
Page 19 of 25

6. Visuals Colors and Theme

The creative direction is authoritative for this section. The muse is Rasmus Andersson: systematic product craft with a warm ground and one hot signal, ride data rendered as editorial numerals. The headline idea is that the core UI object is a live integer — seats available — that must never be misread and must update instantly, so the interface is a seat-count instrument rather than a SaaS landing page.

Palette — light mode.

RoleTokenValue
Background (warm paper ground)--bg#F6F3EE
Surface (cards, form panels)--surface#FFFFFF
Text / primary action (ink)--ink#141517
Accent (single hot signal)--accent#E4572E
Muted (metadata, timestamps, helper text)--muted#8A8578
Hairline border--hairline#E3DED4

Status set (text + 6px dot, never a coloured pill background).

StatusValue
ACTIVE#2F7A5F (deep green)
FULL#E4572E
CANCELLED#8A8578
COMPLETED#141517 at 60%
EXPIRED#8A8578 at 40%

Tangerine #E4572E is reserved for the Request Seat CTA hover state, live seat-count numerals, the FULL badge, focus rings, active filter chips, and the seat-stepper minus/plus glyphs. The primary action is ink black, not blue. Links are ink with a 1px underline offset 3px. Blue and indigo are forbidden anywhere — no #2563EB, #4F46E5, or #6366F1 buttons, links, focus rings, or map pins.

Typography.

  • Headings: Space Grotesk 500/600, tight tracking (−0.02em to −0.035em), sentence case, never all-caps for headlines.
  • Body: Inter Tight.
  • Numerals: JetBrains Mono 500 with font-variant-numeric: tabular-nums, so seat counts never jitter when they tick 4→3→2→1→0.
  • Scale: 1.25 modular on a 4/8-pt rhythm — 12 / 14 / 16 / 20 / 25 / 31 / 39 / 49 / 61.
  • Hero display clamp(40px, 9vw, 96px) mobile→desktop; section headings clamp(24px, 4vw, 40px); ride-card route line 20–25px; body 16px with 1.55 line-height; micro-labels 12px uppercase 0.08em tracking in Space Grotesk 500; monospace numerals 14–20px.
  • The hero wordmark PRAYOMSH CARPOOL is set as two stacked lines at display scale with the second line indented to the second grid column — a typographic gesture, not a centred logo.

Shape language. Compact and precise: 8px radius on inputs, buttons, and chips; 12px on ride cards; 16px on dashboard panels; 999px only on the seat stepper's − and + circular buttons and status dots. Hairline 1px borders in #E3DED4 do the structural work instead of shadows. Buttons are rectangles with a 1px ink border and a 2px hard offset shadow on hover (no soft blur), which reads as a physical key press. Dividers are full-bleed 1px rules that align to the grid. No blobs, no pills-everywhere, no glass.

Spacing rhythm. 4/8-pt scale throughout; 24px gutters; max content 1200px at a visible 12-column grid at 1280px, collapsing to 8 columns at 768px and 4 columns at 375px, with a persistent left rule at column 1 on desktop so the grid is legible.

Imagery style. The interface is the imagery: a real OpenStreetMap/Mapbox vector map panel with ink route polylines, a tangerine pickup pin, a black drop pin, and muted grey map tiles (never default Google blue). Supporting graphics are schematic — a ruled seat-occupancy diagram of four filled/empty seat squares that fill left-to-right as bookings land, thin topographic-style route lines as section dividers, and monospace code-like ride ID labels (e.g. RIDE-2026-00418). No stock photography of people, no 3D blobs, no illustration. Driver avatars are initials in a 1px-bordered square, not a circle.

Readable text and controls stay whole at 375px, 768px, and 1280px: headlines, wordmarks, labels, numbers, card text, and controls stay entirely inside the viewport and their container, wrapping or scaling (for example font-size: clamp(...) with its mobile size) to fit, and no other element covers any part of them. Imagery and decoration may be cropped, bled, rotated, or overlapped as the direction asks, as long as they cover no readable text or control.

Page 20 of 25

7. Signature Design Concept

The public entry is a seat-count instrument, not a landing page. It is a split hero on warm paper #F6F3EE, nothing centred, nothing floating on a gradient.

Left 7 columns. PRAYOMSH set in Space Grotesk 600 at clamp(40px, 9vw, 96px) with tight tracking, and CARPOOL on the next line indented by exactly one grid column so the two words step down the page. Beneath it the tagline “Share the Ride. Split the Cost. Travel Smarter.” at 20–25px in ink, then the supporting line “Find available rides, share your journey and connect with drivers and passengers.” in muted #8A8578, then two buttons on one baseline — Find a Ride as a solid ink block with white text and Offer a Ride as a 1px ink outline block, both 8px radius with a 2px hard offset shadow on hover.

Right 5 columns. A live “Right now” panel: a white surface with a 1px hairline border containing three real rides as ruled rows — route in ink, date/time in muted, available seats as a large tangerine tabular numeral on the right — headed by a small uppercase Space Grotesk label with a pulsing 6px green dot. The panel shows the last server-confirmed values with a timestamp; it never hides the seat truth behind a skeleton after first paint.

Directly under the hero. A full-bleed 1px rule spans the viewport and the seat-logic strip sits on it: 4 → 3 → 2 → 1 → 0 rendered as five monospace digit blocks separated by arrows, with the 0 block outlined in tangerine and labelled FULL. This is the product's core mechanic stated as the hero's baseline — the app's atomic booking logic rendered as its most prominent graphic element.

The concept recomposes only accepted content, states, and controls: the wordmark, tagline, supporting line, the two entry buttons, real ride data, and the seat-count mechanic. It introduces no new behaviour, page, or destination.

Page 21 of 25

8. Interaction Model & Motion Direction

Interaction Model: Static Motion Tempo: restrained Hero Dimensionality: flat

Landing Hero Motion Brief.

  • Focal subject. The live seat-count instrument: the stacked PRAYOMSH / CARPOOL wordmark on the left and the “Right now” panel of real rides on the right, with the 4 → 3 → 2 → 1 → 0 seat-logic rail as the baseline.
  • Input → transformation → outcome thesis. A real booking lands on the server → the backend confirms the new seat count inside its atomic transaction → the affected numeral flips like a mechanical counter over 160ms and the card takes a 400ms tangerine hairline flash, so the visitor sees that the number is live and true. The numeral moves only when the server confirms; it is never optimistically decremented.
  • Motion vocabulary. Fast and functional, 120–200ms, cubic-bezier(0.2, 0, 0, 1). The monospace digit flip (old digit slides up out, new digit slides in) over 160ms is the only ornamental motion in the product and it exists to make realtime legible. Realtime updates arrive with a 1px tangerine border flash on the affected card for 400ms, then settle. Ride cards enter with a 120ms 4px upward fade staggered 30ms per row, capped at the first 8 rows. Hover on a ride card shifts the route arrow 4px right. No bounce, no parallax, no animated gradients.
  • Composed first frame. Warm paper ground; the two-line wordmark stepping down the left grid; tagline and supporting line beneath it; the two buttons on one baseline; the white “Right now” panel on the right with three ruled ride rows and their tangerine tabular seat numerals; the full-bleed hairline rule beneath, carrying the five monospace digit blocks with the tangerine-outlined 0 tagged FULL.
  • Reduced-motion state. With prefers-reduced-motion the digit flip and the border flash are removed, leaving instant value swaps; staggered card entry and the hover arrow shift are removed; the seat-logic rail renders as five static digit blocks with the tangerine-outlined 0 tagged FULL.
Page 22 of 25

9. Non-Functional Requirements

NFR-1 — Backend authority over seat count. Seat count is controlled by the backend and the frontend seat count is never trusted. Provenance: explicit. Rationale: the product's core promise is that the displayed seat number is always true.

NFR-2 — Atomic concurrency safety. Overbooking is prevented with an atomic database transaction/locking; if only one seat remains and two passengers book simultaneously, only one succeeds. Provenance: explicit. Rationale: the final-seat race condition is the defining correctness test of the product.

NFR-3 — FULL-ride visibility rule. FULL rides disappear from passenger search but remain in the database; FULL rides are never shown in available search. Provenance: explicit.

NFR-4 — Zero-seat consequences. At 0 seats: status = FULL, hide from search, disable booking, preserve history. Provenance: explicit.

NFR-5 — Phone privacy. The driver's personal phone number is never publicly exposed, and private data is never exposed through public APIs. Provenance: explicit.

NFR-6 — Secret non-exposure. Passwords, tokens, hashes, and private contact information are never exposed. Provenance: explicit.

NFR-7 — Genuine realtime. Realtime is delivered over WebSockets, Supabase Realtime, or Firebase Realtime; realtime is never faked with timers. Provenance: explicit.

NFR-8 — Secrets in environment variables. API keys and secrets are kept in environment variables. Provenance: explicit.

NFR-9 — No fake production data. The final product contains no fake hardcoded production data. Provenance: explicit.

NFR-10 — Booking integrity rules. A passenger must not be the driver on a booking, and duplicate bookings are not allowed. Provenance: explicit.

NFR-11 — Notification channel obligation. In-app notifications are required; Email/WhatsApp/SMS are optional. Provenance: explicit.

NFR-12 — Security controls. Server-side validation, secure password hashing, authentication/authorization, RBAC, rate limiting, CORS, XSS/SQL injection protection, secure headers, error handling, and logging. Provenance: explicit.

NFR-13 — Responsiveness. Fully responsive for desktop, tablet, and mobile. Provenance: explicit.

NFR-14 — Accessibility. WCAG-following keyboard navigation, labels, accessible forms and errors, screen-reader support, and good contrast. Provenance: explicit.

NFR-15 — SEO. SEO title/meta, Open Graph, sitemap, robots.txt, semantic HTML, and structured data where useful. Provenance: explicit.

NFR-16 — Scalability and production readiness. The product must be fully functional, secure, realtime, responsive, scalable, and production-ready. Provenance: explicit.

NFR-17 — Spatial capability. PostgreSQL + PostGIS supports coordinate storage and nearby matching at 5 / 10 / 25 km. Provenance: explicit.

NFR-18 — Test coverage. Authentication, ride creation, search, booking, concurrency, realtime updates, and security are tested. Provenance: explicit.

NFR-19 — Edge-case handling. Driver/passenger cancellation, duplicate booking, final-seat race condition, full/expired ride, invalid date/location/seats, unauthorized access, network failure, duplicate API requests, and route/time changes are handled. Provenance: explicit.

NFR-20 — Readable content containment. Readable text and controls stay whole at 375px, 768px, and 1280px, inside the viewport and their container, with no other element covering them. Provenance: explicit (creative direction).

Page 23 of 25

10. Tech Stack

Source choices are preserved exactly; nothing is substituted.

  • Frontend: Next.js + React + TypeScript + Tailwind CSS.
  • Backend: Node.js + NestJS/Express + TypeScript.
  • Database: PostgreSQL + PostGIS.
  • Realtime: WebSockets / Supabase Realtime.
  • Maps: Google Maps / Mapbox / OpenStreetMap.
  • Notifications: in-app (required); Email/WhatsApp/SMS (optional external channels).
  • Configuration: API keys and secrets in environment variables.
Page 24 of 25

11. Assumptions and Constraints

Assumptions.

  1. [Assumption — narrow] The map provider is selected at deployment time from Google Maps, Mapbox, or OpenStreetMap; the product's behavior is identical under any of the three, and the map panel uses muted grey tiles with ink polylines and tangerine/black pins rather than provider-default blue.
  2. [Assumption — narrow] The realtime transport is selected at deployment time from WebSockets or Supabase Realtime; the authoritative seat state always remains in PostgreSQL regardless of transport.
  3. [Assumption — narrow] Email/WhatsApp/SMS delivery depends on external providers being configured; when they are not configured, in-app notification alone satisfies the notification requirement.
  4. [Assumption — narrow] Administrative roles are provisioned rather than self-selected, consistent with RBAC.
  5. [Assumption — narrow] A ride's date and time determine expiry; a ride whose date/time has passed is EXPIRED.

Constraints.

  1. Seat count is controlled by the backend; the frontend seat count is never trusted.
  2. Overbooking is prevented with an atomic database transaction/locking; of two simultaneous final-seat requests, only one succeeds.
  3. FULL rides disappear from passenger search but remain in the database; FULL rides are never shown in available search.
  4. At 0 seats: status = FULL, hide from search, disable booking, preserve history.
  5. The driver's personal phone number is never publicly exposed; private data is never exposed through public APIs.
  6. Passwords, tokens, hashes, and private contact information are never exposed.
  7. Realtime is never faked with timers.
  8. API keys and secrets are kept in environment variables.
  9. The final product has no fake hardcoded production data.
  10. A passenger must not be the driver on a booking, and duplicate bookings are not allowed.
  11. In-app notifications are required; Email/WhatsApp/SMS are optional.
  12. Blue and indigo are forbidden anywhere in the interface; the primary action is ink black and the only hot colour is tangerine #E4572E.
  13. Headings and body use Space Grotesk, Inter Tight, and JetBrains Mono only — not Inter, Roboto, Arial, Helvetica, Poppins, or system-ui.
  14. Ride results are one dense ruled list with a sticky map panel, not a grid of identical hover-lift cards.
  15. Ride statuses are a 6px dot plus text, never a coloured pill background.
  16. No soft blurred drop shadows, no 24px+ pill radii on every element, no decorative illustrations, and no stock photography of people.
  17. No full-bleed hero imagery, no parallax scenes, and no motion beyond 200ms functional transitions plus the single 160ms digit flip.
  18. The seat-count truth is never hidden behind a spinner or skeleton after first paint; the ride card always shows the last server-confirmed integer with its timestamp.
Page 25 of 25

12. Glossary

  • PRAYOMSH CARPOOL — the product name; tagline “Share the Ride. Split the Cost. Travel Smarter.”
  • Driver — the persona who offers available car seats by publishing a ride.
  • Passenger — the persona who searches for rides and requests seats.
  • Admin — the persona who operates the secure RBAC admin dashboard for moderation and statistics.
  • Ride — a published journey with driver_id, pickup/drop + coordinates, date, time, car, total_seats, available_seats, status, and timestamps.
  • Ride status — one of ACTIVE / FULL / CANCELLED / COMPLETED / EXPIRED.
  • FULL — the ride status set automatically when available seats reach 0; the ride leaves passenger search but remains in the database.
  • EXPIRED — the ride status applied automatically to past rides.
  • Booking — a passenger's seat request on a ride, with ride_id, passenger_id, seats_requested, status, and timestamps.
  • Booking status — one of PENDING / ACCEPTED / REJECTED / CANCELLED / COMPLETED.
  • Seat stepper — the − 1 + control used to set available passenger seats.
  • Seat-count rail — the 4 → 3 → 2 → 1 → 0 graphic on the landing page, with the 0 outlined in tangerine and tagged FULL.
  • Atomic seat allocation — the backend transaction with locking that decrements seats and prevents overbooking.
  • Pickup radius — the configurable nearby-matching distance of 5 / 10 / 25 km.
  • Review — a 1–5 star rating with an optional comment, with ride_id, reviewer_id, reviewee_id, and timestamp; duplicates are prevented.
  • Report — a safety submission in one of the categories fake profile, fraud, harassment, unsafe behaviour, or incorrect ride.
  • RBAC — role-based access control governing administrative capability.
  • PostGIS — the spatial extension of PostgreSQL used for coordinate storage and nearby matching.
  • Realtime — server-pushed availability and ride-status updates delivered over WebSockets or Supabase Realtime, never timer-based polling.

PRAYOMSH CARPOOL © 2026 PRAYOMSH. All rights reserved.

No completed page designs yet.

Completed design pages will appear here when they are ready to preview.

Landing: Enter as anonymous visitor
Login: Sign in with provisioned admin role
Account Recovery: Reset password when locked out
Admin Panel: Read statistics band
Admin Panel: Search and view users
Admin Panel: Suspend user
Admin Panel: Manage and cancel ride
Admin Panel: View bookings
Admin Panel: Handle reports and reviews
Admin Panel: Read RBAC refusal explanation
Admin Panel: Confirm updated platform statistics

No completed page designs yet.

Completed design pages will appear here when they are ready to preview.

Landing: Enter as anonymous visitor
Login: Sign in with provisioned admin role
Account Recovery: Reset password when locked out
Admin Panel: Read statistics band
Admin Panel: Search and view users
Admin Panel: Suspend user
Admin Panel: Manage and cancel ride
Admin Panel: View bookings
Admin Panel: Handle reports and reviews
Admin Panel: Read RBAC refusal explanation
Admin Panel: Confirm updated platform statistics