What is tRPC?
tRPC lets the client call server procedures as if they were local functions, with full type safety and no code generation or separate schema language. The procedure's input and output types flow straight to the client, so the contract is the code itself.
Why it matters
tRPC is the purest expression of the TypeScript full-stack seam: change a procedure's signature and the client gets a compile error instantly, with no REST boilerplate or schema duplication. For a TypeScript monorepo where one team owns both ends, it removes a whole layer of friction and bugs.
What to learn
- Procedures: queries and mutations
- Input validation with Zod
- How types reach the client without generation
- Routers and merging them
- Context for per-request data like the user
- Integrating tRPC with TanStack Query
- When REST or GraphQL is the better choice
Common pitfall
Choosing tRPC for an API that public or non-TypeScript clients must consume. Its whole advantage is shared TypeScript inference within one codebase; external consumers need a language-agnostic, documented contract — REST with OpenAPI or GraphQL. Use tRPC for your own client, not as a public API.
Resources
Primary (free):
- tRPC — Documentation · docs
- tRPC — React Query integration · docs
- Zod — Documentation · docs
Practice
Build a tRPC router with one query and one mutation, validating input with Zod and reading the user from context. Call both from a typed client. Change a procedure's input type and watch the client fail to compile. Done when the contract is enforced by types with zero duplication.
Outcomes
- Define typesafe queries and mutations with validated input.
- Explain how types reach the client without generation.
- Add per-request context like the authenticated user.
- Choose tRPC versus REST/GraphQL appropriately.