valibot
Schema validation with Valibot, the modular and type-safe schema library. Use when the user needs to validate data, create schemas, parse inputs, or work with Valibot in their project. Also use when migrating from Zod to Valibot.
What this skill does
# Valibot
This skill helps you work effectively with [Valibot](https://valibot.dev), the modular and type-safe schema library for validating structural data.
## When to use this skill
- When the user asks about schema validation with Valibot
- When creating or modifying Valibot schemas
- When parsing or validating user input
- When the user mentions Valibot, schema, or validation
- When migrating from Zod to Valibot
## CRITICAL: Valibot vs Zod — Do Not Confuse!
**Valibot and Zod have different APIs. Never mix them up!**
### Key Differences
| Feature | Zod ❌ | Valibot ✅ |
| ------------------- | ------------------------------------- | --------------------------------------------------------- |
| Import | `import { z } from 'zod'` | `import * as v from 'valibot'` |
| Validations | Chained methods: `.email().min(5)` | Pipeline: `v.pipe(v.string(), v.email(), v.minLength(5))` |
| Parsing | `schema.parse(data)` | `v.parse(schema, data)` |
| Safe parsing | `schema.safeParse(data)` | `v.safeParse(schema, data)` |
| Optional | `z.string().optional()` | `v.optional(v.string())` |
| Nullable | `z.string().nullable()` | `v.nullable(v.string())` |
| Default | `z.string().default('x')` | `v.optional(v.string(), 'x')` |
| Transform | `z.string().transform(fn)` | `v.pipe(v.string(), v.transform(fn))` |
| Refine/Check | `z.string().refine(fn)` | `v.pipe(v.string(), v.check(fn))` |
| Enum | `z.enum(['a', 'b'])` | `v.picklist(['a', 'b'])` |
| Native enum | `z.nativeEnum(MyEnum)` | `v.enum(MyEnum)` |
| Union | `z.union([a, b])` | `v.union([a, b])` |
| Discriminated union | `z.discriminatedUnion('type', [...])` | `v.variant('type', [...])` |
| Intersection | `z.intersection(a, b)` | `v.intersect([a, b])` |
| Min/max length | `.min(5).max(10)` | `v.minLength(5), v.maxLength(10)` |
| Min/max value | `.gte(5).lte(10)` | `v.minValue(5), v.maxValue(10)` |
| Infer type | `z.infer<typeof Schema>` | `v.InferOutput<typeof Schema>` |
| Infer input | `z.input<typeof Schema>` | `v.InferInput<typeof Schema>` |
### Common Mistakes to Avoid
```typescript
// ❌ WRONG - This is Zod syntax, NOT Valibot!
const Schema = v.string().email().min(5);
const result = Schema.parse(data);
// ✅ CORRECT - Valibot uses functions and pipelines
const Schema = v.pipe(v.string(), v.email(), v.minLength(5));
const result = v.parse(Schema, data);
```
```typescript
// ❌ WRONG - Zod-style optional
const Schema = v.object({
name: v.string().optional(),
});
// ✅ CORRECT - Valibot wraps with optional()
const Schema = v.object({
name: v.optional(v.string()),
});
```
```typescript
// ❌ WRONG - Zod-style default
const Schema = v.string().default("hello");
// ✅ CORRECT - Valibot uses second argument
const Schema = v.optional(v.string(), "hello");
```
## Installation
```bash
npm install valibot # npm
yarn add valibot # yarn
pnpm add valibot # pnpm
bun add valibot # bun
```
Import with a wildcard (recommended):
```typescript
import * as v from "valibot";
```
Or with individual imports:
```typescript
import { object, string, pipe, email, parse } from "valibot";
```
## Mental Model
Valibot's API is divided into three main concepts:
### 1. Schemas
Schemas define the expected data type. They are the starting point.
```typescript
import * as v from "valibot";
// Primitive schemas
const StringSchema = v.string();
const NumberSchema = v.number();
const BooleanSchema = v.boolean();
const DateSchema = v.date();
// Complex schemas
const ArraySchema = v.array(v.string());
const ObjectSchema = v.object({
name: v.string(),
age: v.number(),
});
```
### 2. Methods
Methods help you use or modify schemas. The schema is always the first argument.
```typescript
// Parsing
const result = v.parse(StringSchema, "hello");
const safeResult = v.safeParse(StringSchema, "hello");
// Type guard
if (v.is(StringSchema, data)) {
// data is typed as string
}
```
### 3. Actions
Actions validate or transform data within a `pipe()`. They MUST be used inside pipelines.
```typescript
// Actions are used in pipe()
const EmailSchema = v.pipe(
v.string(),
v.trim(),
v.email(),
v.endsWith("@example.com"),
);
```
## Pipelines
Pipelines extend schemas with validation and transformation actions. A pipeline always starts with a schema, followed by actions.
```typescript
import * as v from "valibot";
const UsernameSchema = v.pipe(
v.string(),
v.trim(),
v.minLength(3, "Username must be at least 3 characters"),
v.maxLength(20, "Username must be at most 20 characters"),
v.regex(
/^[a-z0-9_]+$/i,
"Username can only contain letters, numbers, and underscores",
),
);
const AgeSchema = v.pipe(
v.number(),
v.integer("Age must be a whole number"),
v.minValue(0, "Age cannot be negative"),
v.maxValue(150, "Age cannot exceed 150"),
);
```
### Common Validation Actions
**String validations:**
- `v.email()` — Valid email format
- `v.url()` — Valid URL format
- `v.uuid()` — Valid UUID format
- `v.regex(pattern)` — Match regex pattern
- `v.minLength(n)` — Minimum length
- `v.maxLength(n)` — Maximum length
- `v.length(n)` — Exact length
- `v.nonEmpty()` — Not empty string
- `v.startsWith(str)` — Starts with string
- `v.endsWith(str)` — Ends with string
- `v.includes(str)` — Contains string
**Number validations:**
- `v.minValue(n)` — Minimum value (>=)
- `v.maxValue(n)` — Maximum value (<=)
- `v.gtValue(n)` — Greater than (>)
- `v.ltValue(n)` — Less than (<)
- `v.integer()` — Must be integer
- `v.finite()` — Must be finite
- `v.safeInteger()` — Safe integer range
- `v.multipleOf(n)` — Must be multiple of n
**Array validations:**
- `v.minLength(n)` — Minimum items
- `v.maxLength(n)` — Maximum items
- `v.length(n)` — Exact item count
- `v.nonEmpty()` — At least one item
- `v.includes(item)` — Contains item
- `v.excludes(item)` — Does not contain item
### Custom Validation with check()
```typescript
const PasswordSchema = v.pipe(
v.string(),
v.minLength(8),
v.check(
(input) => /[A-Z]/.test(input),
"Password must contain an uppercase letter",
),
v.check((input) => /[0-9]/.test(input), "Password must contain a number"),
);
```
### Value Transformations
These actions modify the value without changing its type:
**String transformations:**
- `v.trim()` — Remove leading/trailing whitespace
- `v.trimStart()` — Remove leading whitespace
- `v.trimEnd()` — Remove trailing whitespace
- `v.toLowerCase()` — Convert to lowercase
- `v.toUpperCase()` — Convert to uppercase
**Number transformations:**
- `v.toMinValue(n)` — Clamp to minimum value (if less than n, set to n)
- `v.toMaxValue(n)` — Clamp to maximum value (if greater than n, set to n)
```typescript
const NormalizedEmailSchema = v.pipe(
v.string(),
v.trim(),
v.toLowerCase(),
v.email(),
);
// Clamp number to range 0-100
const PercentageSchema = v.pipe(v.number(), v.toMinValue(0), v.toMaxValue(100));
```
### Type Transformations
For converting between data types, use these built-in transformation Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.