---
name: trpc-api-builder
description: "End-to-end typesafe APIs — routers, procedures, middleware, transformers, React Query integration. Builds tRPC v11 APIs: router composition, public vs protected procedures, context creation, middleware (auth, rate-limit, logging), input/output schemas with Zod, transformers (superjson), and the seamless React Query / Next.js App Router integration."
license: MIT
---

# tRPC API Builder

Scaffold and extend end-to-end typesafe APIs with tRPC v11, where your client infers types straight from server procedures—no codegen, no OpenAPI schema drift. This skill is for fullstack TypeScript developers building on Next.js (App Router), Remix, or a standalone server who want correct router composition, context, middleware, and React Query wiring without hand-assembling boilerplate.

## When to use it

- Starting a new tRPC backend and you need the `initTRPC` setup, context factory, and root router laid out correctly.
- Adding a feature router (e.g. `postRouter`, `userRouter`) and merging it into `appRouter`.
- Splitting `publicProcedure` from `protectedProcedure` and enforcing auth via middleware.
- Adding cross-cutting middleware: auth guards, rate limiting, request logging, timing.
- Wiring the client side—`createTRPCReact`, the App Router server/client component split, and superjson so `Date`, `Map`, and `BigInt` survive serialization.

## How it works

The skill generates against real tRPC v11 APIs. Initialization uses `initTRPC.context<Context>().create({ transformer: superjson })`, exposing `router`, `procedure`, `middleware`, and `mergeRouters`. Procedures chain `.input(zodSchema)`, optional `.output(...)`, and `.query()` / `.mutation()` / `.subscription()`. Auth is a `t.middleware` that reads `ctx`, throws `TRPCError({ code: 'UNAUTHORIZED' })` when missing, and returns `next({ ctx: { user } })` to narrow context types downstream. Context comes from `createTRPCContext({ req, res })`. On the client it sets up `httpBatchLink` (or `httpLink`), the `<Provider>` with a shared `QueryClient`, and—for Next.js App Router—a server caller via `appRouter.createCaller(ctx)` plus the `@trpc/react-query` hooks for client components.

## Example

```ts
// server/trpc.ts
import { initTRPC, TRPCError } from '@trpc/server';
import superjson from 'superjson';
import type { Context } from './context';

const t = initTRPC.context<Context>().create({ transformer: superjson });
export const router = t.router;
export const publicProcedure = t.procedure;

const isAuthed = t.middleware(({ ctx, next }) => {
  if (!ctx.session?.user) throw new TRPCError({ code: 'UNAUTHORIZED' });
  return next({ ctx: { user: ctx.session.user } });
});
export const protectedProcedure = t.procedure.use(isAuthed);
```

## Tips & gotchas

- The transformer must match on both ends. If the client `createTRPCClient` omits superjson while the server sets it, payloads silently mis-deserialize.
- `httpBatchLink` collapses concurrent calls into one request; if a procedure needs streamed or unbatched delivery, use `httpLink` or `unstable_httpBatchStreamLink`.
- `.output()` strips unknown keys—great for not leaking fields, but it will silently drop data you forgot to include in the schema.
- In the App Router, never import server-only routers into client components; use the generated hooks or a server-side caller instead.

## FAQ

**Does this require code generation?** No. Types flow through TypeScript inference, so there's no build step or generated client to keep in sync.

**v10 or v11?** It targets v11 (the merged `@trpc/server` API and updated React Query integration). Migrating a v10 project? It can adapt the patterns, but verify your link imports.

**Can I expose tRPC procedures as REST?** Not natively—pair it with `trpc-openapi` if you need a public REST/OpenAPI surface alongside the typed client.
