Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Scaffolds tRPC routers, procedures, and Zod schemas with full type safety following DevPrep AI patterns
.claude/skills/aiskillstore-trpc-scaffolder/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 99% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 68% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 26% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 40% | 0% |
Automate creation of type-safe tRPC endpoints with Zod validation.
TL;DR: Run scripts to create routers/schemas, register in _app.ts, validate with scripts.
Auto-triggered by keywords:
lib/trpc/routers/
_app.ts # Register all routers here ⚠️
{name}.ts # Router files
lib/trpc/schemas/
{entity}.schema.ts # Zod schemastypescriptexport const nameRouter = router({ doThing: publicProcedure .input(inputSchema) .output(outputSchema) .mutation(async ({ input }) => { /* logic */ }), });
typescriptexport const inputSchema = z.object({ field: z.string().min(1), }); export type Input = z.infer<typeof inputSchema>; // ⚠️ Required!
typescript// In _app.ts export const appRouter = router({ ai: aiRouter, name: nameRouter, // ⬅️ Add new routers here });
bash./.claude/skills/trpc-scaffolder/scripts/create-router.sh user # Creates: lib/trpc/routers/user.ts # ⚠️ Remember to register in _app.ts!
bash./.claude/skills/trpc-scaffolder/scripts/add-procedure.sh ai getHints query # Outputs code snippet to add to router
bash./.claude/skills/trpc-scaffolder/scripts/create-schema.sh hint # Creates: lib/trpc/schemas/hint.schema.ts
bash./.claude/skills/trpc-scaffolder/scripts/validate-trpc.sh # Checks: router registration, type exports
| Type | Use For | Method | |------|---------|--------| | Query | Fetch data (GET) | .query(async ({ input }) => ...) | | Mutation | Modify data (POST/PUT/DELETE) | .mutation(async ({ input }) => ...) |
| Type | Pattern | Example | |------|---------|---------| | String | z.string().min(1).max(100) | Name validation | | Number | z.number().int().min(0).max(10) | Difficulty 0-10 | | Email | z.string().email() | Email validation | | Optional | z.string().optional() | Optional field | | Array | z.array(z.string()).min(1) | At least 1 item | | Enum | z.enum(["a", "b", "c"]) | Fixed choices | | Object | z.object({ field: z.string() }) | Nested object |
{domain}Router (e.g., aiRouter, userRouter)camelCase (e.g., generateQuestions, getHints){action}{Entity}{Input\|Output}Schema{entity}.schema.ts, {domain}.ts| Code | When | Example | |------|------|---------| | NOT_FOUND | Resource doesn't exist | User not found | | BAD_REQUEST | Invalid input | Validation failed | | UNAUTHORIZED | Not authenticated | Login required | | FORBIDDEN | Not authorized | Access denied | | INTERNAL_SERVER_ERROR | Server error | API failure |
typescript// ❌ Forgot this step // ✅ Add to _app.ts: import { userRouter } from "./user"; export const appRouter = router({ ai: aiRouter, user: userRouter });
typescript// ❌ Schema without types export const userSchema = z.object({ name: z.string() }); // ✅ Always export inferred types export type User = z.infer<typeof userSchema>;
typescript// ❌ Using mutation for fetching data getData: publicProcedure.mutation(...) // ✅ Use query for GET operations getData: publicProcedure.query(...)
typescript// ❌ No validation field: z.string() // ✅ Add constraints field: z.string().min(1, "Field is required")
SKILL.md is self-sufficient for:
Load additional docs when needed:
| Need | Load | |------|------| | Step-by-step tutorial | docs/quick-start-guide.md | | Advanced Zod patterns | docs/trpc-patterns.md (lines 1-80) | | Error handling strategies | docs/trpc-patterns.md (lines 150-220) | | Testing procedures | docs/trpc-patterns.md (lines 220-270) | | Context & middleware | docs/trpc-patterns.md (lines 80-150) |
Code examples:
examples/good-router.ts, examples/good-schema.tsFull project docs: Docs/api-design.md, Docs/api-transition/trpc-migration.md
Version: 1.0.0 | Updated: October 2025 Pattern: Follows quality-reviewer structure (optimized)
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→fail | 28,750 | 40,539 | +41% | 1 | 1 | 0% | 3,264 | 3,722 | +14% | 0 | 0 | — |
case-01 | fail→fail | 59,166 | 291,370 | +392% | 1 | 1 | 0% | 3,485 | 1,679 | -52% | 0 | 0 | — |
case-02 | fail→fail | 27,158 | 109,068 | +302% | 1 | 1 | 0% | 138 | 2,046 | +1383% | 0 | 0 | — |
case-04 | fail→fail | 28,619 | 18,311 | -36% | 1 | 1 | 0% | 1,918 | 2,817 | +47% | 0 | 0 | — |
case-05 | pass→pass | 11,121 | 17,068 | +53% | 1 | 1 | 0% | 2,071 | 3,162 | +53% | 0 | 0 | — |
case-06 | pass→pass | 19,482 | 15,322 | -21% | 1 | 1 | 0% | 1,769 | 2,659 | +50% | 0 | 0 | — |
case-07 | fail→pass | 10,648 | 7,774 | -27% | 1 | 1 | 0% | 1,015 | 2,024 | +99% | 0 | 0 | — |
case-08 | fail→pass | 14,979 | 3,541 | -76% | 1 | 1 | 0% | 1,392 | 2,077 | +49% | 0 | 0 | — |
case-09 | fail→pass | 11,376 | 9,241 | -19% | 1 | 1 | 0% | 1,226 | 2,056 | +68% | 0 | 0 | — |
case-10 | pass→pass | 10,742 | 11,945 | +11% | 1 | 1 | 0% | 1,623 | 2,234 | +38% | 0 | 0 | — |
case-11 | pass→pass | 10,657 | 11,437 | +7% | 1 | 1 | 0% | 1,982 | 2,598 | +31% | 0 | 0 | — |
case-12 | pass→pass | 16,254 | 8,109 | -50% | 1 | 1 | 0% | 2,125 | 2,751 | +29% | 0 | 0 | — |
case-13 | pass→pass | 6,786 | 8,517 | +26% | 1 | 1 | 0% | 891 | 1,930 | +117% | 0 | 0 | — |
case-14 | fail→pass | 14,902 | 10,816 | -27% | 1 | 1 | 0% | 1,892 | 2,381 | +26% | 0 | 0 | — |
case-15 | fail→pass | 18,431 | 8,562 | -54% | 1 | 1 | 0% | 1,328 | 1,853 | +40% | 0 | 0 | — |
case-16 | fail→pass | 30,602 | 7,783 | -75% | 1 | 1 | 0% | 5,182 | 1,901 | -63% | 0 | 0 | — |
case-17 | fail→pass | 7,419 | 5,847 | -21% | 1 | 1 | 0% | 1,343 | 1,790 | +33% | 0 | 0 | — |
case-18 | fail→pass | 9,774 | 3,899 | -60% | 1 | 1 | 0% | 1,544 | 1,780 | +15% | 0 | 0 | — |
case-19 | fail→pass | 14,836 | 8,125 | -45% | 1 | 1 | 0% | 2,163 | 1,728 | -20% | 0 | 0 | — |
case-20 | fail→pass | 33,946 | 3,003 | -91% | 1 | 1 | 0% | 1,572 | 1,661 | +6% | 0 | 0 | — |
case-21 | fail→pass | 20,979 | 15,812 | -25% | 1 | 1 | 0% | 2,702 | 1,709 | -37% | 0 | 0 | — |
case-22 | fail→pass | 6,134 | 9,933 | +62% | 1 | 1 | 0% | 841 | 1,974 | +135% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +55 percentage points is the difference between those two pass rates over the 20 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.