The pictures picked up five faults that the run could not see, because a passing step only proves the click landed. The ring vanished on the lightbox: the accent is nearly black and so is the overlay. It now measures the surface behind it and puts a white hairline outside itself and the number only where the contrast is too low, so every other picture keeps the single line it had. The number fell outside the picture whenever the target was wider than the frame, which is every full-width row: the frame is known before the ring is drawn, so the number moves inside far enough to clear the edge. The satellite imagery was a grey rectangle although every tile came back 200. Leaflet fades a tile in over 200 ms and takes the progress from `+new Date()`, and the browser's clock is pinned to the picture day, so the opacity it writes on every frame is always 0. A stylesheet on Leaflet's own `leaflet-tile-loaded` outranks that inline style. The satellite guide also waits for decoded tiles now instead of for a tile element to exist. The uploaded files looked like nothing anyone would upload. A PDF is drawn with an issuer band, a reference, a table of fields and a footer, and the two photographs are gone: a drawn photograph reads as clip art at any size, so the trip carries a map screenshot with a pin and a booking confirmation in a browser window, which are graphics in reality too. In the panel, a step picture was covered into a 16:10 box and lost its sides; contained everywhere now, the hero and the result in 16:9. Beside that: the place guide gained the drag-and-drop route to a day as its fourth step, in all 23 languages, and `e2e/help/README.md` now holds the whole visual contract, the traps that cost this round (the pinned clock, prettier against the client sources, a killed run holding its ports) and how to find out which pictures a change forces to be retaken.
@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.