zod-extract
Zod Extract
Find Zod schemas defined outside validations/ and centralize them.
Instructions
- Search for Zod usage patterns outside
validations/directory - For each inline schema found:
- Determine the appropriate validation file (existing or new)
- Generate the export with proper naming
- Generate the inferred type export
- Update the original file to import from
validations/
- Update barrel export in
validations/index.ts
What to look for
Zod patterns outside validations/:
// Inline schema definitions
const schema = z.object({ ... })
const userSchema = z.object({ ... })
// Inline in function calls
.input(z.object({ ... }))
zodResolver(z.object({ ... }))
// Partial/extended schemas that should be centralized
schema.partial()
schema.extend({ ... })
schema.pick({ ... })
schema.omit({ ... })
Naming Convention
| Context | Schema Name | Type Name |
|---|---|---|
| Create form | createUserSchema |
CreateUserInput |
| Update form | updateUserSchema |
UpdateUserInput |
| Query params | userQuerySchema |
UserQuery |
| Filter/search | userFilterSchema |
UserFilter |
| tRPC input | [action][Entity]Schema |
[Action][Entity]Input |
Output Pattern
validations/[entity].ts
import { z } from 'zod'
export const createUserSchema = z.object({
email: z.string().email('Invalid email address'),
name: z.string().min(1, 'Name is required'),
})
export const updateUserSchema = createUserSchema.partial()
export type CreateUserInput = z.infer<typeof createUserSchema>
export type UpdateUserInput = z.infer<typeof updateUserSchema>
validations/index.ts
export * from './user'
export * from './booking'
// ... etc
Updated source file
// Before
const schema = z.object({
email: z.string().email(),
name: z.string().min(1),
})
// After
import { createUserSchema } from '@/validations'
Common Cases
tRPC Router Input
// Before - server/api/routers/user/index.ts
export const userRouter = router({
create: publicProcedure
.input(z.object({
email: z.string().email(),
name: z.string(),
}))
.mutation(...)
})
// After
import { createUserSchema } from '@/validations'
export const userRouter = router({
create: publicProcedure
.input(createUserSchema)
.mutation(...)
})
React Hook Form
// Before - components/UserForm.tsx
const form = useForm({
resolver: zodResolver(z.object({
email: z.string().email(),
name: z.string().min(1),
})),
})
// After
import { createUserSchema } from '@/validations'
const form = useForm({
resolver: zodResolver(createUserSchema),
})
Query Parameters
// Before - app/users/page.tsx
const searchParams = z.object({
page: z.coerce.number().default(1),
search: z.string().optional(),
}).parse(params)
// After
import { userQuerySchema } from '@/validations'
const searchParams = userQuerySchema.parse(params)
Exceptions
Keep inline when:
- One-off validation in a test file
- Truly local validation that will never be reused
- Extending/picking from an already-centralized schema in the same file
Output Format
## Zod Extract Report
### Found 3 inline schemas
1. components/UserForm.tsx:12
- Schema: z.object({ email, name })
- Suggested: createUserSchema in validations/user.ts
- Action: Create new file
2. server/api/routers/booking/index.ts:25
- Schema: z.object({ date, userId })
- Suggested: createBookingSchema in validations/booking.ts
- Action: Add to existing file
3. app/search/page.tsx:8
- Schema: z.object({ q, page })
- Suggested: searchQuerySchema in validations/search.ts
- Action: Create new file
### Ready to extract?
I can make these changes now, or you can review first.
More from cerico/macfair
infographic
Generate infographics from text. Extracts key info, renders SVG, exports PNG. Uses Claude Code (no API costs).
38visx
Build data visualizations with visx (React + D3). Use for charts, graphs, and interactive data exploration.
21creative-design
Create distinctive, memorable UI for landing pages, portfolios, marketing sites, and one-off creative work. Use when the user explicitly wants something "distinctive", "creative", "memorable", or "unique" - NOT for standard app components where consistency matters.
20threejs
Build 3D scenes, animations, and interactive experiences with Three.js. Use for product viewers, backgrounds, data visualization, or creative experiments.
13prototype
Create quick React prototypes that bundle to a single HTML file. Use for demos, interactive experiments, or shareable artifacts - NOT for full apps (use audreygen/Next.js for those).
13test-review
Review existing tests for completeness, quality issues, and common mistakes
12