Architecture
Data flow
A complete route through the stack, from map click to database row.
Walking through a route create:
- User clicks the map. Mapbox emits a click with lng/lat. The web app's map component calls
addWaypoint(coords)on the routing Zustand store from@routess/core. - Store updates. The store appends the waypoint, recalculates total distance/duration locally, and notifies subscribers. The sidebar re-renders.
- Persistence side-effect. A subscriber in
apps/webcallsapiClient.routes.upsertCurrent(state), debounced ~500ms. - HTTP request.
@routess/api-clientissuesPATCH /api/v1/routes/:idwith the JWT cookie attached. - API receives. NestJS authenticates the cookie, validates the body via DTOs, and persists via MikroORM.
- Response. The API returns the canonical route. The store reconciles (if the server normalized anything).
Why client-first state?
routess prefers fast local state with eventual server reconciliation. The map needs to feel instantaneous; round-tripping every click would feel laggy.
Failure modes
- Server unreachable: local edits keep working; the persistence layer queues and retries with exponential backoff.
- Auth expired: server returns 401; web redirects to sign-in.
- Validation failure: server returns 422 with field-level errors; web shows a toast and keeps the local edit.