Zod is great but ships 57KB to your users' browsers. Valibot does the same thing at under 1KB — up to 98% smaller bundle size with the same developer experience.
What Is Valibot?
Valibot is a TypeScript-first schema validation library. It uses a modular, tree-shakeable architecture that means you only ship the validators you actually use.
Bundle Size Comparison
| Library | Bundle Size | Tree-Shakeable |
|---|---|---|
| Valibot | ~0.5-1KB | Yes (modular) |
| Zod | ~57KB | No (monolithic) |
| Yup | ~40KB | Partial |
| Joi | ~150KB | No |
Quick Start
npm install valibot
import * as v from 'valibot';
const UserSchema = v.object({
name: v.pipe(v.string(), v.minLength(2), v.maxLength(100)),
email: v.pipe(v.string(), v.email()),
age: v.pipe(v.number(), v.minValue(0), v.maxValue(150)),
role: v.picklist(['admin', 'user', 'moderator']),
});
type User = v.InferOutput<typeof UserSchema>;
// { name: string; email: string; age: number; role: 'admin' | 'user' | 'moderator' }
// Validate
const result = v.safeParse(UserSchema, inputData);
if (result.success) {
console.log(result.output); // Typed as User
} else {
console.log(result.issues); // Detailed error messages
}
Common Patterns
API Response Validation
const ApiResponseSchema = v.object({
data: v.array(v.object({
id: v.number(),
title: v.string(),
tags: v.array(v.string()),
metadata: v.optional(v.record(v.string(), v.unknown())),
})),
pagination: v.object({
page: v.number(),
totalPages: v.number(),
hasNext: v.boolean(),
}),
});
const response = await fetch('/api/articles');
const json = await response.json();
const { output } = v.parse(ApiResponseSchema, json);
// output is fully typed
Form Validation
const LoginSchema = v.object({
email: v.pipe(
v.string(),
v.email('Please enter a valid email'),
),
password: v.pipe(
v.string(),
v.minLength(8, 'Password must be at least 8 characters'),
v.regex(/[A-Z]/, 'Must contain uppercase letter'),
v.regex(/[0-9]/, 'Must contain a number'),
),
});
// With React Hook Form
const form = useForm({
resolver: valibotResolver(LoginSchema),
});
Environment Variables
const EnvSchema = v.object({
DATABASE_URL: v.pipe(v.string(), v.url()),
API_KEY: v.pipe(v.string(), v.minLength(32)),
PORT: v.pipe(v.string(), v.transform(Number), v.number()),
NODE_ENV: v.picklist(['development', 'production', 'test']),
});
const env = v.parse(EnvSchema, process.env);
Why Valibot Over Zod
The API is nearly identical — switching is straightforward:
// Zod
const schema = z.object({
name: z.string().min(2).max(100),
email: z.string().email(),
});
// Valibot — same logic, 98% smaller
const schema = v.object({
name: v.pipe(v.string(), v.minLength(2), v.maxLength(100)),
email: v.pipe(v.string(), v.email()),
});
Framework Integration
-
React Hook Form —
@hookform/resolvers -
SvelteKit —
sveltekit-superforms - Nuxt — direct integration
- tRPC — input validation
- Hono — request validation middleware
Get Started
- Documentation
- GitHub — 7K+ stars
- Migration from Zod
Validating scraped data? My Apify actors extract clean, structured data — combine with Valibot for bulletproof pipelines. Custom solutions: spinov001@gmail.com
Top comments (0)