Read trips-v2 first. trips_v2 is ON by default in both
registries, so the screens in this document are what a user gets only if an
admin turns that flag off, or by typing a deep link. This file was collapsed on
2026-10-29 from a 782-line account written against commit 852f2722
(2026-08-29); the mechanics it described in full — turn-by-turn, rerouting, the
three driving cameras, the road corridor query, trip sync — still run, and the
parts that survive unchanged under trips_v2 are kept here only where no
current doc states them. The web planner is in
road-trip-planner. Everything else that used to be here
is in git history (git log -- docs/features/trips-and-driving.md).
Summary
Before the unified Trips, Scout had two separate trip kinds, each with its own
drawer row and home screen: a Day Trip (a short, radius-bounded itinerary
around one city, built from a swipe deck, a grid, or a Scout-authored curated
trip) and a Road Trip (a long plan between any two points, routed by
OpenRouteService, with every patch within a chosen detour of the road grouped by
the states it crosses). Both drove on one shared trip map with turn-by-turn
instructions, rerouting when you leave the road, and passive auto-collect as
stops are reached. That shared engine is what trips_v2 re-fronts with one
question, "What kind of trip?" — the legacy homes and planners are the part that
was replaced.
Status
- Flag-off path.
trips_v2isdefaultEnabled: trueinmobile/src/config/feature-flags.ts:93andbackend/src/admin/feature-flag-definitions.ts:57; it has been on since 2026-10-06. With it on: the drawer shows one Trips row and hides Road Trip (mobile/src/components/navigation/drawerSections.ts:321-330);/tripsrenders the new Trips (mobile/app/(drawer)/trips.tsx:24);/trip-plannerredirects to Plan my day (mobile/app/trip-planner.tsx:586). With it off, every screen below comes back unchanged. trips_tabis a dead, backend-only flag. It exists only inbackend/src/admin/feature-flag-definitions.ts:49-55(defaultEnabled: false,dev: true, categorymobile, "Show the Trips tab in the bottom tab bar"). A grep ofmobile/src/**andmobile/app/**fortrips_tabfinds nothing (re-run 2026-10-29). Toggling it in the admin UI changes nothing in any build; it is a vestige of a bottom-tab-bar navigation the drawer replaced.- The web road-trip planner is deployed, not launched. An earlier version
of this doc said it was "built, not deployed: not live until launch". Since
2026-10-29
scout-patches.com/tripsis live on the droplet (PM2scout-trips, an nginx/tripsblock) with its flagsweb_saved_tripsandweb_markersstill off, so there is no Save, no My trips and no markers, and nothing links to it yet. Details, limits and the launch checklist are in road-trip-planner § Status.
User-facing surfaces (legacy; trips_v2 off, or by deep link)
Every route is registered in mobile/src/dev/deepLinkRoutes.ts and reachable
as scout://<path> regardless of the flag — only the drawer rows and the two
redirects above depend on it.
| Route | File | What it is |
|---|---|---|
/(drawer)/trips |
mobile/app/(drawer)/trips.tsx |
Day Trip home — TripHomeScreen kind="day" (flag off only; on, this path is the new Trips) |
/(drawer)/road-trip |
mobile/app/(drawer)/road-trip.tsx |
Road Trip home — TripHomeScreen kind="road"; drawer row hidden under trips_v2 |
/trip-planner |
mobile/app/trip-planner.tsx |
Day Trip builder (swipe deck / grid); redirects to /trip-plan with the flag on |
/road-planner |
mobile/app/road-planner.tsx |
Road Trip "where to?" + stop picker (deepLinkRoutes.ts:152) |
/trip-preview |
mobile/app/trip-preview.tsx |
Map-first preview of a trip before committing |
/trip-stops |
mobile/app/trip-stops.tsx |
The itinerary list |
/my-trips |
mobile/app/my-trips.tsx |
Day-trip history: live / saved / done, read-only recaps |
/trip-map |
mobile/app/trip-map.tsx |
The live driving map, day or road via ?kind= (deepLinkRoutes.ts:155) |
Both homes render the same TripHomeScreen
(mobile/src/components/trips/TripHomeScreen.tsx) parameterised by kind, split
into TripHomeScreenViewModelImpl and the pure TripHomeScreenLayout, which is
what lets the DEV screen-mock gallery show both faces
(mobile/src/dev/mocks/trip-home.tsx, scout://dev-screen-mock/trip-home).
The shared engine that is still live under both flags
These are not legacy; they are stated here because no current doc states them.
- Navigate in Scout —
scout://navigate/<patchId>(mobile/app/navigate/[id].tsx), from a patch's ⋯ sheet: a throwaway drive to one patch on the trip map, with the same turn-by-turn, rerouting and arrival unlock, that saves nothing and ends when closed. Not a trip: nodayTripsentry, no sync, nothing in My Trips, no share card, counts toward no trip achievement. The destination is always a patch with coordinates — there is no navigate-to-an-address. The Capture Studio drives it with?sim=1&speed=(studio/src/steps.ts:55). - Reroute gate (
mobile/src/utils/rerouteGate.ts:12-17): off-route threshold 0.15 mi, sustained 20 s, cooldown 60 s. - Detour steps (mirrored client/server,
mobile/src/utils/roadCorridor.ts:11-16,backend/src/trips/trips.service.ts:23-26): road trip 5/10/15/25/50/100/150 mi, default 25, max fetch radius 150; day trip 5/10/25/50. - Routing provider.
ORS_API_KEYmust be set or every routing endpoint throwsRouteProviderError→ 502. The ORS call times out after 15 s (OrsProvider.DEFAULT_TIMEOUT_MS,backend/src/routing/ors.provider.ts:45).RoutingService.peek()(backend/src/routing/routing.service.ts:118) reads the route cache without calling ORS; the web planner meters its cache misses and daily ORS budget with it (road-trip-planner.md § Rate limits). - Sync caps (
mobile/src/domain/tripSync.ts:111-113, mirrored inbackend/src/sync/dto/sync.dto.ts): 250 trips per push, 500 stops per trip, 5,000 stops per push. Trips sync for every account, guests included, over the samePOST /api/sync/push/GET /api/sync/user-datachannel patches use. - Corridor SQL (
backend/src/trips/corridor-sql.ts) is shared with the web planner: crossed states, patches near the route, nearest-state assignment, progress along the drive. Stop-finding is hardwired to theus_statestable, so a route outside the U.S. computes but finds no stops.
Data model
Trip / RoadTrip and trip_patches in backend/prisma/schema.prisma, written
by the sync push; curated_trips and their stops are content (published through
/admin/publish, see admin-and-content-ops). Prod
served 111 curated trips on 2026-09-23 (104 day trips, 7 roads); not re-counted
since. A trip's visitedIds — the stops collected while that trip existed,
the only thing that counts as its progress — is device-only and not synced, so
a reinstall starts every trip at 0-of-N.
API surface
Unchanged by the flag: GET /api/trips/curated, the routing and corridor
endpoints under backend/src/trips/ and backend/src/routing/, and the sync
channel. All JWT-guarded except curated trips. The web planner's own endpoints
(backend/src/road-trips/) are documented in road-trip-planner.md.
Key files
mobile/app/(drawer)/trips.tsx:24,mobile/app/trip-planner.tsx:586— the twotrips_v2reads that choose legacy or new.mobile/src/components/navigation/drawerSections.ts:321-330— one Trips row on, Road Trip row off.mobile/src/components/trips/TripHomeScreen.tsx,TripMap.tsx,TripPreviewScreen.tsx— the legacy homes, the shared map, the preview.mobile/src/utils/rerouteGate.ts,roadCorridor.ts,roadTrip.ts(tripProgress) — engine constants and progress.backend/src/trips/trips.service.ts,corridor-sql.ts,corridor-grouping.ts,curated-trips.service.ts;backend/src/routing/ors.provider.ts,routing.service.ts.
Configuration and flags
trips_v2 (default on, both registries) selects the path. trips_tab
(backend-only, default off, dev) does nothing. ORS_API_KEY is required for
any routing. CONTENT_EDITING_ENABLED=true (local only) is what lets the
curated-trip seed scripts write; reaching prod is a human publish.
Edge cases and known limits
- A day trip live from before the switch is adopted into the new Trips once
(
mobile/app/(drawer)/trips.tsx:25-28); turning the flag off again shows it on the legacy Day Trip home. - No in-app editing of a saved trip on this path: delete and re-plan.
- No scheduling or calendar concept on the legacy screens (the new Trips has a calendar; see trips-v2.md).
- Routing is global; stop-finding is U.S.-only (
us_states). - Trips do not include an offline map pack; unlock needs a network round trip.
What this feature does NOT do
- It is not what users see. With
trips_v2on (default since 2026-10-06, so every store build that carries the flag), nobody reaches the Day Trip / Road Trip homes or the old planners except by deep link. Marketing copy must describe trips-v2, never this path. trips_tabdoes nothing, in any build, on or off.- It does not describe the web planner. That is deployed at
scout-patches.com/tripsbut unlaunched and flag-off; its doc ispublic: falseuntil launch and no copy may mention it yet. - Navigate in Scout does not save anything, route to an address, replace the platform maps hand-off, or work without a location fix.
- The campaign-anchored road system (
anchoredRoads/planRoadinroadTrip.ts) is in the codebase with no live caller.
Tests that cover it
Backend: backend/src/trips/*.spec.ts (corridor-grouping, curated-trips,
reroute, road-trip-pairing, trip-route), backend/src/routing/*.spec.ts
(route-steps, route-cache-key, routing.service),
backend/src/sync/__tests__/sync.trips.db.spec.ts (a pushed trip reaches
trips/trip_patches, re-push upserts, cross-account isolation, Trip Advisor
and Finish Line become earnable). Mobile: the trip-home, trip-planner and
trip-map screen tests under mobile/screen-tests/ and the trip-home screen
mock; mobile/src/components/navigation/__tests__/drawerSections.test.ts pins
the Trips/Road Trip row swap.
Open questions
- Whether to delete the legacy homes and planners outright rather than keep the flag-off path. Nothing decides that today.
- The 111-trip curated count is a 2026-09-23 reading; not re-queried.