Standard Schema Support
Semola uses the Standard Schema specification, which provides a unified interface for validation libraries. This means you can use your preferred validation library:- Zod - Most popular, TypeScript-first
- Valibot - Modular and lightweight
- ArkType - Fast with great type inference
- Any other Standard Schema v1 compatible library
Request Validation
All request fields are validated before reaching your handler. If validation fails, the API returns a 400 Bad Request with detailed error messages.Validation Fields
body: JSON request body (validates Content-Type)params: Path parameters (e.g.,/users/:id)query: Query string (supports arrays like?tags=a&tags=b)headers: HTTP headerscookies: Parsed from Cookie header
Basic Example
Body Validation
Validates JSON request bodies:- Content-Type must be
application/json - Body must be valid JSON
- Data must match the schema
Query String Validation
Validates URL query parameters:- Supports array values (e.g.,
?tags=a&tags=bbecomes["a", "b"]) - Use
z.coerce.number()to parse string values as numbers - All query values are initially strings
Path Parameters
Validates dynamic path segments:Headers Validation
Validates HTTP headers:Cookies Validation
Validates cookies using Bun’s nativeCookieMap:
Response Validation
When output validation is enabled (the default), the response produced by your handler is validated against theresponse schema you define on the route.
Basic Response Validation
Validation Behavior
- Output validation only runs when a
responseschema is defined - Routes without a
responseschema are unaffected - If validation fails, the framework returns 400 Bad Request with error details
- This catches bugs where your handler returns data that doesn’t match the declared contract
Validation Configuration
You can control input and output validation independently via thevalidation option on the Api constructor.
Configuration Options
| Value | Input validation | Output validation |
|---|---|---|
true (default) | ✅ | ✅ |
false | ❌ | ❌ |
{ input: true, output: true } | ✅ | ✅ |
{ input: false } | ❌ | ✅ |
{ output: false } | ✅ | ❌ |
Default (All Validation Enabled)
Disable All Validation
Useful for performance-critical internal services:Disable Only Input Validation
Disable Only Output Validation
Per-Environment Configuration
Validation with Different Libraries
Zod (Recommended)
Valibot
ArkType
Error Handling
Validation Error Response
When validation fails, Semola returns a 400 Bad Request with error details:- Field path (e.g.,
name,query.page,headers.authorization) - Validation error message from the schema library
Custom Error Messages
Use your validation library’s features to customize error messages: With Zod:Body Caching
Semola implements body caching to prevent re-parsing JSON when multiple middlewares validate the same body:Best Practices
- Use specific validation rules - Don’t just validate types, add constraints (min/max, regex, etc.)
- Validate early - Let validation catch errors before expensive operations
- Provide clear error messages - Help users understand what went wrong
- Use
.optional()judiciously - Make fields required unless there’s a good reason - Coerce query/param types - Use
z.coerce.number()for numeric query parameters - Disable validation selectively - Only disable validation when you have a specific performance need
- Keep output validation enabled in development - Catches bugs where handlers return incorrect data
- Use Standard Schema - Benefits from improved type inference and library flexibility