Skip to main content
Version: 11.x

Express Adapter

Example app​

DescriptionLinks
Express server & procedure calls with Node.js.

How to add tRPC to existing Express project​

1. Install deps​

bash
yarn add @trpc/server zod
bash
yarn add @trpc/server zod

Zod isn't a required dependency, but it's used in the sample router below.

AI Agents

If you use an AI coding agent, install tRPC skills for better code generation:

bash
npx @tanstack/intent@latest install
bash
npx @tanstack/intent@latest install

2. Create a tRPC router​

Implement your tRPC router. A sample router is given below:

server.ts
ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
 
export const t = initTRPC.create();
 
export const appRouter = t.router({
getUser: t.procedure.input(z.string()).query((opts) => {
opts.input; // string
return { id: opts.input, name: 'Bilbo' };
}),
createUser: t.procedure
.input(z.object({ name: z.string().min(5) }))
.mutation(async (opts) => {
// use your ORM of choice
return { id: '1', ...opts.input };
}),
});
 
// export type definition of API
export type AppRouter = typeof appRouter;
server.ts
ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
 
export const t = initTRPC.create();
 
export const appRouter = t.router({
getUser: t.procedure.input(z.string()).query((opts) => {
opts.input; // string
return { id: opts.input, name: 'Bilbo' };
}),
createUser: t.procedure
.input(z.object({ name: z.string().min(5) }))
.mutation(async (opts) => {
// use your ORM of choice
return { id: '1', ...opts.input };
}),
});
 
// export type definition of API
export type AppRouter = typeof appRouter;

If your router file starts getting too big, split your router into several subrouters each implemented in its own file. Then merge them into a single root appRouter.

3. Use the Express adapter​

tRPC includes an adapter for Express out of the box. This adapter lets you convert your tRPC router into an Express middleware.

server.ts
ts
import { initTRPC } from '@trpc/server';
import * as trpcExpress from '@trpc/server/adapters/express';
import express from 'express';
 
// created for each request
const createContext = ({
req,
res,
}: trpcExpress.CreateExpressContextOptions) => ({}); // no context
type Context = Awaited<ReturnType<typeof createContext>>;
 
const t = initTRPC.context<Context>().create();
const appRouter = t.router({
// [...]
});
 
const app = express();
 
app.use(
'/trpc',
trpcExpress.createExpressMiddleware({
router: appRouter,
createContext,
}),
);
 
app.listen(4000);
server.ts
ts
import { initTRPC } from '@trpc/server';
import * as trpcExpress from '@trpc/server/adapters/express';
import express from 'express';
 
// created for each request
const createContext = ({
req,
res,
}: trpcExpress.CreateExpressContextOptions) => ({}); // no context
type Context = Awaited<ReturnType<typeof createContext>>;
 
const t = initTRPC.context<Context>().create();
const appRouter = t.router({
// [...]
});
 
const app = express();
 
app.use(
'/trpc',
trpcExpress.createExpressMiddleware({
router: appRouter,
createContext,
}),
);
 
app.listen(4000);

Your endpoints are now available via HTTP!

EndpointHTTP URI
getUserGET http://localhost:4000/trpc/getUser?input=INPUT

where INPUT is a URI-encoded JSON string.
createUserPOST http://localhost:4000/trpc/createUser

with req.body of type {name: string}