valibot
Tiny, tree-shakeable schema validation library — a Zod alternative that won't bloat your bundle.
valibot
General JSTiny, tree-shakeable schema validation library — a Zod alternative that won't bloat your bundle.
Fit
Bundle (gzip)
14.7 kB
85.5 kB raw
Install size includes transitive dependencies. Bundle size is gzipped browser payload.
Freshness
The Problem
Zod is the dominant schema validation library in the TypeScript ecosystem — but it has a significant downside: it's not tree-shakeable. The entire Zod runtime (~14KB gzipped) is included in your bundle whether you use 3 validators or 30.
For client-side apps, Edge Functions, or Lambda functions where bundle size matters, this is a real cost. And for teams using React Hook Form or tRPC, the validation library ends up in the critical path for page load.
What It Does
Valibot provides the same schema validation capabilities as Zod — objects, strings, numbers, arrays, enums, transforms, refinements — but with a module-based architecture that's fully tree-shakeable. Only the validators you import are included in your bundle. A minimal schema can be under 1KB gzipped. It also has nearly 1 million weekly npm downloads.
Installation
npm install valibotUsage Example
Basic schema validation
import * as v from "valibot";
const UserSchema = v.object({
name: v.pipe(v.string(), v.minLength(2), v.maxLength(50)),
email: v.pipe(v.string(), v.email()),
age: v.pipe(v.number(), v.minValue(0), v.maxValue(120)),
role: v.picklist(["admin", "user", "guest"]),
});
type User = v.InferOutput<typeof UserSchema>;
const result = v.safeParse(UserSchema, {
name: "Sarah",
email: "sarah@example.com",
age: 28,
role: "admin",
});
if (result.success) {
console.log(result.output); // Typed as User
} else {
console.log(result.issues); // Detailed validation errors
}Form validation with React Hook Form
import { useForm } from "react-hook-form";
import { valibotResolver } from "@hookform/resolvers/valibot";
import * as v from "valibot";
const SignupSchema = v.object({
email: v.pipe(v.string(), v.email("Enter a valid email")),
password: v.pipe(v.string(), v.minLength(8, "Password must be at least 8 characters")),
});
type SignupForm = v.InferOutput<typeof SignupSchema>;
export function SignupForm() {
const { register, handleSubmit, formState: { errors } } = useForm<SignupForm>({
resolver: valibotResolver(SignupSchema),
});
return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<input {...register("email")} />
{errors.email && <p>{errors.email.message}</p>}
<input type="password" {...register("password")} />
{errors.password && <p>{errors.password.message}</p>}
<button type="submit">Sign up</button>
</form>
);
}API input validation (Next.js route handler)
import * as v from "valibot";
const CreatePostSchema = v.object({
title: v.pipe(v.string(), v.minLength(1), v.maxLength(200)),
content: v.pipe(v.string(), v.minLength(1)),
tags: v.array(v.string()),
});
export async function POST(request: Request) {
const body = await request.json();
const result = v.safeParse(CreatePostSchema, body);
if (!result.success) {
return Response.json({ errors: result.issues }, { status: 400 });
}
// result.output is fully typed
const post = await createPost(result.output);
return Response.json(post);
}Related packages
Unified TypeScript SDK for building AI-powered apps — switch between 20+ LLM providers without rewriting code.
animejsGeneral JSLightweight JavaScript animation library with a tiny footprint and a powerful, expressive API.
AOSGeneral JSAn easy-to-use library that makes elements fade, slide, or zoom into view as the user scrolls down your page.
archiverGeneral JSStreaming interface for generating ZIP and TAR archives in Node.js — create compressed archives programmatically from files, directories, and buffers.
@formkit/auto-animateGeneral JS> Add smooth transitions to any element with a single line — zero-config animations for adds, removes, and moves.