rembrembdocs

tip

If you're using tRPC in a new project, consider using one of the example projects as a starting point or for reference: tRPC Example Projects

tRPC and Next.js are a match made in heaven! Next.js makes it easy for you to build your client and server together in one codebase. This makes it easy to share types between them.

tRPC includes dedicated tools to make the Next.js developer experience as seamless as possible.

Recommended file structure

Recommended but not enforced file structure. This is what you get when starting from the examples.

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

│ │ └── createRouter.ts # <-- router helper

│ └── utils

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

└── [..]

Add tRPC to existing Next.js project

1. Install deps

bash

yarn add @trpc/client @trpc/server @trpc/react @trpc/next zod react-query@3

2. Enable strict mode

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

json

// tsconfig.json

{

// ...

"compilerOptions": {

`// ...`

`"strict": true`

}

}

If strict mode is too much, at least enable strictNullChecks:

json

// tsconfig.json

{

// ...

"compilerOptions": {

`// ...`

`"strictNullChecks": true`

}

}

3. Create a tRPC router

Implement your tRPC router in ./pages/api/trpc/[trpc].ts. If you need to split your router into several subrouters, implement them in a top-level server directory in your project root, then import them into ./pages/api/trpc/[trpc].ts and merge them into a single root appRouter.

View sample router

4. Create tRPC hooks

Create a set of strongly-typed hooks using your API's type signature.

utils/trpc.ts

tsx

import { createReactQueryHooks } from '@trpc/react';

import type { AppRouter } from '../pages/api/trpc/[trpc]';

export const trpc = createReactQueryHooks<AppRouter>();

// => { useQuery: ..., useMutation: ...}

5. Configure _app.tsx

The createReactQueryHooks function expects certain parameters to be passed via the Context API. To set these parameters, create a custom _app.tsx using the withTRPC higher-order component:

pages/_app.tsx

tsx

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

import { AppType } from 'next/dist/shared/lib/utils';

import type { AppRouter } from './api/trpc/[trpc]';

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

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

};

export default withTRPC<AppRouter>({

config(config) {

`/**`

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

 `* @see https://trpc.io/docs/ssr`

 `*/`

`const url = process.env.VERCEL_URL`

  `` ? `https://${process.env.VERCEL_URL}/api/trpc` ``

  `: 'http://localhost:3000/api/trpc';`

`return {`

  `url,`

  `/**`

   `* @see https://tanstack.com/query/v3/docs/react/reference/QueryClient`

   `*/`

  `// queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },`

`};`

},

/**

* @see https://trpc.io/docs/ssr

*/

ssr: true,

})(MyApp);

6. Make API requests

pages/index.tsx

tsx

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

export default function IndexPage() {

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

if (!hello.data) {

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

}

return (

`<div>`

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

`</div>`

);

}

withTRPC() options

config-callback

The config-argument is a function that returns an object that configures the tRPC and React Query clients. This function has a ctx input that gives you access to the Next.js req object, among other things. The returned value can contain the following properties:

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

pages/_app.tsx

tsx

export default withTRPC<AppRouter>({

config(config) {

`/* [...] */`

},

ssr: true,

responseMeta({ clientErrors, ctx }) {

`if (clientErrors.length) {`

  `// propagate first http error from API calls`

  `return {`

    `status: clientErrors[0].data?.httpStatus ?? 500,`

  `};`

`}`

`// cache full page for 1 day + revalidate once every second`

`const ONE_DAY_IN_SECONDS = 60 * 60 * 24;`

`return {`

  ``'Cache-Control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,``

`};`

},

})(MyApp);

Next steps

Refer to the @trpc/react docs for additional information on executing Queries and Mutations inside your components.