We use cookies to understand how the site is used and to display ads. Analytics and advertising only run after you accept. You can change your choice anytime. Privacy policy

Skip to content
devvkit
$devvkit learn --librarie trpc-guide

tRPC Guide

[typescript][api][rpc]
JavaScript / TypeScript
Install
npm install @trpc/server @trpc/client @trpc/react-query zod

tRPC eliminates the HTTP API layer. Write TypeScript functions on the server, call them from client.

Types flow from server to client with zero code generation: autocompletion for every API call.

Works with React, Next.js, Express. HTTP under the hood with batching and WebSocket subscriptions.

Server Setup

Init server· Create tRPC instance.
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;

Router Definition

Query router· Define read endpoint.
export const userRouter = router({
  list: publicProcedure.query(() => db.user.findMany()),
  byId: publicProcedure.input(z.string()).query(({input}) => db.user.findUnique({where:{id:input}})),
});
Mutation· Define write endpoint.
createUser: publicProcedure.input(z.object({name:z.string(),email:z.string().email()}))
  .mutation(({input}) => db.user.create({data: input})),
Merge routers· Combine routers.
export const appRouter = router({ user: userRouter, post: postRouter });
export type AppRouter = typeof appRouter;

Client Integration

Vanilla client· Call procedures.
const client = createTRPCClient<AppRouter>({ links: [httpBatchLink({url:'http://localhost:3000/trpc'})] });
await client.user.list.query();
await client.user.createUser.mutate({name:'Alice',email:'a@b.com'});

React Integration

React Query· React hooks.
export const trpc = createTRPCReact<AppRouter>();
function Users() {
  const {data:users} = trpc.user.list.useQuery();
  const create = trpc.user.createUser.useMutation({onSuccess:() => trpc.user.list.useUtils().invalidate()});
}
Next.js adapter· App Router setup.
// app/api/trpc/[trpc]/route.ts
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
export { handler as GET, handler as POST };

Error Handling

Error handling· Typed TRPCError.
if (!user) throw new TRPCError({ code: 'NOT_FOUND', message: 'User not found' });

Advanced

Auth middleware· Protected procedure.
const authProcedure = publicProcedure.use(async ({ctx, next}) => {
  if (!ctx.user) throw new TRPCError({ code: 'UNAUTHORIZED' });
  return next({ ctx: { ...ctx, user: ctx.user } });
});