Skip to content

@trpc/server

The tRPC server library

trpc-router

222 linesSource

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.):

shell
npx @tanstack/intent@latest install

It 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:

shell
npx @tanstack/intent@latest list

To load one yourself, for example the server auth skill:

shell
npx @tanstack/intent@latest load @trpc/server#auth

3. 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

TaskSkill
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

TaskSkill
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

TaskSkill
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.

server/index.ts
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';

const server = createHTTPServer({
  router: appRouter,
});

server.listen(3000);
See the full backend code
server/trpc.ts
import { initTRPC } from '@trpc/server';

const t = initTRPC.create();

export const router = t.router;
export const publicProcedure = t.procedure;

server/appRouter.ts
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;

server/index.ts
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

client/index.ts
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!

client/index.ts
// 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

client/index.ts
trpc.u;

From https://trpc.io/docs/quickstart#using-your-new-backend-on-the-client