Developing a Next.js app directory with tRPC is a game-changer for building scalable and maintainable APIs.
You can create a Next.js app directory with tRPC by setting up a new project using the tRPC starter template, which includes a pre-configured Next.js app with tRPC already set up.
This approach allows you to get started quickly and easily, with a solid foundation for building your API.
Setting Up
To set up a trpc Next.js app directory, start by installing tRPC in your project. This involves adding it to your package.json file.
Open package.json and add the necessary dependencies, including tRPC. This will enable you to use tRPC's features in your project.
Create a new folder called trpc and add some essential files to it. This includes a context.ts file, which will contain your tRPC context, and a trpc.ts file, where you'll define your tRPC configuration and helpers.
In the trpc.ts file, you'll initialize tRPC with initTRPC, which allows you to use transformers like superjson to serialize complex data types. This ensures that your data is properly formatted for tRPC to handle.
Next, create a reusable procedure called publishProcedure, which will serve as a starting point for your tRPC endpoints. This procedure can be used to create queries, mutations, or subscriptions that your frontend can access.
Create a routes.ts file to define your routes and endpoints. This is where you'll map your procedures to specific URLs and implement the logic for each endpoint.
Creating Middleware
We'll start by creating an auth middleware that checks if a user is logged in. This middleware will be used to protect routes that require authentication.
In our tRPC trpc.ts file, we'll use the procedure helper to create a public procedure for any public routes.
To create an authenticated procedure, we'll use the withAuth middleware we created earlier. This middleware will ensure that only authenticated users can access the protected routes.
Next, we need to create our API endpoint.
App Directory Structure
The app directory structure is a significant change from the older pages router. In the app directory, routes are determined by directory names instead of file names.
Inside these directories, you'll find files with specific names to perform different functions. This is a key difference from the older approach where the file name dictated the route name.
The app directory structure uses a directory-based pattern, where the name of the directory dictates the route. This is a more organized and scalable approach, but it does require getting used to.
Frontend - Next.js
To get started with Next.js, you'll want to create a new project with the app directory. This is the new and recommended way to build Next.js applications, leveraging features like React Server Components and Suspense loading states.
The final folder structure will be:
app
pages
...
...
index.tsx
...
...
To integrate tRPC in your frontend, start by installing the necessary dependencies and creating a tRPC client for React. This client will contain all the routes information from your AppRouter.
You can create the tRPC client by using the createTRPCReact function provided by tRPC. This function will help you create a tRPC client for React with ease.
Next, you'll need to create a tRPC provider so that your whole app can access the context. This is done by wrapping the QueryClientProvider with the tRPC provider.
Preparing Context
As you're setting up your app's directory structure, it's essential to prepare the context for your tRPC routers. The generated routers require a Prisma field in the context.
To include this field, you'll need to create a context with a Prisma client instance. Most likely, you'll want to use one created with enhance to enforce access control policies.
This ensures your client has the necessary permissions to manage data securely. By doing so, you'll have a solid foundation for your app's context.
Using the Router
When working with the App Router in Next.js, you'll need to create a tRPC helper for use in your client code. This helper is crucial for making API calls.
The tRPC helper is created using the `fetchRequestHandler` function from the tRPC library. This is because the App Router uses standard Request and Response objects, unlike the Pages router which uses Next.js-specific objects.
Using the `fetchRequestHandler` function allows you to make API calls without worrying about the underlying implementation details of the App Router. This makes your code more flexible and easier to maintain.
Route.ts
In an app directory project, you'll notice a new pattern for defining API routes, which are now called Route Handlers. This is a significant change from the past when you could define an API route with a file path like api/example.ts.
To make a Route Handler available, you need to structure the file like /app/api/example/route.ts. This is a specific requirement for API endpoints to be accessible at the desired URL.
The route file, which is the new pattern for defining API routes, is a crucial part of the App Router. It's where you'll define the logic for handling API requests and responses.
Route Groups
Route Groups are a way to organize your routes in Next.js, and you can learn more about them in the Next.js documentation.
Route Groups can be useful for grouping related routes together, making it easier to manage and maintain your application's routing.
By using Route Groups, you can simplify your routing configuration and make your code more readable.
Route Groups are a powerful feature in Next.js, allowing you to group routes based on their functionality or purpose.
For example, you might create a Route Group for all your API routes, making it easy to navigate and manage them.
Route Groups can also help with code organization and reusability, making it easier to share code between routes.
Nested Routes
To configure nested routes, create a new directory inside the app directory called nested. Then, create a new file inside the nested directory called page.tsx and add the code.
In your browser, navigate to http://localhost:3000/nested to see the page defined above with the Nested Route text on the screen. This should appear as expected.
Nested routes are designed to be rendered via a layout file and not directly accessed like other types of routes are.
Using tRPC
You can create a tRPC helper to use in your client code. This is necessary because the App Router in Next.js uses standard Request and Response objects, unlike the Pages router which uses specific objects provided by Next.js.
To use tRPC with NestJS & NextJS, you'll need to add the tRPC server in the NestJS app and the tRPC client in the NextJS app. One extra thing to do in the NextJS service is add the NEXT_PUBLIC_NESTJS_SERVER environment variable.
Before using tRPC with NextJS 13, you need to understand the paradigm shift that's happening. With NextJS 13, network requests are now made from the server side, enabled by Server Components.
You'll need to install the tRPC client package in the NextJS application and add a new file called trpc.ts. In this file, you'll define the tRPC client using the AppRouter type, which provides end-to-end type safety.
You can make a server-side tRPC call inside NextJS by updating the function to an async function and using the trpc client to call the hello procedure. The url property in the trpc client should point to the tRPC server, which is localhost:4000/trpc in this case.
Adding tRPC Client
To add the tRPC client in the NextJS app, you'll need to install the @trpc/server package. This is required to avoid a peer dependency error.
Begin by adding a new file called trpc.ts inside the app/ directory. In this file, you'll define the tRPC client.
The url property of the trpc client should point to the tRPC server, which in our case is localhost:4000/trpc. You'll need to update this to use environment variables if you're deploying.
To make a server-side tRPC call inside NextJS, update the function in the page.tsx file to an async function and use the trpc client to call the hello procedure.
Before diving into client-side calls, you'll need to make a small tweak to the tRPC client in the NextJS app.
The tRPC client package has a limitation regarding generic APIs, which can be mitigated by specifying the generateClientHelpers option. This will generate an extra "client" folder containing helpers that do the type fixing.
To use the generated client helpers, you'll need to call the one generated instead of the createTRPCNext API. This is done by specifying the path with the second type parameter of the createTRPCNext function.
Preparing Context
Preparing Context is a crucial step in setting up your tRPC Next.js app directory. You'll need to create a context that includes a Prisma field.
To do this, you'll need to use a PrismaClient instance, and it's a good idea to create one with enhance so that the client enforces access control policies. This will help you manage permissions and ensure that your app is secure.
You can use any PrismaClient instance for the context, but using one created with enhance is the recommended approach. This will give you the benefits of access control and other features that come with enhanced Prisma clients.
Client Helpers
TRPC relies on TypeScript's type inference to provide client-side API call signatures, but this has limitations regarding generic APIs.
One of the limitations is that typing adaptivity is lost when using tRPC, as seen in the example where the post variable is inferred to be of type Post & { author: User } but becomes a fixed Post type when wrapped with tRPC.
To mitigate this limitation, ZenStack's tRPC plugin generates a "type-fixing" helper that re-enables inference power from the client side when the generateClientHelpers option is specified.
This option can be set to "next" for Next.js, "react" for react-query, or "nuxt" for trpc-nuxt.
By using this option, the plugin generates an extra "client" folder containing helpers that do the type fixing.
To use the generated helpers, you need to call the createTRPCNext/createTRPCReact/createTRPCNuxtClient API instead of the original one.
If your generated trpc procedures are installed at a non-top-level path, you can specify the path with the second type parameter of the createTRPCNext, createTRPCReact, or createTRPCNuxtClient function.
Route Configuration
Route Configuration is a crucial aspect of building a trpc Next.js app directory. To manage routes efficiently, Next.js offers route groups.
Route groups allow you to organize routes in a logical and maintainable way. This is especially useful when dealing with complex applications.
You can learn more about route groups in the Next.js documentation.
Featured Images: pexels.com