DEV Community

Cover image for Stop manually setting up tRPC in Next.js — use this CLI instead
Dhavalkurkutiya
Dhavalkurkutiya

Posted on

Stop manually setting up tRPC in Next.js — use this CLI instead

Every time I start a new Next.js project with tRPC, I do the same thing.

Open docs. Copy files. Install packages. Forget to wrap layout.tsx. Get the QueryClient error. Fix it. Repeat next project.

I got tired of it. So I built a CLI.

npx create-trpc-setup
Enter fullscreen mode Exit fullscreen mode

The Problem

Setting up tRPC v11 with Next.js App Router is not hard — but it's tedious. You need:

  1. Install @trpc/server, @trpc/client, @trpc/tanstack-react-query, @tanstack/react-query, zod, server-only...
  2. Create trpc/init.ts with context and procedures
  3. Create trpc/query-client.ts with SSR-safe QueryClient
  4. Create trpc/client.tsx with TRPCReactProvider
  5. Create trpc/server.tsx with HydrateClient and prefetch
  6. Create app/api/trpc/[trpc]/route.ts
  7. Update layout.tsx to wrap children with TRPCReactProvider

Miss any step → error. Every new project.

The Solution

npx create-trpc-setup
Enter fullscreen mode Exit fullscreen mode

Run this inside any existing Next.js project. Everything happens automatically.

What gets detected automatically:

  • Package manager — npm, pnpm, yarn, or bun
  • Path alias — reads tsconfig.json for @/*, ~/*, or any custom alias
  • Auth provider — detects Clerk or NextAuth and configures context
  • Folder structuresrc/ or root layout

What gets generated:

trpc/
├── init.ts         ← context, baseProcedure, protectedProcedure, Zod error formatter
├── query-client.ts ← SSR-safe QueryClient
├── client.tsx      ← TRPCReactProvider + useTRPC hook
├── server.tsx      ← prefetch, HydrateClient, caller
└── routers/
    └── _app.ts     ← health + greet procedures with Zod

app/api/trpc/[trpc]/route.ts   ← API handler with real headers
app/trpc-status/               ← test page (delete after confirming)
Enter fullscreen mode Exit fullscreen mode

layout.tsx — auto-patched:

Before:

<body>
  {children}
  <Toaster />
</body>
Enter fullscreen mode Exit fullscreen mode

After:

<body>
  <TRPCReactProvider>
    {children}
    <Toaster />
  </TRPCReactProvider>
</body>
Enter fullscreen mode Exit fullscreen mode

Using tRPC After Setup

Server Component — prefetch data:

// app/page.tsx
import { HydrateClient, prefetch, trpc } from "@/trpc/server";
import { MyClient } from "./my-client";

export default function Page() {
  prefetch(trpc.greet.queryOptions({ name: "World" }));
  return (
    <HydrateClient>
      <MyClient />
    </HydrateClient>
  );
}
Enter fullscreen mode Exit fullscreen mode

Client Component — use data:

// my-client.tsx
"use client";
import { useSuspenseQuery } from "@tanstack/react-query";
import { useTRPC } from "@/trpc/client";

export function MyClient() {
  const trpc = useTRPC();
  const { data } = useSuspenseQuery(trpc.greet.queryOptions({ name: "World" }));
  return <div>{data.message}</div>;
}
Enter fullscreen mode Exit fullscreen mode

Why Not create-t3-app?

create-t3-app is great — but it only works for new projects.

create-trpc-setup works with existing projects. Already have a Next.js app with Clerk, Shadcn, and custom providers? No problem. Run the command, everything gets added without touching your existing code.

protectedProcedure — Already Included

The generated init.ts includes a protectedProcedure that automatically throws UNAUTHORIZED:

export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
  if (!ctx.userId) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  return next({ ctx: { ...ctx, userId: ctx.userId } });
});
Enter fullscreen mode Exit fullscreen mode

Use it in any router:

getProfile: protectedProcedure.query(({ ctx }) => {
  return { userId: ctx.userId }; // guaranteed non-null
}),
Enter fullscreen mode Exit fullscreen mode

Try It

npx create-trpc-setup
Enter fullscreen mode Exit fullscreen mode

If it saved you time, drop a ⭐ on GitHub and share it with your team.

Top comments (0)