Build a full tRPC v11 setup with procedures, middleware, subscriptions, and React Query integration. Full-stack TypeScript type safety.
## Task
tRPC v11 setup with router, procedures, middleware, and React client.
## Requirements
- tRPC v11 (latest)
- Server: Next.js App Router or standalone
- Client: React with @tanstack/react-query
- Auth: session-based middleware
## Router Definition
```typescript
// Server: define procedures with input validation and middleware
const appRouter = router({
user: router({
me: protectedProcedure.query(({ ctx }) => {
return ctx.db.user.findUnique({ where: { id: ctx.userId } });
}),
update: protectedProcedure
.input(z.object({ name: z.string().min(1), bio: z.string().max(500).optional() }))
.mutation(({ ctx, input }) => {
return ctx.db.user.update({ where: { id: ctx.userId }, data: input });
}),
}),
post: router({
list: publicProcedure
.input(z.object({ cursor: z.string().optional(), limit: z.number().min(1).max(50).default(20) }))
.query(({ input }) => { /* infinite scroll cursor pagination */ }),
create: protectedProcedure
.input(CreatePostSchema)
.mutation(({ ctx, input }) => { /* create + revalidate */ }),
onNew: publicProcedure.subscription(() => {
/* WebSocket subscription for real-time updates */
}),
}),
});
export type AppRouter = typeof appRouter;
```
## Client Usage
```typescript
// Fully typed — autocomplete from server to client
const { data } = trpc.user.me.useQuery();
const mutation = trpc.post.create.useMutation();
const { data: posts, fetchNextPage } = trpc.post.list.useInfiniteQuery(
{ limit: 20 },
{ getNextPageParam: (last) => last.nextCursor }
);
```
## Implementation Notes
1. Auth middleware: extract session → attach userId to context
2. Error formatting: map Zod errors to user-friendly messages
3. Rate limit middleware: per-procedure configurable
4. Batching: enable HTTP batching for multiple parallel queries
5. Subscriptions: use WebSocket adapter for real-time
6. Testing: use createCallerFactory for unit testing proceduresNo gallery images yet.