Validation
End-to-end type safety with Zod for requests and responses.
Validation
Bklar has first-class support for Zod. When you provide a schema, the framework automatically:
- Validates incoming data (Body, Query, or Params).
- Returns 400 Bad Request if validation fails.
- Infers Types for your handler, giving you full autocompletion.
Request Validation
Pass a schemas object in the route options:
import { z } from "zod";
const createUserSchema = z.object({
username: z.string().min(3),
email: z.string().email(),
age: z.number().int().optional(),
});
app.post("/users", (ctx) => {
// ctx.body is fully typed!
const { email, username } = ctx.body;
return ctx.json({ message: `Created user ${username}` });
}, {
schemas: { body: createUserSchema },
});Validating Query & Params
app.get("/search/:category", (ctx) => {
const { category } = ctx.params; // Typed
const { q, limit } = ctx.query; // Typed
return ctx.json({ category, q, limit });
}, {
schemas: {
params: z.object({
category: z.enum(["books", "movies"]),
}),
query: z.object({
q: z.string(),
limit: z.coerce.number().min(1).max(100).default(10),
}),
},
});Response Validation
Bklar also supports response schema validation by status code. Use the responses option:
const userSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
});
app.get("/users/:id", (ctx) => {
return { id: 1, name: "Alice", email: "alice@example.com" };
}, {
responses: { 200: userSchema },
});If the response doesn't match the schema, a warning is logged in development. This catches implementation bugs without breaking the response flow — the client still receives the data.
Response validation is non-blocking
Response validation warns on mismatches but doesn't reject the response. This prevents exposing validation internals to clients while still catching bugs during development.
Note on Coercion
URL parameters and Query strings are strictly strings by default. Use
z.coerce.number() or z.coerce.boolean() to automatically convert them to
the correct type.