Ride Schema
Firestore Document (rides/{rideId})
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
id |
string |
yes | non-empty | Unique ride identifier (nanoId) |
creatorId |
string |
yes | non-empty | UID of the ride creator; also the first admin |
adminIds |
string[] |
yes | non-empty array | UIDs of ride admins; always includes creatorId |
groupId |
string \| null |
no | — | Group UID if this ride belongs to a group; null for standalone rides |
type |
"private" \| "public" |
yes | enum | Discovery scope: private = link-only, public = app-wide |
title |
string |
yes | non-empty | Display name of the ride |
description |
string |
no | — | Optional long-form description |
startAt |
Timestamp |
yes | must be before endAt |
Scheduled ride start time |
endAt |
Timestamp |
yes | must be after startAt |
Scheduled ride end time |
posterUrl |
string \| null |
no | valid URL | Cover image URL; may be sourced from Google Places photo for the destination |
settings.requireRsvpApproval |
boolean |
yes | — | If true, RSVPs require creator/admin approval before access is granted |
settings.maxRiders |
number |
yes | integer ≥ 0 | Max yes-status participants; 0 means unlimited |
startLocation.id |
string |
yes | non-empty | Unique waypoint identifier |
startLocation.placeId |
string \| null |
no | — | Google Places API place ID |
startLocation.latitude |
number |
yes | −90 to 90 | WGS-84 latitude |
startLocation.longitude |
number |
yes | −180 to 180 | WGS-84 longitude |
startLocation.title |
string |
yes | non-empty | Human-readable location name |
startLocation.type |
"origin" |
yes | fixed value | Always "origin" |
endLocation.id |
string |
yes | non-empty | Unique waypoint identifier |
endLocation.placeId |
string \| null |
no | — | Google Places API place ID |
endLocation.latitude |
number |
yes | −90 to 90 | WGS-84 latitude |
endLocation.longitude |
number |
yes | −180 to 180 | WGS-84 longitude |
endLocation.title |
string |
yes | non-empty | Human-readable location name |
endLocation.type |
"destination" |
yes | fixed value | Always "destination" |
breakpointsTo |
Location[] |
no | max 6 items (8 total incl. origin + destination) | Intermediate waypoints; see Location type below |
createdAt |
Timestamp |
yes | server-set | Document creation time |
updatedAt |
Timestamp |
yes | server-set | Last modification time |
Location object (used in breakpointsTo):
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
id |
string |
yes | non-empty | Unique waypoint identifier |
placeId |
string \| null |
no | — | Google Places API place ID |
latitude |
number |
yes | −90 to 90 | WGS-84 latitude |
longitude |
number |
yes | −180 to 180 | WGS-84 longitude |
title |
string |
yes | non-empty | Human-readable location name |
type |
string |
yes | enum | One of additionalDestination, meetingPoint, haltPoint, restaurant, fuelStation, other |
{
"id": "abc123",
"creatorId": "uid_creator",
"adminIds": ["uid_creator"],
"groupId": null, // or "gid_xyz" for group rides
"type": "public", // "private" | "public"
"title": "Weekend Ghat Run",
"description": "Scenic route through the Western Ghats",
"startAt": "2025-06-01T06:00:00Z", // Firestore Timestamp
"endAt": "2025-06-01T14:00:00Z", // Firestore Timestamp
"posterUrl": "https://example.com/poster.jpg", // optional
"settings": {
"requireRsvpApproval": false,
"maxRiders": 25, // 0 = unlimited
},
"startLocation": {
"id": "loc_start",
"placeId": "ChIJ...", // optional Google Places ID
"latitude": 12.9716,
"longitude": 77.5946,
"title": "Bangalore City Center",
"type": "origin",
},
"endLocation": {
"id": "loc_end",
"placeId": "ChIJ...", // optional
"latitude": 15.3647,
"longitude": 75.1240,
"title": "Hampi",
"type": "destination",
},
"breakpointsTo": [
{
"id": "loc_bp1",
"placeId": null,
"latitude": 13.9299,
"longitude": 75.5681,
"title": "Chitradurga Fort",
"type": "haltPoint",
},
],
"createdAt": "2025-05-01T10:00:00Z", // Firestore Timestamp
"updatedAt": "2025-05-01T10:00:00Z", // Firestore Timestamp
}
Sub-collections
rides/{rideId}/participants/{userId}
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
id |
string |
yes | non-empty | UID of the participant (matches document ID) |
name |
string |
yes | non-empty | Display name of the rider |
photoUrl |
string |
yes | valid URL | Avatar URL |
joiningLocationId |
string |
yes (if status is yes or maybe) |
must match a location id in the ride |
ID of the breakpoint where the rider joins |
status |
"yes" \| "no" \| "maybe" |
yes | enum | RSVP status; maybe auto-upgrades to yes when ride starts |
{
"id": "uid_rider",
"name": "Arjun Mehta",
"photoUrl": "https://example.com/avatar.jpg",
"joiningLocationId": "loc_start", // must match a location id on the ride
"status": "yes", // "yes" | "no" | "maybe"
}
rides/{rideId}/routes/{routeId}
routeId encodes direction and alternative index: to-0 is the first outgoing
route (origin → destination), to-1 the second alternative, from-0 the first
return route (destination → origin).
Currently only to-0 is stored. Return routes and multiple alternatives are
planned.
Refer to the Route Schema for the full route document structure.
Server-Controlled Fields
The following fields are set exclusively by the server. They are never accepted
in any API request body. The RideRequestSchema (used by Create and Update
endpoints) must omit all of them.
| Field | Set by |
|---|---|
id |
Server on create (nanoId) |
creatorId |
Server on create (authenticated user's UID) |
adminIds |
Server on create; modified only via Manage Admins |
status |
Server on state transitions (publish, cancel, delete) |
deletedAt |
Server on delete |
createdAt |
Server on create |
updatedAt |
Server on every write |
Security invariant: Accepting
statusordeletedAtin a client request allows any ride admin (not just the creator) to delete or corrupt ride state via the Update endpoint. The Create and Update handlers must strip these fields before writing to Firestore.
Indexes
| Fields | Query Type | Reason |
|---|---|---|
creatorId asc |
Single-field | Fetch all rides created by a user |
groupId asc + startAt asc |
Composite | Group ride feed ordered by start time |
type asc + startAt asc |
Composite | Public ride discovery ordered by start time |
creatorId asc + startAt desc |
Composite | User's ride history in reverse-chronological order |