Skip to content

apps/web — Treeper web frontend

Vite + React + TypeScript map UI (ported from TripViz). It authenticates with Supabase and talks only to the NestJS API (apps/backend, /v1) — never to the workers directly. Adopts the backend data model natively (trip → destinations/days → activities); shared types come from packages/contracts.

See ADR-0009 and feature 0013.

Two modes (Vite inlines VITE_* at build/start time):

  • npm run devvite --mode prod, loads .env.prod (points at the hosted stack).
  • npm run dev:localvite, loads .env.local (points at the local stack).
Terminal window
cd apps/web
npm install
# Local stack (see "Full local stack" below): create .env.local then
npm run dev:local # http://localhost:5173

.env.local example (local Supabase from supabase start + local backend):

VITE_API_BASE=http://localhost:3000
VITE_SUPABASE_URL=http://127.0.0.1:55321
VITE_SUPABASE_ANON_KEY=<local anon key from `supabase status` / apps/backend/.env.local>

The backend must allow the web origin: CORS_ORIGINS=http://localhost:5173 in apps/backend/.env.local (already the default).

Terminal window
# 1. Docker + local Supabase (see infra/supabase/README.md)
colima start --cpu 4 --memory 6 # or Docker Desktop
cd infra && supabase start # API on 127.0.0.1:55321
# 2. Backend + workers (native; both read their .env.local)
cd ../apps/backend && npm install && npm run start:dev # :3000
cd ../apps/workers && uv sync && uv run uvicorn treeper_workers.main:app --port 8000
# 3. Web
cd ../apps/web && npm run dev:local # :5173

Local signup confirmations are off (enable_confirmations=false), so email sign-up gives an immediate session. Auth emails land in Mailpit (127.0.0.1:55324).

VarPurpose
VITE_API_BASETreeper NestJS base URL. The client adds /v1 if missing (so …/v1 or bare host both work).
VITE_SUPABASE_URL / VITE_SUPABASE_ANON_KEYSupabase project for auth (anon key is browser-safe; RLS + API enforce access).
VITE_MAP_STYLEOptional MapLibre style; defaults to free OpenFreeMap Liberty.
src/
auth/ supabase client, useAuth, AuthGate (email + Google)
api/ client (bearer), trips (read), imports (M2 pipeline), view-model
map/ MapView, ActivityMarkers, RouteLayer (MapLibre)
cards/ DayDeck (swipe), DayCard, ActivityRow
components/ TopBar (switcher + import + compare), CompareLegend, ImportSheet
state/ useTripStore (multi-trip + compare)
lib/ activityMeta (kind→icon/color), geo, tripColors, env
Terminal window
npm run build # tsc --noEmit && vite build --mode prod → dist/

Dockerfile builds a static image served by nginx. Build context is the repo root (it needs packages/contracts), and VITE_* are build args (Vite inlines them):

Terminal window
# from the repo root
docker build -f apps/web/Dockerfile \
--build-arg VITE_API_BASE=https://api-treeper.itssatya.in/v1 \
--build-arg VITE_SUPABASE_URL=https://supabase-treeper.itssatya.in \
--build-arg VITE_SUPABASE_ANON_KEY=<prod anon key> \
-t treeper/web .
docker run -p 8080:80 treeper/web # http://localhost:8080

Coolify deploy: see infra/coolify/DEPLOY.md → Web application.

M1 (auth + render) and M2 (import: reel/URL/PDF/text → workers → review → commit) implemented; build + local stack verified (sign-in → trips render; long-text import → parse → commit). Remaining milestones (discovery, edit, media, public view) tracked in feature 0013.