trpc-router
Entry point for all tRPC skills. Decision tree routing by task: initTRPC.create(), t.router(), t.procedure, createTRPCClient, adapters, subscriptions, React Query, Next.js, links, middleware, validators, error handling, caching, FormData, OpenAPI, multiple services. Includes a minimal working server and client.
Agent Skills
Set up and use TanStack Intent to provide AI agent skills for tRPC
From https://trpc.io/docs/skills
tRPC ships TanStack Intent skills to help AI coding agents work with tRPC. When your agent works on a task that matches a skill, it loads the skill's SKILL.md into context.
The skills ship inside @trpc/server, @trpc/client, @trpc/tanstack-react-query, @trpc/next and @trpc/openapi, so they're already in your node_modules.
Setup
1. Run install
The install command adds skill-loading guidance to your agent's config file (AGENTS.md, CLAUDE.md, etc.):
npx @tanstack/intent@latest installIt covers the skills shipped in tRPC and your other installed packages.
2. Use skills in your workflow
When your agent works on a task that matches a skill, it loads the corresponding SKILL.md into context to guide implementation.
To see which skills are available:
npx @tanstack/intent@latest listTo load one yourself, for example the server auth skill:
npx @tanstack/intent@latest load @trpc/server#auth3. Keep skills up-to-date
Skills version with library releases. When you update tRPC (e.g. npm update @trpc/server), you get the skills that match your installed version.
Skills by task
Each skill is generated from a page of these docs. Load one with npx @tanstack/intent@latest load <skill>, for example npx @tanstack/intent@latest load @trpc/server#server-setup.
Build the API
| Task | Skill |
|---|---|
| Initialize tRPC, define routers, procedures and context, export AppRouter | @trpc/server#server-setup |
| Add middleware and reusable base procedures | @trpc/server#middlewares |
| Validate inputs and outputs with Zod or another library | @trpc/server#validators |
| Throw, format and handle errors | @trpc/server#error-handling |
| Authenticate users and protect procedures | @trpc/server#auth |
| Call procedures from server code or tests | @trpc/server#server-side-calls |
| Set HTTP cache headers on responses | @trpc/server#caching |
| Accept FormData, files and binary inputs | @trpc/server#non-json-content-types |
| Stream real-time updates over SSE or WebSockets | @trpc/server#subscriptions |
| Send Date, Map, Set and other rich types with superjson | @trpc/client#superjson |
| Split the API across several services | @trpc/server#service-oriented-architecture |
Serve the API
| Task | Skill |
|---|---|
| Node.js HTTP server, the simplest setup | @trpc/server#adapter-standalone |
| Express | @trpc/server#adapter-express |
| Fastify | @trpc/server#adapter-fastify |
| AWS Lambda behind API Gateway or a Function URL | @trpc/server#adapter-aws-lambda |
| Fetch API and edge runtimes: Cloudflare Workers, Deno, Vercel Edge, Astro, Remix | @trpc/server#adapter-fetch |
Call the API
| Task | Skill |
|---|---|
| Create a TypeScript client, infer types, handle errors | @trpc/client#client-setup |
| Configure links: batching, streaming, splitting, WebSockets, SSE, retries | @trpc/client#links |
| Use tRPC with TanStack React Query | @trpc/tanstack-react-query#react-query-setup |
| Migrate from the classic @trpc/react-query client | @trpc/tanstack-react-query#react-query-classic-migration |
| Next.js App Router, including server components | @trpc/next#nextjs-app-router |
| Next.js Pages Router, SSR and SSG | @trpc/next#nextjs-pages-router |
| Generate an OpenAPI spec and a REST client | @trpc/openapi#openapi |
Learn more
For full documentation on TanStack Intent, see the Quick Start for Consumers guide.
Serving the API
Now that we have defined our router, we can serve it. tRPC has first-class adapters for many popular web servers. To keep it simple, we'll use the standalone Node.js adapter here.
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';
const server = createHTTPServer({
router: appRouter,
});
server.listen(3000);See the full backend code
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;import { z } from "zod";
import { publicProcedure, router } from "./trpc";
type User = { id: string; name: string };
export const appRouter = router({
userList: publicProcedure
.query(async () => {
const users: User[] = [{ id: '1', name: 'Katt' }];
return users;
}),
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const user: User = { id: input, name: 'Katt' };
return user;
}),
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const user: User = { id: '1', ...input };
return user;
}),
});
export type AppRouter = typeof appRouter;import { createHTTPServer } from "@trpc/server/adapters/standalone";
import { appRouter } from "./appRouter";
const server = createHTTPServer({
router: appRouter,
});
server.listen(3000);From https://trpc.io/docs/quickstart#serving-the-api
Using your new backend on the client
Let's now move to the client-side code and embrace the power of end-to-end typesafety. When we import the AppRouter type for the client to use, we have achieved full typesafety for our system without leaking any implementation details to the client.
1. Setup the tRPC Client
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server/appRouter';
// 👆 **type-only** imports are stripped at build time
// Pass AppRouter as a type parameter. 👇 This lets `trpc` know
// what procedures are available on the server and their input/output types.
const trpc = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
}),
],
});Links in tRPC are similar to links in GraphQL, they let us control the data flow to the server. In the example above, we use the httpBatchLink, which automatically batches up multiple calls into a single HTTP request. For more in-depth usage of links, see the links documentation.
2. Type Inference & Autocomplete
You now have access to your API procedures on the trpc object. Try it out!
// Inferred types
const user = await trpc.userById.query('1');
const createdUser = await trpc.userCreate.mutate({ name: 'Katt' });You can also use your autocomplete to explore the API on your client
trpc.u;From https://trpc.io/docs/quickstart#using-your-new-backend-on-the-client