Setting up tRPC with Next.js 14

As web applications demand more streamlined, type-safe, and efficient data-fetching mechanisms, integrating tRPC with Next.js 14 becomes essential. This article will walk you through the step-by-step process of setting up tRPC with Next.js 14 App Router, ensuring you leverage the full potential of both tools.

Overview of tRPC and Next.js 14

Introduction to tRPC

tRPC stands for TypeScript Remote Procedure Call. It is an end-to-end typesafe API framework that allows you to build APIs using TypeScript interfaces and types. The primary advantage of tRPC is its ability to infer types directly from your backend logic, ensuring consistency and type safety across your application.

Features and Benefits of tRPC
  • Type Safety: Ensure that your API calls are consistent and error-free.

  • No Schema Duplication: Utilize TypeScript for both client and server without needing separate schema definitions.

  • Fast and Efficient: Minimize the overhead by directly calling server functions from the client.

  • Framework Agnostic: While we're focusing on Next.js in this article, tRPC supports various frameworks.

Introduction to Next.js 14 App Router

Next.js has long been a go-to framework for building React applications with server-side rendering (SSR) capabilities. The Next.js 14 release enhances these features with its App Router, providing an even more optimized and developer-friendly routing solution.

Initial Setup

Before diving into the integration, let's get a Next.js 14 project up and running and install the necessary dependencies for tRPC.

Creating a Next.js 14 Project
npx create-next-app@latest my-app --typescript
cd my-app
Installing Dependencies
npm install @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query zod

Configuring TypeScript

Configuration of TypeScript is paramount for leveraging the type safety provided by tRPC. Ensure that strict mode is enabled in your project.

Enabling Strict Mode in TypeScript

Open your tsconfig.json and add the following settings:

{
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true
  }
}

Setting Up tRPC

With the project set up and dependencies installed, let's configure the tRPC backend and server.

Creating the tRPC Backend

Create a file src/server/trpc.ts and initialize tRPC with a basic router:

import { initTRPC } from '@trpc/server';
import { z } from 'zod';

const t = initTRPC.create();

export const appRouter = t.router({
  hello: t.procedure
    .input(z.object({ text: z.string() }))
    .query(({ input }) => {
      return { greeting: `hello ${input.text}` };
    }),
});

export type AppRouter = typeof appRouter;
Configuring the tRPC Router in the Backend

Create a file src/pages/api/trpc/[trpc].ts and configure the tRPC HTTP handler:

import { createNextApiHandler } from '@trpc/next';
import { appRouter } from '../../../server/trpc';

export default createNextApiHandler({
  router: appRouter,
  createContext: () => null,
});

Integrating tRPC with Next.js 14 App Router

The integration of tRPC with Next.js 14's App Router allows us to create a seamless, type-safe data-fetching experience.

Creating tRPC Hooks

Create a file src/utils/trpc.ts and configure the tRPC client:

import { httpBatchLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../server/trpc';

export const trpc = createTRPCNext<AppRouter>({
  config() {
    return {
      links: [
        httpBatchLink({
          url: '/api/trpc',
        }),
      ],
    };
  },
  ssr: false,
});
Configuring _app.tsx for tRPC Integration

Wrap your root app page with the tRPC higher-order component (HOC):

import type { AppType } from 'next/app';
import { trpc } from '../utils/trpc';

const MyApp: AppType = ({ Component, pageProps }) => (
  <Component {...pageProps} />
);

export default trpc.withTRPC(MyApp);
Making API Requests Using tRPC Hooks

Utilize the React hooks to make API requests in your components. For example, in pages/index.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>
  );
}

Setting up Prisma for Database Integration

While optional, integrating Prisma ORM can significantly enhance your project's data management capabilities.

Installing and Configuring Prisma ORM
yarn add prisma @prisma/client
npx prisma init

Configure your database in the .env file and set up Prisma schema in prisma/schema.prisma.

Creating tRPC Endpoints and Procedures

Let's create tRPC endpoints to perform CRUD operations using the integrated Prisma ORM.

Defining Routers and Procedures in tRPC

Create a postRouter with CRUD operations:

import { router, publicProcedure } from './trpc';
import { z } from 'zod';
import { prisma } from '../lib/prisma';

export const postRouter = router({
  createPost: publicProcedure
    .input(z.object({
      title: z.string(),
      content: z.string(),
    }))
    .mutation(async ({ input }) => {
      const post = await prisma.post.create({
        data: input,
      });
      return post;
    }),
  getPosts: publicProcedure.query(async () => {
    const posts = await prisma.post.findMany();
    return posts;
  }),
});

Conclusion

In this article, we have meticulously walked through the setup and integration of tRPC with Next.js 14, ensuring a robust and type-safe development experience. Whether you're building small-scale applications or large enterprise solutions, this setup provides a solid foundation. If you're looking for further enhancements and a streamlined content management experience, consider exploring Wisp CMS, which offers comprehensive solutions tailored for modern web development needs.

By leveraging the combined powers of tRPC and Next.js 14, you're well on your way to creating highly efficient, maintainable, and type-safe web applications.

Start building your next project with tRPC and Next.js 14 today, and explore the world of seamless web development!

Raymond Yeh

Raymond Yeh

Published on 12 August 2024

Get engineers' time back from marketing!

Don't let managing a blog on your site get in the way of your core product.

Wisp empowers your marketing team to create and manage content on your website without consuming more engineering hours.

Get started in few lines of codes.

Choosing a CMS
Related Posts
Next.js 14 App Router: GET & POST Examples (with TypeScript)

Next.js 14 App Router: GET & POST Examples (with TypeScript)

Ready to master Next.js 14's App Router? Learn to create GET & POST route handlers with ease. Discover practical uses and advanced features using TypeScript. Start coding smarter today!

Read Full Story
API in Next.js 15: GET & POST Route Handler Examples

API in Next.js 15: GET & POST Route Handler Examples

Build an API Endpoint in Next.js 15 using the latest route handler. See what's new and get code example to serve your API.

Read Full Story
SSR with Remix using TanStack Query

SSR with Remix using TanStack Query

Explore SSR with Remix and TanStack Query in this article, focusing on setup, best practices, and real-world examples to boost SEO, enhance load times, and ensure smoother user interactions.

Read Full Story