Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
{"entry_point":{"summary":"End-to-end type-safe API client with automatic TypeScript inference from server routes","when_to_use":"Building full-stack TypeScript apps where client needs type-safe API access","quick_start":"1. Export AppType from server 2. Import hc client 3. Use typed client methods"},"references":[]}
context_limit
800
Hono RPC - Type-Safe Client
Overview
Hono RPC enables sharing API specifications between server and client through TypeScript's type system. Export your server's type, and the client automatically knows all routes, request shapes, and response types - no code generation required.
Key Features:
Zero-codegen type-safe client
Automatic TypeScript inference
Works with Zod validators
Status code-aware response types
Supports path params, query, headers
When to Use This Skill
Use Hono RPC when:
Building full-stack TypeScript applications
Need type-safe API consumption without OpenAPI/codegen
Want compile-time validation of API calls
Sharing types between client and server in monorepos
constgetClient = (token: string) =>
hc<AppType>('http://localhost:3000', {
headers: () => ({
'Authorization': `Bearer ${token}`
})
})
// Or with a function that returns headersconst client = hc<AppType>('http://localhost:3000', {
headers: () => {
const token = getAuthToken()
return token ? { 'Authorization': `Bearer ${token}` } : {}
}
})
Best Practices
1. Enable Strict Mode
// tsconfig.json{"compilerOptions":{"strict":true// Required for proper type inference!}}
2. Use Explicit Status Codes
// CORRECT: Explicit status enables type discriminationreturn c.json({ data }, 200)
return c.json({ error: 'Not found' }, 404)
// AVOID: c.notFound() doesn't work well with RPCreturn c.notFound() // Response type is not properly inferred
3. Split Large Apps
// For large apps, split routes to reduce IDE overheadconst v1 = newHono()
.route('/users', usersRoute)
.route('/posts', postsRoute)
const v2 = newHono()
.route('/users', usersV2Route)
// Export separate typesexporttype V1Type = typeof v1
exporttype V2Type = typeof v2
4. Consistent Response Shapes
// Define standard response wrappertypeApiSuccess<T> = { ok: true; data: T }
typeApiError = { ok: false; error: string; code?: string }
typeApiResponse<T> = ApiSuccess<T> | ApiError// Use consistentlyconst route = app.get('/users/:id', async (c) => {
const user = awaitfindUser(c.req.param('id'))
if (!user) {
return c.json({ ok: false, error: 'User not found' } asApiError, 404)
}
return c.json({ ok: true, data: user } asApiSuccess<User>, 200)
})