Productivity

trpc

mindrally/skills · updated Apr 8, 2026

$npx skills add https://github.com/mindrally/skills --skill trpc
summary

You are an expert in tRPC v11, TypeScript, and Next.js development. tRPC enables end-to-end typesafe APIs, allowing you to build and consume APIs without schemas, code generation, or runtime errors.

skill.md

tRPC Best Practices

You are an expert in tRPC v11, TypeScript, and Next.js development. tRPC enables end-to-end typesafe APIs, allowing you to build and consume APIs without schemas, code generation, or runtime errors.

Requirements

  • TypeScript >= 5.7.2
  • Strict TypeScript mode enabled

Project Structure

src/
  pages/
    _app.tsx              # createTRPCNext setup
    api/
      trpc/
        [trpc].ts         # tRPC HTTP handler
  server/
    routers/
      _app.ts             # Main router
      [feature].ts        # Feature-specific routers
    context.ts            # App context
    trpc.ts               # Procedure helpers
  utils/
    trpc.ts               # Typesafe React hooks

Server-Side Setup

Initialize tRPC Backend

Initialize tRPC backend once per application. Export reusable router and procedure helpers:

// server/trpc.ts
import { initTRPC } from '@trpc/server';
import superjson from 'superjson';

const t = initTRPC.context<Context>().create({
  transformer: superjson,
});

export const router = t.router;
export const publicProcedure = t.procedure;
export const protectedProcedure = t.procedure.use(isAuthed);
export const adminProcedure = t.procedure.use(isAdmin);

Create Feature Routers

Organize routers by feature/domain. Use Zod for input validation:

// server/routers/user.ts
import { z } from 'zod';
import { router, publicProcedure, protectedProcedure } from '../trpc';

export const userRouter = router({
  getById: publicProcedure
    .input(z.object({ id: z.string() }))
    .query(async ({ input, ctx }) => {
      return ctx.db.user.findUnique({ where: { id: input.id } });
    }),

  update: protectedProcedure
    .input(z.object({
      name: z.string().min(1),
      email: z.string().email(),
    }))
    .mutation(async ({ input, ctx }) => {
      return ctx.db.user.update({
        where: { id: ctx.user.id },
        data: input,
      });
    }),
});

Main App Router

// server/routers/_app.ts
import { router } from '../trpc';
import { userRouter } from './user';
import { postRouter } from './post';

export const appRouter = router({
  user: userRouter,
  post: postRouter,
});

export type AppRouter = typeof appRouter;

Client-Side Setup

Configure tRPC Client

// utils/trpc.ts
import { httpBatchLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
import superjson from 'superjson';
import type { AppRouter } from '../server/routers/_app';

function getBaseUrl() {
  if (typeof window !== 'undefined') return '';
  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
  return `http://localhost:${process.env.PORT ?? 3000}`;
}

export const trpc = createTRPCNext<AppRouter>({
  config() {
    return {
      transformer: superjson,
      links: [
        httpBatchLink({
          url: `${getBaseUrl()}/api/trpc`,
          maxURLLength: 2083,
        }),
      ],
    };
  },
  ssr: false,
});

Key Best Practices

1. Input Validation

Always use Zod for type safety and runtime validation on all procedure inputs:

.input(z.object({
  email: z.string().email(),
  age: z.number().min(0).max(120),
}))

2. Router Organization

Structure routers by feature/domain rather than one monolithic router. Each feature should have its own router file.

3. Middleware Implementation

Implement middleware for authentication, logging, and cross-cutting concerns:

const isAuthed = t.middleware(({ ctx, next }) => {
  if (!ctx.user) {
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }
  return next({ ctx: { user: ctx.user } });
});

4. Error Handling

Use TRPCError for consistent, informative error responses:

import { TRPCError } from '@trpc/server';

throw new TRPCError({
  code: 'NOT_FOUND',
  message: 'User not found',
});

5. Data Transformers

Apply SuperJSON for automatic serialization of dates, Maps, Sets, and other JavaScript types:

import superjson from 'superjson';

const t = initTRPC.create({
  transformer: superjson,
});

6. React Query Integration

Leverage tRPC's built-in React Query utilities for data fetching, mutations, and caching:

// Queries
const { data, isLoading } = trpc.user.getById.useQuery({ id: '123' });

// Mutations
const mutation = trpc.user.update.useMutation({
  onSuccess: () => {
    utils.user.getById.invalidate();
  },
});

// Prefetching
await utils.user.getById.prefetch({ id: '123' });

7. Context Creation

Share resources (database connections, user sessions) across procedures via context:

// server/context.ts
export async function createContext({ req, res }: CreateNextContextOptions) {
  const user = await getUser(req);
  return {
    db: prisma,
    user,
    req,
    res,
  };
}

export type Context = Awaited<ReturnType<typeof createContext>>;

8. Type Exports

Export only type signatures to client code, never router implementations:

// Only export the type
export type AppRouter = typeof appRouter;

// Never export the actual router to client code

9. Authorization Levels

Create distinct procedure types for different authorization levels:

export const publicProcedure = t.procedure;
export const protectedProcedure = t.procedure.use(isAuthed);
export const adminProcedure = t.procedure.use(isAuthed).use(isAdmin);

10. Performance Optimization

  • Enable request batching with httpBatchLink
  • Configure maxURLLength to prevent URL length issues
  • Implement prefetching for static/predictable data
  • Use React Query's caching strategies

Anti-Patterns to Avoid

  • Do not use any types - leverage tRPC's full type inference
  • Do not skip input validation
  • Do not expose internal errors to clients
  • Do not mix server and client code
  • Do not create overly large routers - split by feature
general reviews

Ratings

4.510 reviews
  • Shikha Mishra· Oct 10, 2024

    trpc is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.

  • Piyush G· Sep 9, 2024

    Keeps context tight: trpc is the kind of skill you can hand to a new teammate without a long onboarding doc.

  • Chaitanya Patil· Aug 8, 2024

    Registry listing for trpc matched our evaluation — installs cleanly and behaves as described in the markdown.

  • Sakshi Patil· Jul 7, 2024

    trpc reduced setup friction for our internal harness; good balance of opinion and flexibility.

  • Ganesh Mohane· Jun 6, 2024

    I recommend trpc for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.

  • Oshnikdeep· May 5, 2024

    Useful defaults in trpc — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.

  • Dhruvi Jain· Apr 4, 2024

    trpc has been reliable in day-to-day use. Documentation quality is above average for community skills.

  • Rahul Santra· Mar 3, 2024

    Solid pick for teams standardizing on skills: trpc is focused, and the summary matches what you get after install.

  • Pratham Ware· Feb 2, 2024

    We added trpc from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.

  • Yash Thakker· Jan 1, 2024

    trpc fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.