@smicolon/ai-kit 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/.claude-plugin/CLAUDE.md +7 -0
  2. package/.claude-plugin/marketplace.json +373 -0
  3. package/README.md +26 -16
  4. package/dist/index.js +146 -38
  5. package/package.json +4 -3
  6. package/packs/architect/CHANGELOG.md +17 -0
  7. package/packs/architect/README.md +58 -0
  8. package/packs/architect/agents/system-architect.md +768 -0
  9. package/packs/architect/commands/diagram-create.md +300 -0
  10. package/packs/better-auth/.claude-plugin/plugin.json +14 -0
  11. package/packs/better-auth/.mcp.json +14 -0
  12. package/packs/better-auth/CHANGELOG.md +26 -0
  13. package/packs/better-auth/README.md +125 -0
  14. package/packs/better-auth/agents/auth-architect.md +278 -0
  15. package/packs/better-auth/commands/auth-provider-add.md +265 -0
  16. package/packs/better-auth/commands/auth-setup.md +298 -0
  17. package/packs/better-auth/skills/auth-security/SKILL.md +425 -0
  18. package/packs/better-auth/skills/better-auth-patterns/SKILL.md +455 -0
  19. package/packs/dev-loop/.claude-plugin/plugin.json +10 -0
  20. package/packs/dev-loop/CHANGELOG.md +69 -0
  21. package/packs/dev-loop/README.md +155 -0
  22. package/packs/dev-loop/commands/cancel-dev.md +21 -0
  23. package/packs/dev-loop/commands/dev-loop.md +72 -0
  24. package/packs/dev-loop/commands/dev-plan.md +351 -0
  25. package/packs/dev-loop/hooks/hooks.json +15 -0
  26. package/packs/dev-loop/hooks/stop-hook.sh +178 -0
  27. package/packs/dev-loop/scripts/setup-dev-loop.sh +194 -0
  28. package/packs/dev-loop/skills/tdd-planner/SKILL.md +249 -0
  29. package/packs/dev-loop/skills/tdd-planner/references/framework-patterns.md +874 -0
  30. package/packs/dev-loop/skills/tdd-planner/references/good-example.md +260 -0
  31. package/packs/dev-loop/skills/tdd-planner/references/plan-template.md +275 -0
  32. package/packs/django/CHANGELOG.md +39 -0
  33. package/packs/django/README.md +92 -0
  34. package/packs/django/agents/django-architect.md +182 -0
  35. package/packs/django/agents/django-builder.md +250 -0
  36. package/packs/django/agents/django-feature-based.md +420 -0
  37. package/packs/django/agents/django-reviewer.md +253 -0
  38. package/packs/django/agents/django-tester.md +230 -0
  39. package/packs/django/commands/api-endpoint.md +285 -0
  40. package/packs/django/commands/model-create.md +178 -0
  41. package/packs/django/commands/test-generate.md +325 -0
  42. package/packs/django/rules/migrations.md +138 -0
  43. package/packs/django/rules/models.md +167 -0
  44. package/packs/django/rules/serializers.md +126 -0
  45. package/packs/django/rules/services.md +131 -0
  46. package/packs/django/rules/tests.md +140 -0
  47. package/packs/django/rules/views.md +102 -0
  48. package/packs/django/skills/import-convention-enforcer/SKILL.md +226 -0
  49. package/packs/django/skills/import-convention-enforcer/patterns/django-imports.md +343 -0
  50. package/packs/django/skills/migration-safety-checker/SKILL.md +375 -0
  51. package/packs/django/skills/model-entity-validator/SKILL.md +298 -0
  52. package/packs/django/skills/performance-optimizer/SKILL.md +447 -0
  53. package/packs/django/skills/red-phase-verifier/SKILL.md +180 -0
  54. package/packs/django/skills/security-first-validator/SKILL.md +435 -0
  55. package/packs/django/skills/test-coverage-advisor/SKILL.md +394 -0
  56. package/packs/django/skills/test-validity-checker/SKILL.md +194 -0
  57. package/packs/failure-log/.claude-plugin/plugin.json +14 -0
  58. package/packs/failure-log/CHANGELOG.md +20 -0
  59. package/packs/failure-log/README.md +168 -0
  60. package/packs/failure-log/commands/failure-add.md +106 -0
  61. package/packs/failure-log/commands/failure-list.md +89 -0
  62. package/packs/failure-log/hooks/hooks.json +16 -0
  63. package/packs/failure-log/hooks/scripts/inject-failures.sh +64 -0
  64. package/packs/failure-log/skills/failure-log-manager/SKILL.md +164 -0
  65. package/packs/flutter/.claude-plugin/plugin.json +10 -0
  66. package/packs/flutter/CHANGELOG.md +19 -0
  67. package/packs/flutter/README.md +170 -0
  68. package/packs/flutter/agents/flutter-architect.md +166 -0
  69. package/packs/flutter/agents/flutter-builder.md +303 -0
  70. package/packs/flutter/agents/release-manager.md +355 -0
  71. package/packs/flutter/commands/fastlane-setup.md +188 -0
  72. package/packs/flutter/commands/flutter-build.md +90 -0
  73. package/packs/flutter/commands/flutter-deploy.md +133 -0
  74. package/packs/flutter/commands/flutter-test.md +117 -0
  75. package/packs/flutter/commands/signing-setup.md +209 -0
  76. package/packs/flutter/hooks/hooks.json +17 -0
  77. package/packs/flutter/skills/fastlane-knowledge/SKILL.md +193 -0
  78. package/packs/flutter/skills/flutter-architecture/SKILL.md +127 -0
  79. package/packs/flutter/skills/store-publishing/SKILL.md +163 -0
  80. package/packs/hono/.claude-plugin/plugin.json +19 -0
  81. package/packs/hono/CHANGELOG.md +19 -0
  82. package/packs/hono/README.md +143 -0
  83. package/packs/hono/agents/hono-architect.md +240 -0
  84. package/packs/hono/agents/hono-builder.md +285 -0
  85. package/packs/hono/agents/hono-reviewer.md +279 -0
  86. package/packs/hono/agents/hono-tester.md +346 -0
  87. package/packs/hono/commands/middleware-create.md +223 -0
  88. package/packs/hono/commands/project-init.md +306 -0
  89. package/packs/hono/commands/route-create.md +153 -0
  90. package/packs/hono/commands/rpc-client.md +263 -0
  91. package/packs/hono/hooks/hooks.json +4 -0
  92. package/packs/hono/skills/cloudflare-bindings/SKILL.md +408 -0
  93. package/packs/hono/skills/hono-patterns/SKILL.md +309 -0
  94. package/packs/hono/skills/rpc-typesafe/SKILL.md +388 -0
  95. package/packs/hono/skills/zod-validation/SKILL.md +332 -0
  96. package/packs/nestjs/CHANGELOG.md +29 -0
  97. package/packs/nestjs/README.md +75 -0
  98. package/packs/nestjs/agents/nestjs-architect.md +402 -0
  99. package/packs/nestjs/agents/nestjs-builder.md +301 -0
  100. package/packs/nestjs/agents/nestjs-tester.md +437 -0
  101. package/packs/nestjs/commands/module-create.md +369 -0
  102. package/packs/nestjs/rules/controllers.md +92 -0
  103. package/packs/nestjs/rules/dto.md +124 -0
  104. package/packs/nestjs/rules/entities.md +102 -0
  105. package/packs/nestjs/rules/services.md +106 -0
  106. package/packs/nestjs/skills/barrel-export-manager/SKILL.md +389 -0
  107. package/packs/nestjs/skills/import-convention-enforcer/SKILL.md +365 -0
  108. package/packs/nextjs/CHANGELOG.md +36 -0
  109. package/packs/nextjs/README.md +76 -0
  110. package/packs/nextjs/agents/frontend-tester.md +680 -0
  111. package/packs/nextjs/agents/frontend-visual.md +820 -0
  112. package/packs/nextjs/agents/nextjs-architect.md +331 -0
  113. package/packs/nextjs/agents/nextjs-modular.md +433 -0
  114. package/packs/nextjs/commands/component-create.md +398 -0
  115. package/packs/nextjs/rules/api-routes.md +129 -0
  116. package/packs/nextjs/rules/components.md +106 -0
  117. package/packs/nextjs/rules/hooks.md +132 -0
  118. package/packs/nextjs/skills/accessibility-validator/SKILL.md +445 -0
  119. package/packs/nextjs/skills/import-convention-enforcer/SKILL.md +399 -0
  120. package/packs/nextjs/skills/react-form-validator/SKILL.md +569 -0
  121. package/packs/nuxtjs/CHANGELOG.md +30 -0
  122. package/packs/nuxtjs/README.md +56 -0
  123. package/packs/nuxtjs/agents/frontend-tester.md +680 -0
  124. package/packs/nuxtjs/agents/frontend-visual.md +820 -0
  125. package/packs/nuxtjs/agents/nuxtjs-architect.md +537 -0
  126. package/packs/nuxtjs/commands/component-create.md +223 -0
  127. package/packs/nuxtjs/rules/components.md +101 -0
  128. package/packs/nuxtjs/rules/composables.md +118 -0
  129. package/packs/nuxtjs/rules/server-routes.md +127 -0
  130. package/packs/nuxtjs/skills/accessibility-validator/SKILL.md +183 -0
  131. package/packs/nuxtjs/skills/import-convention-enforcer/SKILL.md +196 -0
  132. package/packs/nuxtjs/skills/veevalidate-form-validator/SKILL.md +190 -0
  133. package/packs/onboard/CHANGELOG.md +22 -0
  134. package/packs/onboard/README.md +103 -0
  135. package/packs/onboard/agents/onboard-guide.md +118 -0
  136. package/packs/onboard/commands/onboard.md +313 -0
  137. package/packs/onboard/skills/onboard-context-provider/SKILL.md +98 -0
  138. package/packs/tanstack-router/.claude-plugin/plugin.json +14 -0
  139. package/packs/tanstack-router/CHANGELOG.md +30 -0
  140. package/packs/tanstack-router/README.md +113 -0
  141. package/packs/tanstack-router/agents/tanstack-architect.md +173 -0
  142. package/packs/tanstack-router/agents/tanstack-builder.md +360 -0
  143. package/packs/tanstack-router/agents/tanstack-tester.md +454 -0
  144. package/packs/tanstack-router/commands/form-create.md +313 -0
  145. package/packs/tanstack-router/commands/query-create.md +263 -0
  146. package/packs/tanstack-router/commands/route-create.md +190 -0
  147. package/packs/tanstack-router/commands/table-create.md +413 -0
  148. package/packs/tanstack-router/skills/ai-patterns/SKILL.md +370 -0
  149. package/packs/tanstack-router/skills/db-patterns/SKILL.md +346 -0
  150. package/packs/tanstack-router/skills/devtools-patterns/SKILL.md +415 -0
  151. package/packs/tanstack-router/skills/form-patterns/SKILL.md +425 -0
  152. package/packs/tanstack-router/skills/pacer-patterns/SKILL.md +341 -0
  153. package/packs/tanstack-router/skills/query-patterns/SKILL.md +359 -0
  154. package/packs/tanstack-router/skills/router-patterns/SKILL.md +285 -0
  155. package/packs/tanstack-router/skills/store-patterns/SKILL.md +351 -0
  156. package/packs/tanstack-router/skills/table-patterns/SKILL.md +531 -0
  157. package/packs/tanstack-router/skills/tanstack-conventions/SKILL.md +428 -0
  158. package/packs/tanstack-router/skills/virtual-patterns/SKILL.md +490 -0
  159. package/packs/worktree/.claude-plugin/plugin.json +19 -0
  160. package/packs/worktree/CHANGELOG.md +24 -0
  161. package/packs/worktree/README.md +110 -0
  162. package/packs/worktree/commands/wt.md +73 -0
  163. package/packs/worktree/scripts/wt.sh +396 -0
  164. package/packs/worktree/skills/worktree-manager/SKILL.md +68 -0
@@ -0,0 +1,388 @@
1
+ ---
2
+ name: rpc-typesafe
3
+ description: This skill activates when setting up Hono RPC client, configuring type-safe API calls, or discussing client-server type sharing. It provides patterns for the hc client, type inference, and React Query integration.
4
+ ---
5
+
6
+ # Hono RPC Type Safety
7
+
8
+ Patterns for type-safe client-server communication with Hono.
9
+
10
+ ## Server Setup
11
+
12
+ ### Export App Type
13
+
14
+ ```typescript
15
+ // src/index.ts
16
+ import { Hono } from 'hono'
17
+ import { zValidator } from '@hono/zod-validator'
18
+ import { z } from 'zod'
19
+
20
+ const app = new Hono()
21
+
22
+ // Define routes with validators for full type inference
23
+ const routes = app
24
+ .get('/users', async (c) => {
25
+ return c.json({ users: [{ id: '1', name: 'John' }] })
26
+ })
27
+ .post('/users',
28
+ zValidator('json', z.object({
29
+ email: z.string().email(),
30
+ name: z.string()
31
+ })),
32
+ async (c) => {
33
+ const data = c.req.valid('json')
34
+ return c.json({ id: crypto.randomUUID(), ...data }, 201)
35
+ }
36
+ )
37
+ .get('/users/:id', async (c) => {
38
+ const id = c.req.param('id')
39
+ return c.json({ id, name: 'John' })
40
+ })
41
+
42
+ export default routes
43
+
44
+ // CRITICAL: Export type for client
45
+ export type AppType = typeof routes
46
+ ```
47
+
48
+ ### Route Chaining for Type Inference
49
+
50
+ ```typescript
51
+ // Chain routes to preserve types
52
+ const userRoutes = new Hono()
53
+ .get('/', async (c) => c.json({ users: [] }))
54
+ .post('/',
55
+ zValidator('json', createUserSchema),
56
+ async (c) => c.json({ id: '1' }, 201)
57
+ )
58
+
59
+ const postRoutes = new Hono()
60
+ .get('/', async (c) => c.json({ posts: [] }))
61
+ .post('/',
62
+ zValidator('json', createPostSchema),
63
+ async (c) => c.json({ id: '1' }, 201)
64
+ )
65
+
66
+ // Compose and export
67
+ const app = new Hono()
68
+ .route('/users', userRoutes)
69
+ .route('/posts', postRoutes)
70
+
71
+ export type AppType = typeof app
72
+ ```
73
+
74
+ ## Client Setup
75
+
76
+ ### Basic Client
77
+
78
+ ```typescript
79
+ // client.ts
80
+ import { hc } from 'hono/client'
81
+ import type { AppType } from './server'
82
+
83
+ // Create typed client
84
+ const client = hc<AppType>('http://localhost:8787')
85
+
86
+ // Type-safe requests
87
+ const res = await client.users.$get()
88
+ const data = await res.json() // Typed!
89
+ ```
90
+
91
+ ### Client Factory
92
+
93
+ ```typescript
94
+ // lib/api-client.ts
95
+ import { hc } from 'hono/client'
96
+ import type { AppType } from '@/server'
97
+
98
+ export function createClient(baseUrl: string, token?: string) {
99
+ return hc<AppType>(baseUrl, {
100
+ headers: token ? { Authorization: `Bearer ${token}` } : undefined
101
+ })
102
+ }
103
+
104
+ // Default instance
105
+ export const api = createClient(
106
+ process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8787'
107
+ )
108
+ ```
109
+
110
+ ## Request Patterns
111
+
112
+ ### GET Requests
113
+
114
+ ```typescript
115
+ // Simple GET
116
+ const res = await api.users.$get()
117
+ const { users } = await res.json()
118
+
119
+ // GET with query params
120
+ const res = await api.users.$get({
121
+ query: {
122
+ page: 1,
123
+ limit: 20,
124
+ search: 'john'
125
+ }
126
+ })
127
+
128
+ // GET with path params
129
+ const res = await api.users[':id'].$get({
130
+ param: { id: 'user-123' }
131
+ })
132
+ ```
133
+
134
+ ### POST Requests
135
+
136
+ ```typescript
137
+ // POST with JSON body
138
+ const res = await api.users.$post({
139
+ json: {
140
+ email: 'user@example.com',
141
+ name: 'New User'
142
+ }
143
+ })
144
+
145
+ if (res.ok) {
146
+ const user = await res.json()
147
+ console.log(user.id) // Typed!
148
+ }
149
+ ```
150
+
151
+ ### PUT/PATCH Requests
152
+
153
+ ```typescript
154
+ const res = await api.users[':id'].$put({
155
+ param: { id: 'user-123' },
156
+ json: {
157
+ name: 'Updated Name'
158
+ }
159
+ })
160
+ ```
161
+
162
+ ### DELETE Requests
163
+
164
+ ```typescript
165
+ const res = await api.users[':id'].$delete({
166
+ param: { id: 'user-123' }
167
+ })
168
+
169
+ if (res.status === 204) {
170
+ console.log('Deleted successfully')
171
+ }
172
+ ```
173
+
174
+ ## Type Utilities
175
+
176
+ ### InferRequestType / InferResponseType
177
+
178
+ ```typescript
179
+ import { hc, InferRequestType, InferResponseType } from 'hono/client'
180
+ import type { AppType } from './server'
181
+
182
+ // Get specific endpoint type
183
+ type CreateUserRequest = InferRequestType<typeof api.users.$post>['json']
184
+ // { email: string; name: string }
185
+
186
+ type UserResponse = InferResponseType<typeof api.users[':id'].$get>
187
+ // { id: string; name: string }
188
+
189
+ // Use in functions
190
+ async function createUser(data: CreateUserRequest): Promise<UserResponse> {
191
+ const res = await api.users.$post({ json: data })
192
+ return res.json()
193
+ }
194
+ ```
195
+
196
+ ### URL Generation
197
+
198
+ ```typescript
199
+ // Generate URL without making request
200
+ const url = api.users[':id'].$url({
201
+ param: { id: 'user-123' }
202
+ })
203
+ // 'http://localhost:8787/users/user-123'
204
+
205
+ // Useful for links, prefetching, etc.
206
+ ```
207
+
208
+ ## Error Handling
209
+
210
+ ### Response Status Checking
211
+
212
+ ```typescript
213
+ async function getUser(id: string) {
214
+ const res = await api.users[':id'].$get({ param: { id } })
215
+
216
+ if (!res.ok) {
217
+ if (res.status === 404) {
218
+ throw new Error('User not found')
219
+ }
220
+ throw new Error(`API error: ${res.status}`)
221
+ }
222
+
223
+ return res.json()
224
+ }
225
+ ```
226
+
227
+ ### Typed Error Responses
228
+
229
+ ```typescript
230
+ // Server defines error format
231
+ app.get('/users/:id', async (c) => {
232
+ const user = await getUser(c.req.param('id'))
233
+
234
+ if (!user) {
235
+ return c.json({ error: 'User not found' }, 404)
236
+ }
237
+
238
+ return c.json(user)
239
+ })
240
+
241
+ // Client handles typed errors
242
+ const res = await api.users[':id'].$get({ param: { id } })
243
+
244
+ if (res.status === 404) {
245
+ const { error } = await res.json()
246
+ console.log(error) // 'User not found'
247
+ }
248
+ ```
249
+
250
+ ## React Query Integration
251
+
252
+ ### Query Hooks
253
+
254
+ ```typescript
255
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
256
+ import { api } from '@/lib/api-client'
257
+
258
+ // List query
259
+ export function useUsers(page = 1) {
260
+ return useQuery({
261
+ queryKey: ['users', page],
262
+ queryFn: async () => {
263
+ const res = await api.users.$get({ query: { page } })
264
+ if (!res.ok) throw new Error('Failed to fetch users')
265
+ return res.json()
266
+ }
267
+ })
268
+ }
269
+
270
+ // Single item query
271
+ export function useUser(id: string) {
272
+ return useQuery({
273
+ queryKey: ['users', id],
274
+ queryFn: async () => {
275
+ const res = await api.users[':id'].$get({ param: { id } })
276
+ if (!res.ok) throw new Error('User not found')
277
+ return res.json()
278
+ },
279
+ enabled: !!id
280
+ })
281
+ }
282
+ ```
283
+
284
+ ### Mutation Hooks
285
+
286
+ ```typescript
287
+ export function useCreateUser() {
288
+ const queryClient = useQueryClient()
289
+
290
+ return useMutation({
291
+ mutationFn: async (data: { email: string; name: string }) => {
292
+ const res = await api.users.$post({ json: data })
293
+ if (!res.ok) throw new Error('Failed to create user')
294
+ return res.json()
295
+ },
296
+ onSuccess: () => {
297
+ queryClient.invalidateQueries({ queryKey: ['users'] })
298
+ }
299
+ })
300
+ }
301
+
302
+ export function useUpdateUser() {
303
+ const queryClient = useQueryClient()
304
+
305
+ return useMutation({
306
+ mutationFn: async ({ id, data }: { id: string; data: { name: string } }) => {
307
+ const res = await api.users[':id'].$put({ param: { id }, json: data })
308
+ if (!res.ok) throw new Error('Failed to update user')
309
+ return res.json()
310
+ },
311
+ onSuccess: (_, { id }) => {
312
+ queryClient.invalidateQueries({ queryKey: ['users', id] })
313
+ }
314
+ })
315
+ }
316
+ ```
317
+
318
+ ### Component Usage
319
+
320
+ ```typescript
321
+ function UserList() {
322
+ const { data, isLoading, error } = useUsers()
323
+ const createUser = useCreateUser()
324
+
325
+ if (isLoading) return <div>Loading...</div>
326
+ if (error) return <div>Error: {error.message}</div>
327
+
328
+ return (
329
+ <div>
330
+ {data?.users.map(user => (
331
+ <div key={user.id}>{user.name}</div>
332
+ ))}
333
+
334
+ <button
335
+ onClick={() => createUser.mutate({
336
+ email: 'new@example.com',
337
+ name: 'New User'
338
+ })}
339
+ >
340
+ Add User
341
+ </button>
342
+ </div>
343
+ )
344
+ }
345
+ ```
346
+
347
+ ## Configuration Requirements
348
+
349
+ ### TypeScript Config
350
+
351
+ Both server and client need strict mode:
352
+
353
+ ```json
354
+ {
355
+ "compilerOptions": {
356
+ "strict": true,
357
+ "moduleResolution": "bundler"
358
+ }
359
+ }
360
+ ```
361
+
362
+ ### Status Codes for Type Discrimination
363
+
364
+ ```typescript
365
+ // Server: Explicit status codes enable type inference
366
+ app.post('/users', async (c) => {
367
+ return c.json({ id: '1', name: 'User' }, 201) // 201 for created
368
+ })
369
+
370
+ app.get('/users/:id', async (c) => {
371
+ const user = await getUser(id)
372
+ if (!user) {
373
+ return c.json({ error: 'Not found' }, 404) // 404 for not found
374
+ }
375
+ return c.json(user, 200) // 200 for success
376
+ })
377
+ ```
378
+
379
+ ## Best Practices
380
+
381
+ 1. **Always export `AppType`** from server
382
+ 2. **Chain routes** for proper type inference
383
+ 3. **Use `zValidator`** for automatic request type inference
384
+ 4. **Specify status codes** for response type discrimination
385
+ 5. **Use `strict: true`** in both server and client tsconfig
386
+ 6. **Create typed error handlers** for consistent error responses
387
+ 7. **Wrap in React Query** for caching and state management
388
+ 8. **Use `InferRequestType`/`InferResponseType`** for complex types
@@ -0,0 +1,332 @@
1
+ ---
2
+ name: zod-validation
3
+ description: This skill activates when writing form validation, request validation, or Zod schemas in Hono. It provides patterns for validating JSON bodies, query parameters, path parameters, and headers with proper error handling.
4
+ ---
5
+
6
+ # Zod Validation in Hono
7
+
8
+ Patterns for request validation using Zod and @hono/zod-validator.
9
+
10
+ ## Setup
11
+
12
+ ```bash
13
+ bun add zod @hono/zod-validator
14
+ ```
15
+
16
+ ## Basic Validation
17
+
18
+ ### JSON Body
19
+
20
+ ```typescript
21
+ import { zValidator } from '@hono/zod-validator'
22
+ import { z } from 'zod'
23
+
24
+ const createUserSchema = z.object({
25
+ email: z.string().email('Invalid email address'),
26
+ name: z.string().min(1, 'Name is required').max(100),
27
+ age: z.number().int().positive().optional(),
28
+ })
29
+
30
+ app.post('/users',
31
+ zValidator('json', createUserSchema),
32
+ async (c) => {
33
+ const data = c.req.valid('json')
34
+ // data is typed as { email: string; name: string; age?: number }
35
+ return c.json(data, 201)
36
+ }
37
+ )
38
+ ```
39
+
40
+ ### Query Parameters
41
+
42
+ ```typescript
43
+ const paginationSchema = z.object({
44
+ page: z.coerce.number().int().positive().default(1),
45
+ limit: z.coerce.number().int().min(1).max(100).default(20),
46
+ sort: z.enum(['asc', 'desc']).default('desc'),
47
+ search: z.string().optional(),
48
+ })
49
+
50
+ app.get('/users',
51
+ zValidator('query', paginationSchema),
52
+ async (c) => {
53
+ const { page, limit, sort, search } = c.req.valid('query')
54
+ // All values are properly typed and coerced
55
+ return c.json({ page, limit, sort, search })
56
+ }
57
+ )
58
+ ```
59
+
60
+ ### Path Parameters
61
+
62
+ ```typescript
63
+ const userParamsSchema = z.object({
64
+ id: z.string().uuid('Invalid user ID format'),
65
+ })
66
+
67
+ app.get('/users/:id',
68
+ zValidator('param', userParamsSchema),
69
+ async (c) => {
70
+ const { id } = c.req.valid('param')
71
+ return c.json({ id })
72
+ }
73
+ )
74
+ ```
75
+
76
+ ### Headers
77
+
78
+ ```typescript
79
+ const authHeaderSchema = z.object({
80
+ authorization: z.string().startsWith('Bearer '),
81
+ 'x-request-id': z.string().uuid().optional(),
82
+ })
83
+
84
+ app.get('/protected',
85
+ zValidator('header', authHeaderSchema),
86
+ async (c) => {
87
+ const headers = c.req.valid('header')
88
+ return c.json({ authenticated: true })
89
+ }
90
+ )
91
+ ```
92
+
93
+ ### Form Data
94
+
95
+ ```typescript
96
+ const uploadSchema = z.object({
97
+ title: z.string().min(1),
98
+ description: z.string().optional(),
99
+ // File validation happens separately
100
+ })
101
+
102
+ app.post('/upload',
103
+ zValidator('form', uploadSchema),
104
+ async (c) => {
105
+ const { title, description } = c.req.valid('form')
106
+ return c.json({ title, description })
107
+ }
108
+ )
109
+ ```
110
+
111
+ ## Schema Patterns
112
+
113
+ ### Reusable Field Schemas
114
+
115
+ ```typescript
116
+ // validators/common.ts
117
+ export const emailSchema = z.string().email('Invalid email')
118
+ export const uuidSchema = z.string().uuid('Invalid ID format')
119
+ export const dateSchema = z.coerce.date()
120
+
121
+ export const paginationSchema = z.object({
122
+ page: z.coerce.number().int().positive().default(1),
123
+ limit: z.coerce.number().int().min(1).max(100).default(20),
124
+ })
125
+ ```
126
+
127
+ ### Create/Update Pattern
128
+
129
+ ```typescript
130
+ // validators/user.schema.ts
131
+ export const createUserSchema = z.object({
132
+ email: z.string().email(),
133
+ name: z.string().min(1).max(100),
134
+ password: z.string().min(8),
135
+ role: z.enum(['user', 'admin']).default('user'),
136
+ })
137
+
138
+ // Partial for updates (all fields optional)
139
+ export const updateUserSchema = createUserSchema.partial()
140
+
141
+ // Omit for specific updates
142
+ export const updatePasswordSchema = createUserSchema.pick({
143
+ password: true,
144
+ }).extend({
145
+ currentPassword: z.string(),
146
+ confirmPassword: z.string(),
147
+ }).refine(data => data.password === data.confirmPassword, {
148
+ message: 'Passwords do not match',
149
+ path: ['confirmPassword'],
150
+ })
151
+
152
+ // Infer TypeScript types
153
+ export type CreateUser = z.infer<typeof createUserSchema>
154
+ export type UpdateUser = z.infer<typeof updateUserSchema>
155
+ ```
156
+
157
+ ### Nested Objects
158
+
159
+ ```typescript
160
+ const addressSchema = z.object({
161
+ street: z.string(),
162
+ city: z.string(),
163
+ country: z.string(),
164
+ zip: z.string(),
165
+ })
166
+
167
+ const orderSchema = z.object({
168
+ items: z.array(z.object({
169
+ productId: z.string().uuid(),
170
+ quantity: z.number().int().positive(),
171
+ })).min(1, 'At least one item required'),
172
+ shippingAddress: addressSchema,
173
+ billingAddress: addressSchema.optional(),
174
+ })
175
+ ```
176
+
177
+ ### Conditional Validation
178
+
179
+ ```typescript
180
+ const paymentSchema = z.discriminatedUnion('method', [
181
+ z.object({
182
+ method: z.literal('card'),
183
+ cardNumber: z.string().length(16),
184
+ cvv: z.string().length(3),
185
+ }),
186
+ z.object({
187
+ method: z.literal('paypal'),
188
+ paypalEmail: z.string().email(),
189
+ }),
190
+ z.object({
191
+ method: z.literal('bank'),
192
+ accountNumber: z.string(),
193
+ routingNumber: z.string(),
194
+ }),
195
+ ])
196
+ ```
197
+
198
+ ### Custom Refinements
199
+
200
+ ```typescript
201
+ const registrationSchema = z.object({
202
+ password: z.string().min(8),
203
+ confirmPassword: z.string(),
204
+ }).refine(data => data.password === data.confirmPassword, {
205
+ message: 'Passwords must match',
206
+ path: ['confirmPassword'],
207
+ })
208
+
209
+ const dateRangeSchema = z.object({
210
+ startDate: z.coerce.date(),
211
+ endDate: z.coerce.date(),
212
+ }).refine(data => data.endDate > data.startDate, {
213
+ message: 'End date must be after start date',
214
+ path: ['endDate'],
215
+ })
216
+ ```
217
+
218
+ ### Transform
219
+
220
+ ```typescript
221
+ const userInputSchema = z.object({
222
+ email: z.string().email().toLowerCase().trim(),
223
+ name: z.string().trim(),
224
+ tags: z.string().transform(s => s.split(',').map(t => t.trim())),
225
+ })
226
+ ```
227
+
228
+ ## Custom Error Handling
229
+
230
+ ### Custom Error Hook
231
+
232
+ ```typescript
233
+ import { zValidator } from '@hono/zod-validator'
234
+
235
+ const customValidator = <T extends z.ZodType>(
236
+ target: 'json' | 'query' | 'param' | 'header' | 'form',
237
+ schema: T
238
+ ) => {
239
+ return zValidator(target, schema, (result, c) => {
240
+ if (!result.success) {
241
+ const errors = result.error.issues.map(issue => ({
242
+ field: issue.path.join('.'),
243
+ message: issue.message,
244
+ }))
245
+
246
+ return c.json({
247
+ error: 'Validation failed',
248
+ details: errors,
249
+ }, 400)
250
+ }
251
+ })
252
+ }
253
+
254
+ // Usage
255
+ app.post('/users',
256
+ customValidator('json', createUserSchema),
257
+ async (c) => {
258
+ const data = c.req.valid('json')
259
+ return c.json(data)
260
+ }
261
+ )
262
+ ```
263
+
264
+ ### Validation Error Response Format
265
+
266
+ ```typescript
267
+ // Standard error format
268
+ {
269
+ "error": "Validation failed",
270
+ "details": [
271
+ { "field": "email", "message": "Invalid email address" },
272
+ { "field": "name", "message": "Name is required" }
273
+ ]
274
+ }
275
+ ```
276
+
277
+ ## Multiple Validators
278
+
279
+ Chain validators for different request parts:
280
+
281
+ ```typescript
282
+ app.put('/users/:id',
283
+ zValidator('param', userParamsSchema),
284
+ zValidator('json', updateUserSchema),
285
+ async (c) => {
286
+ const { id } = c.req.valid('param')
287
+ const data = c.req.valid('json')
288
+
289
+ return c.json({ id, ...data })
290
+ }
291
+ )
292
+ ```
293
+
294
+ ## Type Export Pattern
295
+
296
+ ```typescript
297
+ // validators/user.schema.ts
298
+ import { z } from 'zod'
299
+
300
+ export const createUserSchema = z.object({
301
+ email: z.string().email(),
302
+ name: z.string(),
303
+ })
304
+
305
+ export const updateUserSchema = createUserSchema.partial()
306
+
307
+ export const userParamsSchema = z.object({
308
+ id: z.string().uuid(),
309
+ })
310
+
311
+ export const userQuerySchema = z.object({
312
+ page: z.coerce.number().default(1),
313
+ limit: z.coerce.number().default(20),
314
+ })
315
+
316
+ // Export inferred types
317
+ export type CreateUser = z.infer<typeof createUserSchema>
318
+ export type UpdateUser = z.infer<typeof updateUserSchema>
319
+ export type UserParams = z.infer<typeof userParamsSchema>
320
+ export type UserQuery = z.infer<typeof userQuerySchema>
321
+ ```
322
+
323
+ ## Best Practices
324
+
325
+ 1. **Always use `zValidator`** for all request inputs
326
+ 2. **Use `z.coerce`** for query params (they're always strings)
327
+ 3. **Provide clear error messages** in schema definitions
328
+ 4. **Export inferred types** for use elsewhere
329
+ 5. **Create reusable field schemas** for common patterns
330
+ 6. **Use `.partial()`** for update schemas
331
+ 7. **Use `.refine()`** for cross-field validation
332
+ 8. **Set sensible defaults** with `.default()`