tRPC: the type-only import is the whole trick, and the Deno quickstart line is broken
GitHub describes it as 🧙‍♀️ Move Fast and Break Nothing. End-to-end typesafe APIs made easy.. The repository metadata lists TypeScript as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- tRPC is a MIT licensed TypeScript framework for building and consuming fully typesafe APIs with no schemas and no code generation. The mechanism is elegant, the client surface is small, and the details around it, a truncated Deno command, skills installed from another organisation, and a clean script whose prune clause binds to the wrong term, are where the friction is.
- Who is it for?
- tRPC fits a TypeScript codebase where the client and server are built together, you want autocompletion on inputs, outputs and errors, and you would rather not maintain a schema or a codegen step. It does not fit a mixed-language team, since the guarantee is a compile-time property of shared type declarations, and it does not fit anyone who needs runtime validation of untrusted payloads.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The client imports type declarations and no code, and that is the entire design
The caption under the demo in the README is the whole pitch: the client is not importing any code from the server, only its type declarations. That is what lets tRPC offer full static typesafety and autocompletion on the client for inputs, outputs and errors without schemas and without code generation, and it is why the feature list claims no run-time bloat and no build pipeline. A procedure is a function on the server and a typed proxy on the client, and the only thing crossing the module boundary is the compiler's view of it. The consequence follows from the same sentence. The guarantee is compile-time and lives inside a TypeScript build, so a caller that is not TypeScript, or a payload that arrives from outside your project, gets none of it. And since the intro says there are no schemas, nothing on the path validates shape at run time. The type system tells you the contract; something else has to trust that the wire matches it.
Zero dependencies and batteries included are describing two different packages
The feature list contains both claims, and they are not in conflict once you notice they point at different things. Light is stated as zero deps and a tiny client-side footprint. Batteries included is stated as React, Next.js, Express and Fastify adapters, immediately qualified with the note that tRPC is not tied to React and that there are many community adapters for other libraries, linked through an awesome-trpc page. So the dependency-free thing is the core, and the adapters are where a dependency tree appears. This matters when you audit what you are about to install. Running a dependency check against the core tells you almost nothing about the Next adapter or the Express adapter you will actually import, and the community adapters carry no such guarantee at all. Ask which package in your dependency graph is which: for a request-batching and subscriptions story you are also buying adapters, a router, and whatever the community layer pulls in.
Four quickstart lines carry an example-path flag and the Deno line does not
The quickstart offers the same full-stack Next.js starter through five package managers. Four of them are complete:
yarn create next-app --example https://github.com/trpc/trpc --example-path examples/next-prisma-starter trpc-prisma-starter
npx create-next-app --example https://github.com/trpc/trpc --example-path examples/next-prisma-starter trpc-prisma-starter
pnpm create next-app --example https://github.com/trpc/trpc --example-path examples/next-prisma-starter trpc-prisma-starter
bunx create-next-app --example https://github.com/trpc/trpc --example-path examples/next-prisma-starter trpc-prisma-starter
deno init --npm next-app --example https://github.com/trpc/trpThe fifth line is not the same command. The repository URL is cut off at trpc/trp, and the --example-path argument that points at examples/next-prisma-starter is absent entirely. A reader who follows the Deno line does not get the same starter as the reader who follows the other four, and nothing in the page flags the difference. If you are on Deno, treat the published command as broken, copy the shape of the npm line and correct the URL and the path yourself, and check what you actually got before reading any of the tutorial material.
The tRPC skills for coding agents are installed from another organisation, unpinned
There is a short section aimed at people using AI coding agents, naming Claude Code, Cursor and Windsurf, and the entire instruction is one line:
npx @tanstack/intent@latest installNote what that is. The skills that teach a coding agent about tRPC are not published as a tRPC package. They come from @tanstack/intent, a different project's namespace, and they are run at the latest tag, so there is no version you can pin and no changelog tied to a tRPC release. The consequence is a moving definition of what your agent believes tRPC's API looks like, independent of the version of tRPC you have installed. That cuts both ways. It means an agent will produce plausible tRPC code quickly, and it means the instructions it received may correspond to a newer or older API than the one in your lockfile. After installing, check the generated guidance against the tRPC version you actually depend on rather than assuming the agent knows.
Contributing requires Node 24 and pnpm 12, and the dev loop is three orchestrators
The root manifest is private, declares type module, and pins its toolchain twice: engines asks for node ^24.0.0 and pnpm ^12.0.0, and packageManager pins [email protected]. Building, dev, lint and the typechecks all run through turbo, with filters such as turbo --filter=./packages/* build and a parallel pnpm typecheck across the same packages, while tests are vitest. Alongside that sit pnpm-workspace.yaml for dependency linking and lerna.json for versioning, so a contributor is running three coordination tools at once. The link-all script, meant to make local development pleasant, is also worth reading before you trust it:
"link-all": "cd packages/server && cd ../server && pnpm link --global && cd ../client && pnpm link --global && cd ../react-query && pnpm link --global && cd ../next && pnpm link --global"The second cd is ../server relative to packages/server, so it lands back where it started and the server package is linked twice while client, react-query and next are linked once each. Harmless, but it tells you the script is not carefully maintained. The global linking is the part with teeth, since those four packages then shadow the published ones in every other project on the machine until you unlink them.
The clean script's prune clause is bound to the wrong term in the find chain
Cleaning build output is one line, and it is worth reading closely:
"clean": "find . -name node_modules -o -name .turbo -o -name .next -o -name dist -o -name __generated__ -type d -prune -o -name '*.tsbuildinfo' | xargs rm -rf"In a find expression, implicit and binds tighter than or, so this is a chain of alternatives in which the -type d -prune pair applies only to the __generated__ term. The earlier directory names are therefore printed rather than pruned, and the traversal descends into node_modules, .next and dist looking for more matches before anything is deleted. The deletion itself is correct, since rm -rf takes files and directories alike, so the outcome is right and the cost is wrong: on a monorepo with a large install this turns a fast clean into a full walk of the dependency tree. A parenthesised expression would fix it. Nobody appears to have needed to, which is a fair signal about how often the script runs.
Request batching is automatic, so your server sees fewer requests than your client made
One feature line reads that request batching combines requests made at the same time automatically into one, and subscriptions are supported alongside it. The batching part is the one to think about before you adopt, because it changes what the rest of your infrastructure observes. If your client fires six queries in the same tick, your server may receive one HTTP request rather than six, and everything that reasons per request is now working from a different count than your application code. That includes rate limiters whose budget is expressed in requests, analytics that report request volume, CDNs and proxies with per-request caching rules, and any per-request token or nonce issuance. None of this is wrong, but it is a behaviour you inherit rather than a setting you chose, and the README does not describe a threshold, a size limit or a way to turn it off for the calls that must arrive individually. If a specific endpoint depends on being its own request, verify that rather than assuming.
The examples directory is the real documentation, and three of its folders are hidden
There is no tutorial in this repository, and the examples folder is what stands in for one. Reading its names tells you the deployment surface precisely: minimal and minimal-react, express-minimal, express-server and fastify-server for Node servers, kitchen-sink, lazy-load, minimal-content-types and minimal-per-procedure-errors for feature isolation, bun, cloudflare-workers and deno-deploy for edge and worker runtimes, lambda-url, lambda-api-gateway and lambda-api-gateway-streaming for AWS Lambda with two distinct entry shapes, and a long set of Next.js variants including next-edge-runtime, next-formdata, next-big-router, next-prisma-starter, next-prisma-todomvc and next-prisma-websockets-starter. Three more are prefixed with a dot: .experimental, .railway and .test. A dot-prefixed directory is skipped by ordinary globs, so those three are not part of the default workspace set, and an example you discover there is outside the normal build and typecheck coverage. Pick the folder that matches your runtime and read it before the docs site, because it is the version that compiles.
Editorial conclusion
tRPC fits a TypeScript codebase where the client and server are built together, you want autocompletion on inputs, outputs and errors, and you would rather not maintain a schema or a codegen step. It does not fit a mixed-language team, since the guarantee is a compile-time property of shared type declarations, and it does not fit anyone who needs runtime validation of untrusted payloads. Before you adopt it, decide how your requests are batched and what that does to per-request infrastructure, pin the version rather than tracking the major, and remember that the type safety stops at the boundary where a non-TypeScript caller takes over.
Frequently asked questions
What does tRPC stand for?
The repository never expands the acronym anywhere on its README. What it does say is that tRPC lets you build and consume fully typesafe APIs without schemas or code generation, implemented in TypeScript and released under the MIT licence, with the client importing only type declarations from the server.
Is tRPC the same as gRPC?
The README contains no comparison with gRPC and does not mention it. It describes tRPC's own properties instead: zero dependencies, a tiny client-side footprint, no code generation or build pipeline, adapters for React, Next.js, Express and Fastify, plus subscriptions and request batching.
What is tRPC vs rest?
There is no REST comparison on the page either. The claim tRPC makes is compile-time: full static typesafety and autocompletion on the client for inputs, outputs and errors, achieved with no schemas, so nothing on the path validates the payload shape at run time.
Is oRPC better than tRPC?
oRPC is not mentioned anywhere in this repository, so there is nothing here to weigh against it. The nearest thing to a comparison surface is the community adapter listing at trpc.io/docs/awesome-trpc, which is where the project points when it wants to show how it fits libraries beyond its own first-party adapters.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/trpc-trpc)