Skip to content

ADR-0009: Web frontend as a React/Vite app (apps/web)

Status: Accepted
Date: 2026-06-07
Owner: @satya
Supersedes: (none)
Superseded-by:(none)

Treeper is mobile-only at v0 (ADR-0001); PRODUCT.md lists “desktop / web app” as out of scope for v0. Separately, TripViz — a polished React/Vite map UI (animated MapLibre map, swipeable day cards, media carousels, multi-trip compare, color-coded trips) — already exists and reimplemented, more crudely, much of what treeper’s backend + workers already do (reel/PDF parsing, geocoding, itinerary search, media enrichment). We want a web surface for treeper without rebuilding the UI, and without forking the data model.

Adopt TripViz as treeper’s web frontend, brought into the monorepo as apps/web (Vite + React + TypeScript), authenticating via Supabase and talking only to the existing NestJS API (/v1) — never to the workers directly (ADR-0002/0003 boundaries hold). It adopts treeper’s data model natively (trip → destinations/days → activities); TripViz’s standalone schema and its throwaway Express server are dropped. Shared types live in a new packages/contracts consumed by apps/web (the backend may adopt it later).

OptionWhy not
Keep TripViz standalone, call treeper APIs over HTTP from a separate repoLooser cohesion, duplicated deploy/auth/types; not a true “v2 of treeper”.
Build a fresh web app from scratch on treeper’s modelThrows away TripViz’s mature, distinctive map/compare UI for no benefit.
Adapter layer (keep TripViz’s Trip/Spot schema, translate at the edge)Two models to maintain; native adoption keeps one source of truth (the backend).
Next.js instead of Vite SPANo SSR/SEO need for an authed app; Vite reuses TripViz as-is and ships static for Coolify.
  • A capable web client with zero new backend AI/scraping code — reuses NestJS + workers.
  • One data model (the backend’s); packages/contracts starts the long-planned shared-types layer.
  • TripViz’s map/carousel/compare UX becomes a treeper differentiator on the web.
  • CORS must be enabled on the backend (done, gated by CORS_ORIGINS).
  • apps/web is a self-contained npm app (no JS workspace root yet); packages/contracts is shared via a tsconfig/vite path alias rather than a workspace dependency.
  • Activities carry no route geometry and some lack coords — the web renders an order-curve and skips null-coord activities on the map (still lists them in cards).
  • Extract more of the backend’s DTOs into packages/contracts; have the backend consume it.
  • Consider code-splitting the MapLibre chunk.
  • Deploy apps/web on Coolify (app.itssatya.in) alongside backend/workers.