{"id":"abbec752-9eee-4cc1-93fb-26340af72697","shortId":"nLJtVj","kind":"skill","title":"trpc-fullstack","tagline":"Build end-to-end type-safe APIs with tRPC — routers, procedures, middleware, subscriptions, and Next.js/React integration patterns.","description":"# tRPC Full-Stack\n\n## Overview\n\ntRPC lets you build fully type-safe APIs without writing a schema or code-generation step. Your TypeScript types flow from the server router directly to the client — so every API call is autocompleted, validated at compile time, and refactoring-safe. Use this skill when building TypeScript monorepos, Next.js apps, or any project where the server and client share a codebase.\n\n## When to Use This Skill\n\n- Use when building a TypeScript full-stack app (Next.js, Remix, Express + React) where the client and server share a single repo\n- Use when you want end-to-end type safety on API calls without REST/GraphQL schema overhead\n- Use when adding real-time features (subscriptions) to an existing tRPC setup\n- Use when designing multi-step middleware (auth, rate limiting, tenant scoping) on tRPC procedures\n- Use when migrating an existing REST/GraphQL API to tRPC incrementally\n\n## Core Concepts\n\n### Routers and Procedures\n\nA **router** groups related **procedures** (think: endpoints). Procedures are typed functions — `query` for reads, `mutation` for writes, `subscription` for real-time streams.\n\n### Input Validation with Zod\n\nAll procedure inputs are validated with Zod schemas. The validated, typed input is available in the procedure handler — no manual parsing.\n\n### Context\n\n`context` is shared state passed to every procedure — auth session, database client, request headers, etc. It is built once per request in a context factory. **Important:** Next.js App Router and Pages Router require separate context factories because App Router handlers receive a fetch `Request`, not a Node.js `NextApiRequest`.\n\n### Middleware\n\nMiddleware chains run before a procedure. Use them for authentication, logging, and request enrichment. They can extend the context for downstream procedures.\n\n---\n\n## How It Works\n\n### Step 1: Install and Initialize\n\n```bash\nnpm install @trpc/server @trpc/client @trpc/react-query @tanstack/react-query zod\n```\n\nCreate the tRPC instance and reusable builders:\n\n```typescript\n// src/server/trpc.ts\nimport { initTRPC, TRPCError } from '@trpc/server';\nimport { type Context } from './context';\nimport { ZodError } from 'zod';\n\nconst t = initTRPC.context<Context>().create({\n  errorFormatter({ shape, error }) {\n    return {\n      ...shape,\n      data: {\n        ...shape.data,\n        zodError:\n          error.cause instanceof ZodError ? error.cause.flatten() : null,\n      },\n    };\n  },\n});\n\nexport const router = t.router;\nexport const publicProcedure = t.procedure;\nexport const middleware = t.middleware;\n```\n\n### Step 2: Define Two Context Factories\n\nNext.js App Router handlers receive a fetch `Request` (not a Node.js `NextApiRequest`), so the context\nmust be built differently depending on the call site. Define one factory per surface:\n\n```typescript\n// src/server/context.ts\nimport { type FetchCreateContextFnOptions } from '@trpc/server/adapters/fetch';\nimport { auth } from '@/server/auth'; // Next-Auth v5 / your auth helper\nimport { db } from './db';\n\n/**\n * Context for the HTTP handler (App Router Route Handler).\n * `opts.req` is the fetch Request — auth is resolved server-side via `auth()`.\n */\nexport async function createTRPCContext(opts: FetchCreateContextFnOptions) {\n  const session = await auth(); // server-side auth — no req/res needed\n  return { session, db, headers: opts.req.headers };\n}\n\n/**\n * Context for direct server-side callers (Server Components, RSC, cron jobs).\n * No HTTP request is involved, so we call auth() directly from the server.\n */\nexport async function createServerContext() {\n  const session = await auth();\n  return { session, db };\n}\n\nexport type Context = Awaited<ReturnType<typeof createTRPCContext>>;\n```\n\n### Step 3: Build an Auth Middleware and Protected Procedure\n\n```typescript\n// src/server/trpc.ts (continued)\nconst enforceAuth = middleware(({ ctx, next }) => {\n  if (!ctx.session?.user) {\n    throw new TRPCError({ code: 'UNAUTHORIZED' });\n  }\n  return next({\n    ctx: {\n      // Narrows type: session is non-null from here\n      session: { ...ctx.session, user: ctx.session.user },\n    },\n  });\n});\n\nexport const protectedProcedure = t.procedure.use(enforceAuth);\n```\n\n### Step 4: Create Routers\n\n```typescript\n// src/server/routers/post.ts\nimport { z } from 'zod';\nimport { router, publicProcedure, protectedProcedure } from '../trpc';\nimport { TRPCError } from '@trpc/server';\n\nexport const postRouter = router({\n  list: publicProcedure\n    .input(\n      z.object({\n        limit: z.number().min(1).max(100).default(20),\n        cursor: z.string().optional(),\n      })\n    )\n    .query(async ({ ctx, input }) => {\n      const posts = await ctx.db.post.findMany({\n        take: input.limit + 1,\n        cursor: input.cursor ? { id: input.cursor } : undefined,\n        orderBy: { createdAt: 'desc' },\n      });\n      const nextCursor =\n        posts.length > input.limit ? posts.pop()!.id : undefined;\n      return { posts, nextCursor };\n    }),\n\n  byId: publicProcedure\n    .input(z.object({ id: z.string() }))\n    .query(async ({ ctx, input }) => {\n      const post = await ctx.db.post.findUnique({ where: { id: input.id } });\n      if (!post) throw new TRPCError({ code: 'NOT_FOUND' });\n      return post;\n    }),\n\n  create: protectedProcedure\n    .input(\n      z.object({\n        title: z.string().min(1).max(200),\n        body: z.string().min(1),\n      })\n    )\n    .mutation(async ({ ctx, input }) => {\n      return ctx.db.post.create({\n        data: { ...input, authorId: ctx.session.user.id },\n      });\n    }),\n\n  delete: protectedProcedure\n    .input(z.object({ id: z.string() }))\n    .mutation(async ({ ctx, input }) => {\n      const post = await ctx.db.post.findUnique({ where: { id: input.id } });\n      if (!post) throw new TRPCError({ code: 'NOT_FOUND' });\n      if (post.authorId !== ctx.session.user.id)\n        throw new TRPCError({ code: 'FORBIDDEN' });\n      return ctx.db.post.delete({ where: { id: input.id } });\n    }),\n});\n```\n\n### Step 5: Compose the Root Router and Export Types\n\n```typescript\n// src/server/root.ts\nimport { router } from './trpc';\nimport { postRouter } from './routers/post';\nimport { userRouter } from './routers/user';\n\nexport const appRouter = router({\n  post: postRouter,\n  user: userRouter,\n});\n\n// Export the type for the client — never import the appRouter itself on the client\nexport type AppRouter = typeof appRouter;\n```\n\n### Step 6: Mount the API Handler (Next.js App Router)\n\nThe App Router handler must use `fetchRequestHandler` and the **fetch-based** context factory.\n`createTRPCContext` receives `FetchCreateContextFnOptions` (with a fetch `Request`), not\na Pages Router `req/res` pair.\n\n```typescript\n// src/app/api/trpc/[trpc]/route.ts\nimport { fetchRequestHandler } from '@trpc/server/adapters/fetch';\nimport { type FetchCreateContextFnOptions } from '@trpc/server/adapters/fetch';\nimport { appRouter } from '@/server/root';\nimport { createTRPCContext } from '@/server/context';\n\nconst handler = (req: Request) =>\n  fetchRequestHandler({\n    endpoint: '/api/trpc',\n    req,\n    router: appRouter,\n    // opts is FetchCreateContextFnOptions — req is the fetch Request\n    createContext: (opts: FetchCreateContextFnOptions) => createTRPCContext(opts),\n  });\n\nexport { handler as GET, handler as POST };\n```\n\n### Step 7: Set Up the Client (React Query)\n\n```typescript\n// src/utils/trpc.ts\nimport { createTRPCReact } from '@trpc/react-query';\nimport type { AppRouter } from '@/server/root';\n\nexport const trpc = createTRPCReact<AppRouter>();\n```\n\n```typescript\n// src/app/providers.tsx\n'use client';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { httpBatchLink } from '@trpc/client';\nimport { useState } from 'react';\nimport { trpc } from '@/utils/trpc';\n\nexport function TRPCProvider({ children }: { children: React.ReactNode }) {\n  const [queryClient] = useState(() => new QueryClient());\n  const [trpcClient] = useState(() =>\n    trpc.createClient({\n      links: [\n        httpBatchLink({\n          url: '/api/trpc',\n          headers: () => ({ 'x-trpc-source': 'react' }),\n        }),\n      ],\n    })\n  );\n\n  return (\n    <trpc.Provider client={trpcClient} queryClient={queryClient}>\n      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n    </trpc.Provider>\n  );\n}\n```\n\n---\n\n## Examples\n\n### Example 1: Fetching Data in a Component\n\n```typescript\n// components/PostList.tsx\n'use client';\nimport { trpc } from '@/utils/trpc';\n\nexport function PostList() {\n  const { data, isLoading, error } = trpc.post.list.useQuery({ limit: 10 });\n\n  if (isLoading) return <p>Loading…</p>;\n  if (error) return <p>Error: {error.message}</p>;\n\n  return (\n    <ul>\n      {data?.posts.map((post) => (\n        <li key={post.id}>{post.title}</li>\n      ))}\n    </ul>\n  );\n}\n```\n\n### Example 2: Mutation with Cache Invalidation\n\n```typescript\n'use client';\nimport { trpc } from '@/utils/trpc';\n\nexport function CreatePost() {\n  const utils = trpc.useUtils();\n\n  const createPost = trpc.post.create.useMutation({\n    onSuccess: () => {\n      // Invalidate and refetch the post list\n      utils.post.list.invalidate();\n    },\n  });\n\n  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    const form = e.currentTarget;\n    const data = new FormData(form);\n    createPost.mutate({\n      title: data.get('title') as string,\n      body: data.get('body') as string,\n    });\n    form.reset();\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input name=\"title\" placeholder=\"Title\" required />\n      <textarea name=\"body\" placeholder=\"Body\" required />\n      <button type=\"submit\" disabled={createPost.isPending}>\n        {createPost.isPending ? 'Creating…' : 'Create Post'}\n      </button>\n      {createPost.error && <p>{createPost.error.message}</p>}\n    </form>\n  );\n}\n```\n\n### Example 3: Server-Side Caller (Server Components / SSR)\n\nUse `createServerContext` — the dedicated server-side factory — so that `auth()` is called\ncorrectly without needing a synthetic or empty request object:\n\n```typescript\n// app/posts/page.tsx (Next.js Server Component)\nimport { appRouter } from '@/server/root';\nimport { createCallerFactory } from '@trpc/server';\nimport { createServerContext } from '@/server/context';\n\nconst createCaller = createCallerFactory(appRouter);\n\nexport default async function PostsPage() {\n  // Uses createServerContext — calls auth() server-side, no req/res cast needed\n  const caller = createCaller(await createServerContext());\n  const { posts } = await caller.post.list({ limit: 20 });\n\n  return (\n    <ul>\n      {posts.map((post) => (\n        <li key={post.id}>{post.title}</li>\n      ))}\n    </ul>\n  );\n}\n```\n\n### Example 4: Real-Time Subscriptions (WebSocket)\n\n```typescript\n// server/routers/notifications.ts\nimport { observable } from '@trpc/server/observable';\nimport { EventEmitter } from 'events';\n\nconst ee = new EventEmitter();\n\nexport const notificationRouter = router({\n  onNew: protectedProcedure.subscription(({ ctx }) => {\n    return observable<{ message: string; at: Date }>((emit) => {\n      const onNotification = (data: { message: string }) => {\n        emit.next({ message: data.message, at: new Date() });\n      };\n\n      const channel = `user:${ctx.session.user.id}`;\n      ee.on(channel, onNotification);\n      return () => ee.off(channel, onNotification);\n    });\n  }),\n});\n```\n\n```typescript\n// Client usage — requires wsLink in the client config\ntrpc.notification.onNew.useSubscription(undefined, {\n  onData(data) {\n    toast(data.message);\n  },\n});\n```\n\n---\n\n## Best Practices\n\n- ✅ **Export only `AppRouter` type** from server code — never import `appRouter` on the client\n- ✅ **Use separate context factories** — `createTRPCContext` for the HTTP handler, `createServerContext` for Server Components and callers\n- ✅ **Validate all inputs with Zod** — never trust raw `input` without a schema\n- ✅ **Split routers by domain** (posts, users, billing) and merge in `root.ts`\n- ✅ **Extend context in middleware** rather than querying the DB multiple times per request\n- ✅ **Use `utils.invalidate()`** after mutations to keep the cache fresh\n- ❌ **Don't cast context with `as any`** to silence type errors — the mismatch will surface as a runtime failure when auth or session lookups return undefined\n- ❌ **Don't use `createContext({} as any)`** in Server Components — use `createServerContext()` which calls `auth()` directly\n- ❌ **Don't put business logic in the route handler** — keep it in the procedure or a service layer\n- ❌ **Don't share the tRPC client instance globally** — create it per-provider to avoid stale closures\n\n---\n\n## Security & Safety Notes\n\n- Always enforce authorization in `protectedProcedure` — never rely on client-side checks alone\n- Validate all input shapes with Zod, including pagination cursors and IDs, to prevent injection via malformed inputs\n- Avoid exposing internal error details to clients — use `TRPCError` with a public-safe `message` and keep stack traces server-side only\n- Rate-limit public procedures using middleware to prevent abuse\n\n---\n\n## Common Pitfalls\n\n- **Problem:** Auth session is `null` in protected procedures even when the user is logged in\n  **Solution:** Ensure `createTRPCContext` uses the correct server-side auth call (e.g. `auth()` from Next-Auth v5) and is not receiving a Pages Router `req/res` cast via `as any` in an App Router handler\n\n- **Problem:** Server Component caller fails for auth-dependent queries\n  **Solution:** Use `createServerContext()` (the dedicated server-side factory) instead of passing an empty or synthetic object to `createContext`\n\n- **Problem:** \"Type error: AppRouter is not assignable to AnyRouter\"\n  **Solution:** Import `AppRouter` as a `type` import (`import type { AppRouter }`) on the client, not the full module\n\n- **Problem:** Mutations not reflecting in the UI after success\n  **Solution:** Call `utils.<router>.<procedure>.invalidate()` in `onSuccess` to trigger a refetch via React Query\n\n- **Problem:** \"Cannot find module '@trpc/server/adapters/next'\" with App Router\n  **Solution:** Use `@trpc/server/adapters/fetch` and `fetchRequestHandler` for the App Router; the `nextjs` adapter is for Pages Router only\n\n- **Problem:** Subscriptions not connecting\n  **Solution:** Subscriptions require `splitLink` — route subscriptions to `wsLink` and queries/mutations to `httpBatchLink`\n\n---\n\n## Related Skills\n\n- `@typescript-expert` — Deep TypeScript patterns used inside tRPC routers and generic utilities\n- `@react-patterns` — React hooks patterns that pair with `trpc.*.useQuery` and `useMutation`\n- `@test-driven-development` — Write procedure unit tests using `createCallerFactory` without an HTTP server\n- `@security-auditor` — Review tRPC middleware chains for auth bypass and input validation gaps\n\n## Additional Resources\n\n- [tRPC Official Docs](https://trpc.io/docs)\n- [create-t3-app](https://create.t3.gg) — Production Next.js starter with tRPC wired in\n- [tRPC GitHub](https://github.com/trpc/trpc)\n- [TanStack Query Docs](https://tanstack.com/query/latest)\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.","tags":["trpc","fullstack","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows"],"capabilities":["skill","source-sickn33","skill-trpc-fullstack","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/trpc-fullstack","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34460 github stars · SKILL.md body (15,409 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T06:52:03.242Z","embedding":null,"createdAt":"2026-04-18T21:46:32.981Z","updatedAt":"2026-04-22T06:52:03.242Z","lastSeenAt":"2026-04-22T06:52:03.242Z","tsv":"'/api/trpc':827,913 '/context':335 '/db':425 '/docs)':1651 '/query/latest)':1674 '/react':22 '/route.ts':803 '/routers/post':732 '/routers/user':736 '/server/auth':414 '/server/context':820,1090 '/server/root':816,869,1082 '/trpc':572,728 '/trpc/trpc)':1668 '/utils/trpc':894,945,985 '1':305,588,606,659,665,932 '10':955 '100':590 '2':370,974 '20':592,1121 '200':661 '3':512,1044 '4':558,1130 '5':715 '6':765 '7':852 'abus':1417 'ad':140 'adapt':1566 'addit':1644 'alon':1367 'alway':1355 'anyrout':1507 'api':12,38,62,132,172,768 'app':82,107,257,267,376,431,771,774,1467,1553,1562,1655 'app/posts/page.tsx':1075 'approut':739,754,761,763,814,830,867,1080,1094,1205,1212,1502,1510,1517 'ask':1708 'assign':1505 'async':449,496,597,632,667,683,1097 'auditor':1632 'auth':158,238,412,417,420,440,447,457,461,490,502,515,1062,1103,1296,1315,1421,1444,1447,1451,1477,1638 'auth-depend':1476 'authent':288 'author':1357 'authorid':674 'autocomplet':65 'avail':221 'avoid':1349,1385 'await':456,501,509,602,637,688,1114,1118 'base':784 'bash':309 'best':1201 'bill':1249 'bodi':662,1022,1024 'boundari':1716 'build':4,33,78,101,513 'builder':323 'built':247,392 'busi':1320 'button':1032 'byid':625 'bypass':1639 'cach':977,1274 'call':63,133,397,489,1064,1102,1314,1445,1535 'caller':476,1048,1112,1230,1473 'caller.post.list':1119 'cannot':1548 'cast':1109,1278,1461 'chain':280,1636 'channel':1176,1180,1184 'check':1366 'children':898,899,929 'clarif':1710 'clear':1683 'client':59,90,114,241,750,758,856,877,922,927,941,981,1187,1193,1215,1340,1364,1391,1520 'client-sid':1363 'closur':1351 'code':45,534,647,698,707,1209 'code-gener':44 'codebas':93 'common':1418 'compil':68 'compon':478,937,1050,1078,1228,1310,1472 'components/postlist.tsx':939 'compos':716 'concept':177 'config':1194 'connect':1575 'const':340,358,362,366,454,499,523,553,578,600,615,635,686,738,821,871,901,906,949,989,992,1003,1008,1011,1091,1111,1116,1146,1151,1164,1175 'context':229,230,253,264,297,333,373,389,426,470,508,785,1218,1255,1279 'continu':522 'core':176 'correct':1065,1440 'creat':317,343,559,652,1038,1039,1343,1653 'create-t3-app':1652 'create.t3.gg':1656 'createcal':1092,1113 'createcallerfactori':1084,1093,1625 'createcontext':839,1305,1498 'createdat':613 'createpost':988,993 'createpost.error':1041 'createpost.error.message':1042 'createpost.ispending':1036,1037 'createpost.mutate':1016 'createservercontext':498,1053,1088,1101,1115,1225,1312,1482 'createtrpccontext':451,787,818,842,1220,1437 'createtrpcreact':862,873 'criteria':1719 'cron':480 'ctx':526,538,598,633,668,684,1156 'ctx.db.post.create':671 'ctx.db.post.delete':710 'ctx.db.post.findmany':603 'ctx.db.post.findunique':638,689 'ctx.session':529,549 'ctx.session.user':551 'ctx.session.user.id':675,703,1178 'cursor':593,607,1376 'data':349,672,934,950,966,1012,1166,1198 'data.get':1018,1023 'data.message':1171,1200 'databas':240 'date':1162,1174 'db':423,467,505,1262 'dedic':1055,1484 'deep':1593 'default':591,1096 'defin':371,399 'delet':676 'depend':394,1478 'desc':614 'describ':1687 'design':153 'detail':1389 'develop':1619 'differ':393 'direct':56,472,491,1316 'disabl':1035 'doc':1648,1671 'domain':1246 'downstream':299 'driven':1618 'e':1005 'e.currenttarget':1010 'e.g':1446 'e.preventdefault':1007 'ee':1147 'ee.off':1183 'ee.on':1179 'emit':1163 'emit.next':1169 'empti':1071,1493 'end':6,8,126,128 'end-to-end':5,125 'endpoint':187,826 'enforc':1356 'enforceauth':524,556 'enrich':292 'ensur':1436 'environ':1699 'environment-specif':1698 'error':346,952,961,963,1286,1388,1501 'error.cause':352 'error.cause.flatten':355 'error.message':964 'errorformatt':344 'etc':244 'even':1428 'event':1145 'eventemitt':1143,1149 'everi':61,236 'exampl':930,931,973,1043,1129 'exist':148,170 'expert':1592,1704 'export':357,361,365,448,495,506,552,577,721,737,745,759,844,870,895,946,986,1095,1150,1203 'expos':1386 'express':110 'extend':295,1254 'factori':254,265,374,401,786,1059,1219,1488 'fail':1474 'failur':1294 'featur':144 'fetch':272,381,438,783,792,837,933 'fetch-bas':782 'fetchcreatecontextfnopt':408,453,789,810,833,841 'fetchrequesthandl':779,805,825,1559 'find':1549 'flow':51 'forbidden':708 'form':1009,1015,1029 'form.reset':1027 'formdata':1014 'found':649,700 'fresh':1275 'full':27,105,1523 'full-stack':26,104 'fulli':34 'fullstack':3 'function':191,450,497,896,947,987,1098 'gap':1643 'generat':46 'generic':1601 'get':847 'github':1665 'github.com':1667 'github.com/trpc/trpc)':1666 'global':1342 'group':183 'handler':225,269,378,430,434,769,776,822,845,848,1224,1325,1469 'handlesubmit':1004,1031 'header':243,468,914 'helper':421 'hook':1607 'http':429,483,1223,1628 'httpbatchlink':884,911,1587 'id':609,620,629,640,680,691,712,1378 'import':255,326,331,336,406,411,422,563,567,573,725,729,733,752,804,808,813,817,861,865,878,883,887,891,942,982,1079,1083,1087,1138,1142,1211,1509,1514,1515 'includ':1374 'increment':175 'initi':308 'inittrpc':327 'inittrpc.context':342 'inject':1381 'input':204,210,219,583,599,627,634,654,669,673,678,685,1233,1239,1370,1384,1641,1713 'input.cursor':608,610 'input.id':641,692,713 'input.limit':605,618 'insid':1597 'instal':306,311 'instanc':320,1341 'instanceof':353 'instead':1489 'integr':23 'intern':1387 'invalid':978,996,1537 'involv':486 'isload':951,957 'job':481 'keep':1272,1326,1401 'key':970,1126 'layer':1334 'let':31 'li':969,1125 'limit':160,585,954,1120,1410,1675 'link':910 'list':581,1001 'load':959 'log':289,1433 'logic':1321 'lookup':1299 'malform':1383 'manual':227 'match':1684 'max':589,660 'merg':1251 'messag':1159,1167,1170,1399 'middlewar':17,157,278,279,367,516,525,1257,1414,1635 'migrat':168 'min':587,658,664 'mismatch':1288 'miss':1721 'modul':1524,1550 'monorepo':80 'mount':766 'multi':155 'multi-step':154 'multipl':1263 'must':390,777 'mutat':195,666,682,975,1270,1526 'narrow':539 'need':464,1067,1110 'never':751,1210,1236,1360 'new':532,645,696,705,904,1013,1148,1173 'next':416,527,537,1450 'next-auth':415,1449 'next.js':21,81,108,256,375,770,1076,1658 'next.js/react':20 'nextapirequest':277,386 'nextcursor':616,624 'nextj':1565 'node.js':276,385 'non':544 'non-nul':543 'note':1354 'notificationrout':1152 'npm':310 'null':356,545,1424 'object':1073,1496 'observ':1139,1158 'offici':1647 'ondata':1197 'one':400 'onnew':1154 'onnotif':1165,1181,1185 'onsubmit':1030 'onsuccess':995,1539 'opt':452,831,840,843 'option':595 'opts.req':435 'opts.req.headers':469 'orderbi':612 'output':1693 'overhead':137 'overview':29 'page':260,796,1458,1569 'pagin':1375 'pair':799,1610 'pars':228 'pass':234,1491 'pattern':24,1595,1605,1608 'per':249,402,1265,1346 'per-provid':1345 'permiss':1714 'pitfal':1419 'post':601,623,636,643,651,687,694,741,850,968,1000,1040,1117,1124,1247 'post.authorid':702 'post.id':971,1127 'post.title':972,1128 'postlist':948 'postrout':579,730,742 'posts.length':617 'posts.map':967,1123 'posts.pop':619 'postspag':1099 'practic':1202 'prevent':1380,1416 'problem':1420,1470,1499,1525,1547,1572 'procedur':16,165,180,185,188,209,224,237,284,300,519,1330,1412,1427,1621 'product':1657 'project':85 'protect':518,1426 'protectedprocedur':554,570,653,677,1359 'protectedprocedure.subscription':1155 'provid':1347 'public':1397,1411 'public-saf':1396 'publicprocedur':363,569,582,626 'put':1319 'queri':192,596,631,858,1260,1479,1546,1670 'queries/mutations':1585 'querycli':879,902,905,924,925,928 'queryclientprovid':880,926 'rate':159,1409 'rate-limit':1408 'rather':1258 'raw':1238 'react':111,857,890,919,1545,1604,1606 'react-pattern':1603 'react.formevent':1006 'react.reactnode':900 'read':194 'real':142,201,1132 'real-tim':141,200,1131 'receiv':270,379,788,1456 'refactor':72 'refactoring-saf':71 'refetch':998,1543 'reflect':1528 'relat':184,1588 'reli':1361 'remix':109 'repo':120 'req':823,828,834 'req/res':463,798,1108,1460 'request':242,250,273,291,382,439,484,793,824,838,1072,1266 'requir':262,1189,1578,1712 'resolv':442 'resourc':1645 'rest/graphql':135,171 'return':347,465,503,536,622,650,670,709,920,958,962,965,1028,1122,1157,1182,1300 'returntyp':510 'reusabl':322 'review':1633,1705 'root':718 'root.ts':1253 'rout':433,1324,1580 'router':15,55,178,182,258,261,268,359,377,432,560,568,580,719,726,740,772,775,797,829,1153,1244,1459,1468,1554,1563,1570,1599 'rsc':479 'run':281 'runtim':1293 'safe':11,37,73,1398 'safeti':130,1353,1715 'schema':42,136,215,1242 'scope':162,1686 'secur':1352,1631 'security-auditor':1630 'separ':263,1217 'server':54,88,116,444,459,474,477,494,1046,1049,1057,1077,1105,1208,1227,1309,1405,1442,1471,1486,1629 'server-sid':443,458,473,1045,1056,1104,1404,1441,1485 'server/routers/notifications.ts':1137 'servic':1333 'session':239,455,466,500,504,541,548,1298,1422 'set':853 'setup':150 'shape':345,348,1371 'shape.data':350 'share':91,117,232,1337 'side':445,460,475,1047,1058,1106,1365,1406,1443,1487 'silenc':1284 'singl':119 'site':398 'skill':76,98,1589,1678 'skill-trpc-fullstack' 'solut':1435,1480,1508,1534,1555,1576 'sourc':918 'source-sickn33' 'specif':1700 'split':1243 'splitlink':1579 'src/app/api/trpc':801 'src/app/providers.tsx':875 'src/server/context.ts':405 'src/server/root.ts':724 'src/server/routers/post.ts':562 'src/server/trpc.ts':325,521 'src/utils/trpc.ts':860 'ssr':1051 'stack':28,106,1402 'stale':1350 'starter':1659 'state':233 'step':47,156,304,369,511,557,714,764,851 'stop':1706 'stream':203 'string':1021,1026,1160,1168 'submit':1034 'subscript':18,145,198,1134,1573,1577,1581 'substitut':1696 'success':1533,1718 'surfac':403,1290 'synthet':1069,1495 't.middleware':368 't.procedure':364 't.procedure.use':555 't.router':360 't3':1654 'take':604 'tanstack':1669 'tanstack.com':1673 'tanstack.com/query/latest)':1672 'tanstack/react-query':315,882 'task':1682 'tenant':161 'test':1617,1623,1702 'test-driven-develop':1616 'think':186 'throw':531,644,695,704 'time':69,143,202,1133,1264 'titl':656,1017,1019 'toast':1199 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'trace':1403 'treat':1691 'trigger':1541 'trpc':2,14,25,30,149,164,174,319,802,872,892,917,943,983,1339,1598,1612,1634,1646,1661,1664 'trpc-fullstack':1 'trpc.createclient':909 'trpc.io':1650 'trpc.io/docs)':1649 'trpc.notification.onnew.usesubscription':1195 'trpc.post.create.usemutation':994 'trpc.post.list.usequery':953 'trpc.provider':921 'trpc.useutils':991 'trpc/client':313,886 'trpc/react-query':314,864 'trpc/server':312,330,576,1086 'trpc/server/adapters/fetch':410,807,812,1557 'trpc/server/adapters/next':1551 'trpc/server/observable':1141 'trpcclient':907,923 'trpcerror':328,533,574,646,697,706,1393 'trpcprovid':897 'trust':1237 'two':372 'type':10,36,50,129,190,218,332,407,507,540,722,747,760,809,866,1033,1206,1285,1500,1513,1516 'type-saf':9,35 'typeof':762 'typescript':49,79,103,324,404,520,561,723,800,859,874,938,979,1074,1136,1186,1591,1594 'typescript-expert':1590 'ui':1531 'unauthor':535 'undefin':611,621,1196,1301 'unit':1622 'url':912 'usag':1188 'use':74,96,99,121,138,151,166,285,778,876,940,980,1052,1100,1216,1267,1304,1311,1392,1413,1438,1481,1556,1596,1624,1676 'usemut':1615 'usequeri':1613 'user':530,550,743,1177,1248,1431 'userrout':734,744 'usest':888,903,908 'util':990,1536,1602 'utils.invalidate':1268 'utils.post.list.invalidate':1002 'v5':418,1452 'valid':66,205,212,217,1231,1368,1642,1701 'via':446,1382,1462,1544 'want':124 'websocket':1135 'wire':1662 'without':39,134,1066,1240,1626 'work':303 'write':40,197,1620 'wslink':1190,1583 'x':916 'x-trpc-sourc':915 'z':564 'z.number':586 'z.object':584,628,655,679 'z.string':594,630,657,663,681 'zod':207,214,316,339,566,1235,1373 'zoderror':337,351,354","prices":[{"id":"bd142b56-8b65-4cdb-8623-7cd8d2757b6a","listingId":"abbec752-9eee-4cc1-93fb-26340af72697","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:46:32.981Z"}],"sources":[{"listingId":"abbec752-9eee-4cc1-93fb-26340af72697","source":"github","sourceId":"sickn33/antigravity-awesome-skills/trpc-fullstack","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/trpc-fullstack","isPrimary":false,"firstSeenAt":"2026-04-18T21:46:32.981Z","lastSeenAt":"2026-04-22T06:52:03.242Z"}],"details":{"listingId":"abbec752-9eee-4cc1-93fb-26340af72697","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"trpc-fullstack","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34460,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-22T06:40:00Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"4e5a102d26b35b6a02c8d0354478c3f12ba9a868","skill_md_path":"skills/trpc-fullstack/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/trpc-fullstack"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"name":"trpc-fullstack","description":"Build end-to-end type-safe APIs with tRPC — routers, procedures, middleware, subscriptions, and Next.js/React integration patterns."},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/trpc-fullstack"},"updatedAt":"2026-04-22T06:52:03.242Z"}}