Every journey map (the desktop aside, the phone screens and the shared page) now carries four switches: Plan, Recorded, Entries and Photos, each with its count, a spinner while it loads, the warning tone when it could not be read and the reason when it has nothing to show. A switch only hides, in place: the map is not rebuilt and keeps its view, and the choice is kept in this browser per journey (per link on a shared page, by a hash of its token). The plan draws the places the linked trips put on their days as hollow dashed pins and the trips' GPX routes dashed; a place an entry was written about is not drawn twice, the entry's pin carries a check instead. The stays a day report was taken over from show as dots in the colour of their day. Marks on one spot join into a disc with their number and open as a list; a picked place or stay opens a card with its trip, days and times and leads to its entry. A key beside the switches explains every pin and line and says that a plan is no proof of a visit. The phone timelines now show the photos too. The GPX routes come with the map's layers through the linked trips, read only while the journey's track switch is on; the frozen /tracks answer stays Studio's. The share settings on desktop and phone get Trip plan and Recorded routes under Map, off by default and only switchable while the map is shared.
@trek/shared
Single source of truth for TREK's API contracts, expressed as Zod schemas and consumed by both the server (request validation + inferred DTO types) and the client (typed requests/responses).
This package is part of the incremental NestJS + React 19 migration (see the "Brownfield Rewrite" board). It is intentionally dormant until modules start importing it — adding it changes nothing for users.
Rules
- One folder per domain:
src/<domain>/<domain>.schema.ts(+.spec.ts). - Domain-agnostic building blocks live in
src/common/. - A route is only considered migrated once its contract lives here.
- Schemas are the source of truth; server DTOs and client types are inferred from them
(
z.infer<typeof schema>), never hand-duplicated.
Consumption (dev)
Both apps resolve @trek/shared to this package's TypeScript source:
- Server (
tsx): viapathsinserver/tsconfig.json. - Client (
vite): viaresolve.aliasinclient/vite.config.ts(+pathsfor the type-checker).
Production packaging (Docker / workspace wiring) is introduced in card F2, when the server first depends on this package at runtime. Until then prod builds are untouched.
Not yet here
The canonical error envelope is finalised in card F5 (it must match TREK's current Express error responses byte-for-byte), so it is deliberately not invented in F1.