rembrembdocs

caution

This guide is for the Next.js Pages Router. If you are using the Next.js App Router, see the App Router setup guide instead.

Recommended file structure

We recommend a file structure like this one, although it is not enforced by tRPC. This is what you'll see in our examples. The rest of this page will take you through the process of adding tRPC in to this structure.

graphql

.

├── prisma # <-- if prisma is added

│ └── [..]

├── src

│ ├── pages

│ │ ├── _app.tsx # <-- add `withTRPC()`-HOC here

│ │ ├── api

│ │ │ └── trpc

│ │ │ └── [trpc].ts # <-- tRPC HTTP handler

│ │ └── [..]

│ ├── server

│ │ ├── routers

│ │ │ ├── _app.ts # <-- main app router

│ │ │ ├── post.ts # <-- sub routers

│ │ │ └── [..]

│ │ ├── context.ts # <-- create app context

│ │ └── trpc.ts # <-- procedure helpers

│ └── utils

│ └── trpc.ts # <-- your typesafe tRPC hooks

└── [..]

Add tRPC to existing Next.js project

1. Install deps

npm install @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@latest zod

AI Agents

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

bash

npx @tanstack/intent@latest install

The Next.js integration is actually a combination of our React Query Integration and some Next.js specific integrations.

2. Enable strict mode

If you want to use Zod for input validation, make sure you have enabled strict mode in your tsconfig.json:

tsconfig.json

diff

"compilerOptions": {

+ "strict": true

}

If strict mode is too harsh, you'll at least want to enable strictNullChecks:

tsconfig.json

diff

"compilerOptions": {

+ "strictNullChecks": true

}

3. Create a tRPC router

Initialize your tRPC backend in src/server/trpc.ts using the initTRPC function, and create your first router. We're going to make a simple "hello world" router and procedure here - but for deeper information on creating your tRPC API you should refer to:

View sample backend

4. Create tRPC hooks

Use the createTRPCNext function to create a set of strongly-typed hooks from your API's type signature.

utils/trpc.ts

tsx

import { httpBatchLink } from '@trpc/client';

import { createTRPCNext } from '@trpc/next';

import type { AppRouter } from '../server/routers/_app';

function getBaseUrl() {

if (typeof window !== 'undefined')

`// browser should use relative path`

`return '';`

if (process.env.VERCEL_URL)

`// reference for vercel.com`

``return `https://${process.env.VERCEL_URL}`;``

if (process.env.RENDER_INTERNAL_HOSTNAME)

`// reference for render.com`

``return `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;``

// assume localhost

return `http://localhost:${process.env.PORT ?? 3000}`;

}

export const trpc = createTRPCNext<AppRouter>({

config(config) {

`return {`

  `links: [`

    `httpBatchLink({`

      `/**`

       `* If you want to use SSR, you need to use the server's full URL`

       `* @see https://trpc.io/docs/client/nextjs/pages-router/ssr`

       `**/`

      ``url: `${getBaseUrl()}/api/trpc`,``

      `// You can pass any HTTP headers you wish here`

      `async headers() {`

        `return {`

          `// authorization: getAuthCookie(),`

        `};`

      `},`

    `}),`

  `],`

`};`

},

/**

* @see https://trpc.io/docs/client/nextjs/pages-router/ssr

**/

ssr: false,

});

note

createTRPCNext does not work with the tRPC-v9 interop mode. If you are migrating from v9 using interop, you should continue using the old way of initializing tRPC.

5. Configure _app.tsx

Wrap your root app page in the trpc.withTRPC HOC, similar to this:

pages/_app.tsx

tsx

import type { AppType } from 'next/app';

import { trpc } from '../utils/trpc';

const MyApp: AppType = ({ Component, pageProps }) => {

return <Component {...pageProps} />;

};

export default trpc.withTRPC(MyApp);

6. Make an API request

You're all set!

You can now use the React hooks you have just created to invoke your API. For more detail see the React Query Integration

pages/index.tsx

tsx

import { trpc } from '../utils/trpc';

export default function IndexPage() {

const hello = trpc.hello.useQuery({ text: 'client' });

if (!hello.data) {

`return <div>Loading...</div>;`

}

return (

`<div>`

  `<p>{hello.data.greeting}</p>`

`</div>`

);

}

createTRPCNext() options

config-callback

The config-argument is a function that returns an object that configures the tRPC and React Query clients. This function receives an object with an optional ctx property (of type NextPageContext) that gives you access to the Next.js req object during server-side rendering. The returned value can contain the following properties:

overrides: (default: undefined)

Configure overrides for React Query's hooks.

ssr-boolean (default: false)

Whether tRPC should await queries when server-side rendering a page. Defaults to false.

responseMeta-callback

Ability to set request headers and HTTP status when server-side rendering.

Example

utils/trpc.ts

tsx

import { createTRPCNext } from '@trpc/next';

import type { AppRouter } from '../server/routers/_app';

export const trpc = createTRPCNext<AppRouter>({

config(config) {

`return {`

  `links: [`

    `/* [...] */`

  `],`

`};`

},

});

Next steps

Browse the rest of the docs to learn more about things like authorization, middlewares, and error handling.

You can also find information about queries and mutations now that you're using @trpc/react-query.