In this chapter we're gonna go ahead and set up the RPC in our project. After we've done that we are going to experiment using it with a client component, with a server component and then we're going to preview prefetching and how it works and how we are going to use it moving on. So first things, first ensure that you are on your default branch here, ensure that you have synchronized all changes, you shouldn't have any numbers in the source control here, everything should be up to date. And then you can also shut down your app simply because in the beginning all we're going to do is install a bunch of packages. So head to trpc.io or use the link in the description and let me show you how you can find the documentation that will tell us what we need to do in Next.js.
So you can click on the quick start which will take you to the documentation and in here you will have some options like back-end usage and client usage And in here you will notice that you have Next.js integration. That's because they still support explaining how to set it up with the pages router. This is not what we are looking for. What we need is one of these, either the 10-stack React query or React query. So I previously used this type of integration, But nowadays they have this complete new rewrite of how you use 10-stack query with TRPC.
And honestly, it makes so much more sense and it's actually simpler to use. And it's the recommended way of going forward. So this is what you have to find. Go inside of tRPC documentation, client usage, 10-stack React query, and not in the setup. If you want to, you can go in the setup, But you can see that you're missing some things like the server router, like where does this come from?
So that's why I recommend that you go inside of server components first. And in here, you will read how to set up the RPC with 10-Stack React Query using their new integration, using server components, which basically can be translated to Next.js app router. So basically they are doing a separation of server components and client components. That's why while the documentation might be a little bit confusing. In here, you can find everything you need for the Next.js integration.
So, let's go ahead and start with installing the dependencies. So, I'm just going to copy this entire thing here and paste it, but I will also show you the versions that I am using. So my TRPC server here is 11.1.2. My TRPC client, very importantly, will match that version And my TRPC 10-Stack React query will also match that version. Now, for 10-Stack React query, not TRPC 10-Stack React query, the actual 10-Stack React query, they use latest, but I will prefer using the exact version just for this tutorial's sake, right?
Obviously if you are developing this on your own it's completely fine to use the latest versions but for this tutorial I want to ensure longevity and the Zod version will be 3.25.7 client only and server only it doesn't really matter these versions don't change too much and I don't think anything will be breaking here but of course I will show you which versions I got installed So why am I adding versions for these things? And why am I adding versions for Zod? So the reason I'm adding versions for all of these is because you can see that if one of them is 11.1.2, the others need to be that version as well. The other reason is, you can see, for example, 10-stack React query has a warning. The package is currently in beta as we stabilize the API.
We might do breaking changes without respecting semver. So what does this sentence mean? It means that usually you would expect a breaking change in a major version change, but since they are in beta, the breaking change might come in 11.1.3, right? That's why I'm telling you that for this tutorial it might be safer and it might save you some headaches to simply use the same versions that I'm using. And I'm also pinning the TANstack React query version simply because I know that this version is compatible with this.
And why do I pin Zod version? Well, that's because Zod is also in some kind of transitioning phase where they are introducing version 4. So depending on when you watch this video, version 4 might become, you know, the default to use, but this is the current highest version that I have been able to find and we'll see how compatible it is with these other ones but this is the reason why I'm doing that because there's a lot of moving versions here a lot of beta things a lot of breaking changes and I just want to make it easier for you to follow along. And go ahead and add dash dash legacy peer deps. And wait for a second for this to install.
There we go. So no need to start anything immediately, we can just go back here. And let's create the TRPC router. So we're going to go inside of source, create a new folder, TRPC, and inside let's create init.ts. And go ahead and click on this view sample backend.
Now just a small note, in case this documentation changes and you can no longer find these code snippets, don't worry. So this is how I'm going to do it. I'm going to copy it, I'm going to paste it here, and I'm just going to slowly scroll so that you can see exactly what's inside. It's not a very big code snippet. In case the documentation no longer shows it, you will have no problem writing it yourself.
There we go. So just add this in the init file. Now what we have to do is we have to create our app router, which will handle all of our procedures and different routers, right? So we're doing that instead of TRPC routers underscore app dot ts. So instead of the TRPC folder, go ahead and create routers.
And inside create underscore app dot ts and paste this inside there we go and you can see that it can find dot dot in it which is this file right here perfect after you have added that let's go ahead and let's add to our app folder API tRPC dynamic tRPC route.ts so we can copy this and we will have to modify this snippet a bit because you can see they're using a different type of alias here. So let's go inside of app folder, API, let's create the trpc folder, then let's go ahead and create another folder, trpc inside of square brackets, and finally route.ts. So app, api, trpc, trpc in square brackets, route.ts. And paste this here. And we are now going to modify these two to not use this squiggly line, but instead the at sign because that is our default alias.
So this leads the import to source folder and then we can access the RPC from there. There we go. So I think that's all we need for the setup. So let's leave it like this for now. And Often when I go through this documentation, I forgot to do something, so I'm trying to be as careful as possible that that does not happen.
So in order to use the RPC both in client and in server components, we will need to have client factories and server factories to handle that right so let's go ahead and create a query client factory so I'm going to copy this and create query-client.ts so let's close this Let's go inside of trpc and query-client.ts and let's paste it here. And I will now slowly go over this. So in here we have the import, in here we have the super JSON import, which we can comment out because a we don't have the package installed and b we are not using it yet and after that we simply export a function make query client this is basically the 10 stack query setup that's it we will later enable the serialization I just want to finish following through with the setup great so that's the query client and now let's go ahead and see what else we have if you want to read more about it you can pause the screen or go to the documentation here Now let's go ahead and create a TRPC client for client components. So I'm going to copy this and I'm going to create inside of the TRPC folder client.tsx like this.
Let me close everything else client dot d s x and let's paste that inside of here. So in here, we mark it as use client, we do all of these imports right here. And then we add our make query client from this, which we've just added previously, right? MakeQueryClient. And we import the appRouterType from our routers here because this is where we are going to add all of our different routers.
So in here, it will have the appRouter to give the context and the type interference for all of them. So I'm just going over this slowly in case you cannot find that code snippet and want to type it yourself. So in here we define the function getQueryClient, which I suppose is doing it so it's compatible during server-side rendering here. Even though this is a client... Even though this is a provider for the client component usage, we still have to handle server side rendering.
That's different from a server component. So that's why it's doing this. And after that, we have this get URL, which I definitely want to modify. I think is a bit unnecessarily complicated and it's optimized for Vercel, but what if you're not deploying on Vercel, right? So how about we do this?
So find getUrl method, or if you're in the middle of typing it, go ahead and stop here. And instead, let's go to our .environment here and let's add next public app URL. And in here, we can copy the better out URL because it's exactly the same. It's basically where we have our app running. If you are unsure, you can do npm run dev and you will see exactly where it's running, like this.
And just add it here, be mindful of the protocol and of the port. So this will be much easier to do because you can see that the Vercel URL does not include the protocol, so then they have to attach it to the protocol. It's just a mess to work with. Instead, what we can just do is remove these two lines and just do return process.environment, next public app URL, please copy and paste so you don't accidentally misspell. That's it.
And what's important here is that you have actually defined the TRPC folder in the slash API slash TRPC. So be mindful of that API, TRPC, make sure you didn't misspell it. And Finally, we have the TRPC React provider, which combines the query client with the TRPC. We are later going to enable the SuperJSON transformer. And finally, it adds all the necessary providers using the 10-Stack Query and the TRPC.
And now we can wrap our application into that. Great, so I hope that kind of explained it. I will once again go through this slowly in case you're typing it out line by line. So now let's go ahead And let's mount the provider in the root of our application. So I'm going to go inside of layout right here.
So this root layout in the app folder. And I'm going to go ahead and import PRPC React provider. So be mindful here not to import the wrong thing. PRPC, I already forgot what it's called react provider from at PRPC client. The reason I'm telling you to be mindful is because autocomplete IntelliSense might pull you and you might import a similarly named provider, which is not what we want.
So now let's go ahead and simply wrap our entire app into that. Like that, And there we go. Now we can safely use trpc and 10 stack query throughout our application. Now we have to create an equivalent caller for server components because this is useless in server components but it will be quite handy for us to access our TRPC router in a server component. So again, I'm gonna copy this and create TRPC server.tsx.
So let's go inside of here. Server.tsx like this and let's paste it here. So now what we're going to do is first ensure that you have server only and I just remembered that I forgot to show you so client only 0.0.1 server only 0.0.1 those are my versions. Great and in here you should have no problems with this relative imports because it's all in the same folder. So we have the init, we have the query client, and we have the routers app.
And you can remove this part. So this is if the router is in a separate server, that's not the case for us. So we can remove that. And this is the cool thing. So usually, if you were attempt to, you know, fetch your data in a server component using some kind of abstraction like HONO RPC, what it would do is it would actually do a fetch request on your server, which is unnecessary overhead.
But that isn't the biggest issue. It's not slowing anything down too much. The issue is, if you're doing a fetch request in a server component, you're losing authentication there. You need to fill that fetch request with cookies and headers. Well, this kind of server module for TRPC will allow us to natively call TRPC procedures in server components, preserving the auth state.
That's why this is so good. So there is no fetch request happening here. It will directly call the TRPC procedures. You will see more of this in action later on. Great!
So in here, they immediately show you the prefetching example, which I think is a bit complicated if you've never seen this before but basically prefetching allows us to combine the best of both worlds. When Next.js page loads the first thing it loads is a server component And in here we have the option to prefetch a query. For example, we just loaded a meeting with meeting ID 1, 2, 3. So what we're going to do in the server component is we're going to start the prefetch. We're going to say, okay, start prefetching this immediately.
And then we're going to wrap this into the hydration boundary. And then in the client component, we're going to use the client ERPC integration. And in here, we will be able to load a already loaded data, right? Because the server component will already put the data into cache. So our client component will be ready to immediately use it, right?
And we are also gonna be able to use useSuspenseQuery with that. And then we are going to have an even better developer experience for us. I know it's all a bit too much overwhelming at the moment, but you're going to see when we start doing this how helpful it really is. But how about we go ahead and actually try a very simple example. So what I'm trying to do here is the following.
Let's go inside of our TRPC routers. And in here we can see hello base procedure. So a pretty simple procedure. How about we go inside of our modules home, home view, because this is a client component. Make sure you have your app running here.
And this is what we're gonna do now. So we no longer need to display anything auth related, we have that in the sidebar now. But what we can do is the following. We can learn how to use trpc here. So let's first add trpc hook.
So const trpc is use trpc from trpc client. And then in here we would have the data which would be use query from tanstack query and then in here usually what you would do is you would create your fetcher and then pass the body what they have done is they have separated the API from TRPC and useQuery. So you useQuery and you learn useQuery independently, right? You're not learning TRPC, you're learning TanStackQuery. That's the cool thing about this new integration they've done.
Usually what you would do is trpc.yourProcedure.useQuery. But that would require you to learn this whole new syntax, whereas with this one, you already know useQuery most likely, right? So all you have to do is pass hello and query options inside. And let's pass in, is it name? Let's just see.
Hello, text, okay. Let's pass in text to be Antonio. And then in here, simply render data.greeting with a question mark here. So now when you go to localhost 3000 and refresh this, this should no longer exist and instead it should say hello Antonio. There we go, hello Antonio.
So it loaded for a second and then it said hello Antonio. So that's how you would use it in a client component. Quite normal, nothing too unusual, right? But we can also use it in a server component if we need to. So let's just do that before we wrap up the chapter.
So getting data in a server component, you would almost never, you will almost never need this, right? But if you really, really need data in a server component, you can, right? So what we're going to do is let's just go inside of app folder, dashboard page. And what I'm going to do here is I'm going to fetch the greeting the same way. So const greeting will be a wait.
And let's see what do we need to import? A caller function. And I'm not even sure if I have it. Yes, they are telling me that I need to export it. Because we will never use this, but just to demonstrate to you that you can still do it.
Let's go inside of the TRPC server. If it's easy enough to do, we will do it. If it's complicated, We will just skip. Let's see. OK, all I need is the caller.
Expert const caller, app router, create caller, and pass in this. Perfect. Let's import the caller from trpc server. So caller, hello, text, Antonio, server. And then in here, we are just going to return a paragraph, greeting, dot greeting.
So this would technically be data and then data dot greeting. So now I'm overriding that client component and you can see hello, I'm the only new server. So I just wanted to demonstrate to you that it's possible to do this as well. But we won't be doing that. We'll be doing the third option, which is the prefetching, leveraging both the speed of server components and the knowledge and the, I'm not sure what's the correct term to use, the familiarity of the client components, right?
Because we are used to this, we know how to work with this, right? But it would be nice to leverage the speed of the server components, which load sooner than the client components. So you're going to see us combine all of that in one. Great, but we just tested both so we know that both the client and the server iteration of these are working in. We're going to learn more about the RPC as we go forward.
So we've done this, this, this, and this. And I forgot to do one more step, which is to merge the pull requests. So let's go ahead and do that. So I have 11 uncommitted changes here. Let's go ahead and change the branch first.
New branch. This will be 08-drpc-setup. Great. Let's confirm I'm on the new branch and let's click the plus icon to stage all of our changes here and let's do 08-prpc-setup and let's commit and let's publish the branch. There we go.
And let's go ahead and open a pull request to see what CodeRabbit has to say about this, though I won't change it much simply because this is the official documentation, so I'm just gonna follow how they've done it, but still let's see what AI has to say about this. And here we have the summary. So let's read through the walkthrough this time. This update integrates TRPC and React Query into the project, introducing new API routes, server and client utilities, and a context provider for the app. Authentication logic is removed from the home view, because we removed it, right?
And which now displays data fetched via TRPC. Several supporting modules and dependencies are added or updated to enable seamless type-safe API calls. And that was pretty much the point of this chapter. And this is where you will finally see these sequence diagrams become increasingly more useful, especially if you're struggling to understand all of these types of TRPC calls, right? Server, TRPC client, TRPC hybrid with prefetching.
So this will come in quite handy in here, for example, you can see a very, very simple one, which is a use TRPC with use query for the hello procedure, where we pass the text, and then we bring back from the app router the greeting with that text included and then render it back. In here we have some comments but these are just demonstrations, right? We will obviously remove this so it's making sure that we are careful with this query that we have the error and the loading field but we are going to remove it anyway and we will handle error and loading but in a different way using suspense we are also going to implement proper protected procedures later on You can see how it already suggested that right here. Perfect. And in here, of course, it recommends a fallback, but we don't really need a fallback.
You know, if you don't add this environment variable, the app will not work either way because we will use it for some other things later on. And finally, the caller here, which again, does not matter, because we only added it to demonstrate how you can use tRPC for purely server component call. But still, you can see how for seemingly harmless pull request, it noticed so many things that could go wrong. Luckily for us, most of this is just for demonstration, but definitely a useful tool to have. Let's go ahead and merge this pull request.
And after it's merged, go back to your IDE, select the main branch, and go ahead and synchronize the changes. To double check, you can click on the source control here, open the graph, and just confirm that you have emerged the TRPC setup. Perfect! Amazing, amazing job and see you in the next chapter.