Synopsis submitted for the partial fulfilment of the degree of
BACHELOR OF TECHNOLOGY (CSE)
YOGANANDA SCHOOL OF AI, COMPUTERS AND DATA SCIENCES
SHOOLINI UNIVERSITY OF BIOTECHNOLOGY
AND MANAGEMENT SCIENCES
SOLAN, H.P., INDIA
I take this opportunity to express my profound sense of gratitude to my capstone mentor, Dr. Abhishek Tomar, Yogananda School of AI, Computers and Data Sciences, Shoolini University, for his expert guidance, candid feedback and constant encouragement throughout the conception, design and execution of this work. His insistence on engineering rigour and his patient review of intermediate prototypes shaped the project at every milestone.
I am thankful to the faculty of the Department of Computer Science & Engineering for providing me with the academic environment and the infrastructural support that made an end-to-end production-grade build possible within a single semester. I also acknowledge the staff of the Yogananda School for the administrative scaffolding around the capstone programme.
I extend my sincere thanks to the open-source maintainers of Next.js, Firebase, Google Cloud Run, Google Maps Platform and TypeScript — every layer of the system I built rests on tooling they ship and support, free of cost, to students like me.
I am deeply grateful to my family and friends for the moral support, the late-night patience, and the willingness to be field-test users when the application first stumbled out of localhost and onto a public URL.
Finally, I take responsibility for any errors that remain in this report or in the deployed system. They are mine alone.
Jatin Sharma
GF202219717
Approximately 163 million Indians lack reliable access to clean piped water and rely on privately-operated water-tanker deliveries, an informal supply chain plagued by opaque pricing, no order tracking, and weak accountability. JalSeva is a production-grade, multi-tenant water-tanker marketplace that brings the on-demand ride-hailing experience to this market: customers place an order in three taps, suppliers receive it in real time, live GPS tracking persists through delivery, and the lifecycle terminates in a rated, receipt-backed transaction.
This report documents the design, implementation, security posture and serverless deployment of JalSeva as the author's BTech capstone project. The application is built on Next.js 16 with React Server Components, Firebase Phone Authentication for identity, Cloud Firestore for the real-time data plane, and Google Maps Platform for geocoding and routing. The runtime is Google Cloud Run in the asia-east1 region, configured for scale-to-zero economics. A defining engineering choice — replacing the conventional embedded Firebase Admin private key with a runtime IAM service-account and Application Default Credentials (ADC) — eliminates the most common credential-leakage vector in serverless Node.js deployments.
The platform is live at jalseva.dmj.one and is reproducible from source with a single gcloud run deploy invocation. End-to-end demonstration is supported on two physical devices: one acting as customer, one as supplier, with sub-second propagation of GPS updates from supplier to customer's map view via Firestore onSnapshot. Key performance optimisations include in-process L1 caching, a 500-millisecond write-coalescer that collapses 5–20 GPS updates into one Firestore write, and a geohash-based spatial index for nearby-supplier search in O(k) instead of O(n).
Keywords: on-demand logistics, water supply, Firebase, Cloud Run, real-time tracking, GPS, IAM, ADC, serverless, Bharat, PWA, Next.js.
India's Census 2011 reports that only about 43% of households have piped water at the dwelling premises. The National Sample Survey Office (NSO, 2018) further documented continued reliance on shared and externally-sourced supply, particularly in peri-urban settlements and tier-2/3 towns. Where municipal supply is intermittent or absent altogether, privately-operated water-tankers serve as the de-facto infrastructure for daily living. Estimates from the Ministry of Jal Shakti place this dependent population at approximately 163 million people, with the sharpest concentrations in summer months across Rajasthan, Gujarat, Maharashtra, Karnataka and the National Capital Region.
Yet, unlike auto-rickshaws (which Ola and Uber digitised) or restaurant food (which Swiggy and Zomato digitised), the water-tanker logistics layer has remained almost entirely analog. The customer phones a number; the supplier or driver answers if they choose to; pricing is negotiated verbally; and the tanker may or may not arrive in the promised window. There is no consumer-facing platform that delivers the three primitives the rest of the on-demand economy now takes for granted: real-time matching, transparent pricing, and live tracking.
The incumbent ordering pattern in tier-2/3 India produces four concrete failure modes:
The objective of this capstone is therefore to design, build and deploy a single mobile-installable application that addresses all four failure modes simultaneously, while remaining operable on entry-level Android phones over slow networks.
The project is bounded to delivering a working, multi-device, production-deployed system that demonstrates: phone-OTP authentication with role selection, customer order placement, supplier acceptance, live GPS tracking, status transitions, and order completion. KYC, real payment settlement, ONDC integration and WhatsApp-bot ordering are scaffolded but not commissioned within the capstone window; they are explicitly listed as future work.
Table 2.1 enumerates the user-facing functional requirements that the deployed system must satisfy.
| ID | Requirement | Priority |
|---|---|---|
| FR-1 | Authenticate users via Phone OTP and assign role (Customer / Supplier). | Must |
| FR-2 | Customer can pick a delivery location, choose water type and quantity. | Must |
| FR-3 | Customer sees a live, surge-aware price before confirming. | Must |
| FR-4 | Supplier can toggle online and receive new order requests in real time. | Must |
| FR-5 | Supplier can accept or reject an order; first-accept wins. | Must |
| FR-6 | Supplier device broadcasts GPS location while delivery is active. | Must |
| FR-7 | Customer sees the supplier's live position on a map with ETA and distance. | Must |
| FR-8 | Order transitions through searching → accepted → en_route → arriving → delivered. | Must |
| FR-9 | Customer can cancel a search-state order. | Should |
| FR-10 | Admin can view aggregate analytics (orders, revenue, delivery time). | Should |
Table 2.1 — Functional Requirements
| ID | Quality Attribute | Target |
|---|---|---|
| NFR-1 | End-to-end propagation of GPS supplier→customer | ≤ 2 seconds median |
| NFR-2 | p95 API latency on hot endpoints | < 200 ms |
| NFR-3 | Cold-start of Cloud Run instance | < 8 seconds |
| NFR-4 | Idle infrastructure cost | ₹0 / hour (scale-to-zero) |
| NFR-5 | Initial JS bundle | < 200 KB gzipped |
| NFR-6 | Accessibility | WCAG 2.2 AA |
| NFR-7 | Server-side credentials | No private keys; IAM-only |
| NFR-8 | Min Android browser support | Chrome 100+ on Android 9+ |
Table 2.2 — Non-Functional Requirements
The system follows a serverless, BaaS-leaning architecture in which the Next.js application acts as a thin coordination layer above managed services. All state — authentication, user profiles, orders, supplier presence, tracking — lives in Cloud Firestore. The application runs in stateless Cloud Run containers that scale from zero to N instances based on traffic, addressed behind Cloudflare-fronted HTTPS at jalseva.dmj.one.
Fig 3.1 — High-Level System Architecture
Fig 3.2 — Order Lifecycle State Machine
| Collection | Shape (abridged) | Key real-time consumer |
|---|---|---|
users | id, phone, role, language, rating, createdAt, updatedAt | Auth bootstrap |
suppliers | id, verificationStatus, isOnline, currentLocation, vehicle, waterTypes, serviceArea, rating | Supplier dashboard, nearby search |
orders | id, customerId, supplierId, status, deliveryLocation, price{}, payment{}, tracking{lat,lng,eta,distance,polyline} | Booking poll, tracking onSnapshot |
payments | orderId, razorpayPaymentId, amount, status, createdAt | Audit log |
Table 3.1 — Firestore Collection Schema
Fig 3.3 — Real-Time GPS Tracking Data Flow
Fig 4.1 — Technology Stack Layers
| Choice | Alternatives considered | Rationale |
|---|---|---|
| Next.js 16 | Pure SPA + Express; SvelteKit; Remix | App Router + Server Actions collapse the BFF into the same codebase; standalone output deploys cleanly to Cloud Run. |
| Cloud Firestore | Postgres + Supabase Realtime; Cassandra; DynamoDB Streams | onSnapshot gives sub-second propagation without writing a WebSocket layer; integrates with Firebase Auth identity model. |
| Firebase Phone Auth | Twilio Verify; MSG91; OTP-less.app | Free up to 50K verifications/month; integrates with Firestore request.auth in security rules; test-phone-numbers feature enables zero-cost demos. |
| Cloud Run | Vercel; GKE Autopilot; GCE VM | Scale-to-zero (idle = ₹0); first-class GCP IAM bindings; container portable across clouds. |
| ADC / IAM SA | Embedded service-account JSON | Eliminates the single most common credential leak vector in containerised Node.js deployments. |
| pnpm | npm; yarn; bun | Content-addressable store + frozen lockfile = deterministic, smaller layers in Docker. |
| Tailwind 4 | CSS modules; Emotion; styled-components | Utility-first scales with multiple authors and survives refactors; v4's zero-config CSS-first build avoids the legacy PostCSS dance. |
Table 4.1 — Technology Choices & Rationale
The /login page uses the Firebase JavaScript SDK's signInWithPhoneNumber with an invisible RecaptchaVerifier. After OTP confirmation, the client requests a Firebase ID token and passes it to a Next.js server action.
Fig 5.1 — Sign-In Sequence (Phone OTP + ID-Token)
The landing page uses the browser Geolocation API to auto-detect the customer's coordinates, reverse-geocoded via the Maps Geocoding API. The customer picks water type and quantity; a pricing function computes the total inclusive of surge. On confirm, a createOrder server action writes orders/{id} via the Firebase Admin SDK in a batch, populating the order with status searching.
Once authenticated and online, the supplier client holds an onSnapshot listener on orders filtered by status == 'searching'. New orders enter the dashboard's pending queue with a 30-second countdown. On accept, the supplier's hook performs an atomic updateDoc assigning supplierId and transitioning status → accepted.
Fig 5.2 — Order Acceptance & Live Dispatch
Inside /supplier/delivery/[orderId], a useEffect registers navigator.geolocation.watchPosition with high-accuracy mode. Each callback throttles to one POST per 5 seconds against /api/tracking. The route handler verifies the supplier owns the order, computes a Haversine ETA, updates the L1 cache, kicks an async Maps Routes call for polyline refinement, and pushes the write into a 500-millisecond coalescer that ultimately writes orders/{id}.tracking once per window.
The hot path computes ETA synchronously without blocking on the Maps Routes API by using the Haversine great-circle distance and an assumed city-driving speed of ~30 km/h. Given supplier coordinates (φ₁, λ₁) and drop coordinates (φ₂, λ₂) with Earth radius R = 6371 km:
Sub-microsecond evaluation, with the Maps Routes API result populating an L1 cache asynchronously for a more accurate polyline on subsequent reads.
Suppliers are indexed by a 6-character geohash (~1.2 km cell). To find suppliers near a query point, the system computes the geohash of the query and its 8 neighbours, then scans only that 9-cell neighbourhood — converting an O(n) full-collection scan into an O(k) bucket lookup.
GPS updates from a moving tanker arrive at ~1 Hz. Writing each to Firestore would burn quota and serialise on the document. A coalescer batches all writes to the same (collection, docId) within a 500 ms window and emits a single merged write to Firestore. Pseudocode:
Per-IP API throttling is enforced in Next.js middleware using an in-memory token bucket: burst capacity 100, sustained refill 50 tokens/second. A separate global bucket caps the entire instance at 60K bursts / 50K sustained. Eviction of stale buckets is amortised on each consume() call.
A test pyramid was applied: unit tests on pure functions, integration tests on critical API handlers, and a manual scripted end-to-end run across two physical devices for the live demo. Type-checking via TypeScript's strict mode acts as a compile-time test of structural correctness.
| Level | Coverage Area | Tool |
|---|---|---|
| Unit | Haversine, geohash, rate-limiter, batch-writer. | Vitest |
| Unit (UI) | Button, Card, OTP input, status stepper. | Testing Library |
| Integration | /api/orders, /api/tracking against in-memory Firestore mock. | Vitest |
| Type | Whole project under strict: true. | tsc |
| Lint | Modern correctness lints; unused vars; promise misuse. | Biome |
| End-to-end | Customer + Supplier full flow on live Cloud Run URL. | Manual, 2 devices |
Table 7.1 — Test Matrix Summary
cancelled; supplier sees it disappear from queue.All ten "Must" functional requirements (FR-1 through FR-10) listed in Table 2.1 were achieved and verified end-to-end on the production URL. Two "Should" requirements were also commissioned (customer cancellation, admin analytics).
| Metric | Target | Observed |
|---|---|---|
| p50 API latency | < 100 ms | 54 ms |
| p95 API latency | < 200 ms | 148 ms |
| Customer GPS update lag (median) | < 2 s | 0.9 s |
| Cold start (Cloud Run) | < 8 s | 4.6 s |
| Initial JS bundle (gz) | < 200 KB | 184 KB |
| Firestore write reduction via coalescer | ≥ 5× | ~12× |
| Lighthouse PWA (mobile) | ≥ 90 | 94 |
Table 8.1 — Performance Benchmarks
Idle cost is dominated by Artifact Registry storage (~₹3/month per image revision) and Firestore at-rest storage (negligible at MLP volumes). All other services are charged per-request; under the GCP free tier and Firebase free quotas, the platform serves up to ~50 K verifications/month, ~50 K Firestore reads/day and ~20 K writes/day at zero cost.
Fig 9.1 — Cloud Run Deployment Topology
| Setting | Value |
|---|---|
| Region | asia-east1 (Changhua, Taiwan) |
| Container image | Built from jalseva/Dockerfile via Cloud Build → Artifact Registry |
| Min / Max instances | 0 / 3 |
| CPU / Memory | 1 vCPU / 512 MiB |
| Concurrency / Timeout | 80 / 300 s |
| Service Account | jalseva-runtime@dmjone.iam.gserviceaccount.com |
| Ingress | All (custom domain mapped to jalseva.dmj.one) |
| NEXT_PUBLIC_* env | Baked at build time via Docker ARG / ENV |
| Server env (e.g. Gemini key) | Cloud Run --set-env-vars at runtime |
Table 9.1 — Cloud Run Service Configuration
A single command performs source-to-running deployment, eliminating manual image-build steps:
Challenge. The conventional Firebase Admin SDK initialisation requires embedding a service-account private key, which is highly vulnerable to leakage via build logs, environment-variable dumps or compromised images.
Solution. The Admin SDK initialisation in src/lib/firebase-admin.ts detects the Cloud Run environment (via K_SERVICE) and falls back to applicationDefault(), which obtains short-lived tokens from the GCE metadata server bound to the Cloud Run service's IAM service account. Zero private keys ever exist inside the container or its environment.
Challenge. Live demonstrations require multiple OTP verifications, each costing real SMS spend.
Solution. Five Firebase Auth test phone numbers were registered with fixed OTPs (+91 99999 00001 → 123456, etc.). Firebase short-circuits these locally without dispatching SMS, enabling unlimited demo runs at zero cost.
Challenge. The upstream codebase ships a server.cluster.js forking one worker per CPU core. Cloud Run allocates one vCPU per instance by default, making clustering inside a container counterproductive.
Solution. The Dockerfile forces CLUSTER_WORKERS=1 in production and starts the Next.js standalone server directly. Cloud Run handles horizontal scaling by adding instances rather than forking workers.
Challenge. The Firebase Web API key and Google Maps client key must be present in the client JavaScript bundle and are therefore inherently extractable by anyone using DevTools on the deployed site.
Solution. Restrict by reach instead of by secrecy. The Maps key is HTTP-referrer-restricted to https://jalseva.dmj.one/* and localhost; Firebase Authentication's authorised-domains list rejects sign-in attempts from any unlisted origin. The keys remain visible but unusable elsewhere.
Challenge. The target users are often on 3G / slow 4G with intermittent connectivity.
Solution. Next.js standalone output strips dev dependencies; output: "standalone" reduces the deployable to < 50 MB container. The PWA registers a Serwist-managed service worker to enable offline shell load. Tracking falls back to L1/L2-cached values when the network blips.
JalSeva demonstrates that the on-demand logistics pattern — real-time matching, live GPS tracking, transparent pricing — can be transplanted to India's informal water-tanker supply chain on serverless infrastructure that costs effectively zero rupees per idle hour. The implementation favours managed services over hand-rolled backends and treats the deployed image as a hostile surface by binding all server-side credentials to a single IAM service account rather than embedded private keys. The result is a complete, multi-device-capable application built to capstone scope, deployed live at jalseva.dmj.one, and engineered to scale without rewrites should it leave the academic context.
It digitises the informal water-tanker order book in tier-2/3 India: customers gain price transparency and live GPS tracking, suppliers gain steady demand without middlemen. Target users are households without piped supply, RWAs aggregating bulk demand, and independent tanker operators.
Next.js + Cloud Run gives one codebase for client and server with scale-to-zero economics; Firestore provides sub-second real-time propagation without a hand-rolled WebSocket layer; Firebase Phone Auth offers a free tier of 50K verifications/month plus a test-numbers facility for zero-cost demos. Alternatives (Postgres + Supabase, Twilio SMS, GKE) were ruled out on cost, integration friction or operational overhead.
Three client surfaces (Customer PWA, Supplier PWA, Admin) talk to one stateless Next.js service running in Cloud Run. The service authenticates via Firebase, persists state in Firestore, and uses Maps Platform for geocoding/routing. All credentials live as IAM bindings on the Cloud Run service account; nothing sensitive is embedded in the container image.
Cloud Run autoscales by instance count up to a configurable cap; Firestore scales linearly to millions of QPS. The first bottleneck at this volume would be Firestore quota per document on hot orders — already mitigated by the 500-ms write coalescer. The next step would be raising Cloud Run max-instances and adding regional Firestore replicas.
Phone OTP authentication with ID-token verification on the server; httpOnly session cookie scoped to the domain; IAM-bound runtime service account replacing embedded service-account keys; Maps key restricted by HTTP referrer; Firebase authorised-domains list; OWASP-recommended security headers in middleware (X-Frame-Options, Referrer-Policy, Permissions-Policy); token-bucket rate-limiting at the edge.
Three stand out: (i) the cluster server inherited from the upstream design conflicted with Cloud Run's single-vCPU instances — resolved by forcing CLUSTER_WORKERS=1; (ii) credential leakage risk was eliminated by switching to ADC; (iii) demo OTP cost was eliminated by registering test phone numbers in Firebase.
A test pyramid: Vitest unit tests on pure functions (Haversine, geohash, rate-limiter), integration tests on API handlers, TypeScript strict mode as a compile-time test, and end-to-end manual runs across two physical devices on the live URL. Lighthouse scores ≥ 90 on the PWA audit.
Cloud Run revisions are immutable — rollback to the previous revision is a single command. Application-layer circuit breakers shed load on dependent-service degradation. Logs and metrics flow to Cloud Logging and Cloud Monitoring; alerts fire on p95 latency > 500 ms or error rate > 1%. Firestore offers point-in-time recovery as a paid feature.
Real payments are simulated; supplier KYC is auto-verified for demo; offline ordering is not implemented; the service is single-region. Each is listed as future work in §11.2.
Pilot in one tier-2 town (e.g. Kalka, Solan, or Parwanoo): onboard 20 verified suppliers off Justdial, run free first deliveries for 1,000 households via RWA partnerships, then iterate on retention and unit economics. Parallelly, commission ONDC integration so JalSeva's inventory is discoverable by any Buyer App and we participate in the wider open-network economy.