Contract-First API
A tRPC contract is not a document — it is code that both applications import.
The layers
packages/schemas— zod schemas andz.infertypes. The single source of truth.packages/api— tRPC routers built on top of those schemas.- Frontend imports only
type AppRouterand gets end-to-end inference.
Validation boundaries
- Input validation — zod schemas on every procedure.
- Data validation —
db.jsonis parsed at startup, the server fails fast on invalid data. - Transport — queries use
GET, mutations usePOST, superjson for serialization.
If the schema does not run anywhere, it is documentation, not a contract.
Responses without envelopes
articles.list returns Article[] directly. tRPC already namespaces procedures by path, so { items: [...] } wrappers only add noise on the client.




