npx skills add open-circle/agent-skills --skill valibot
mgd34msu/goodvibes-gemini
valibot
Validates data with Valibot's modular, tree-shakable schema library for minimal bundle size. Use when bundle size matters, building form validation, or needing lightweight TypeScript validation.
Installation
npx skills add mgd34msu/goodvibes-gemini --skill valibot
Similar popular skills
Related neighbors and high-traction skills in the same topics — useful to compare before installing.
Guidance for distinctive, intentional visual design when building new UI or reshaping an existi…
866.4K installsBrowser automation CLI for AI agents. Use when the user needs to interact with websites, includ…
810.4K installsReview UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "chec…
617.3K installsBuild, deploy, evaluate, optimize, fine-tune, and manage Microsoft Foundry agents, models, and …
576.5K installsDebug Azure production issues on Azure using AppLens, Azure Monitor, resource health, and safe …
568.9K installsAlso in this package
Other skills from mgd34msu/goodvibes-gemini · top by installs.
npx skills add mgd34msu/goodvibes-gemini
More details
Agent compatibility
Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.
Also listed on
Alternate registries and mirrors of this skill.
Repository health
main
Package contents
Files included with this skill beyond the listing page.
-
skill md
SKILL.md7,558 B -
docs
SUMMARY.md209 B
History
- First seen on skills.sh
- First recorded snapshot · 3 installs
SKILL.md
Valibot
Modular schema validation library with best-in-class bundle size (~1KB for basic forms).
Quick Start
npm install valibot
import * as v from 'valibot';
const schema = v.object({
name: v.pipe(v.string(), v.minLength(2)),
email: v.pipe(v.string(), v.email()),
age: v.pipe(v.number(), v.minValue(0)),
});
// Validate
const result = v.safeParse(schema, data);
if (result.success) {
console.log(result.output);
} else {
console.log(result.issues);
}
Schema Types
Primitives
import * as v from 'valibot';
// String
v.string()
v.pipe(v.string(), v.minLength(1), v.maxLength(100))
// Number
v.number()
v.pipe(v.number(), v.minValue(0), v.maxValue(100))
// Boolean
v.boolean()
// Null/Undefined
v.null_()
v.undefined_()
// BigInt
v.bigint()
// Symbol
v.symbol()
// Date
v.date()
v.pipe(v.date(), v.minValue(new Date()))
String Validations
v.pipe(
v.string(),
v.minLength(1, 'Required'),
v.maxLength(100, 'Too long'),
v.email('Invalid email'),
v.url('Invalid URL'),
v.uuid('Invalid UUID'),
v.regex(/^[a-z]+$/, 'Only lowercase'),
v.startsWith('https://'),
v.endsWith('.com'),
v.includes('@'),
v.trim(),
v.toLowerCase(),
v.toUpperCase(),
)
Number Validations
v.pipe(
v.number(),
v.minValue(0, 'Must be positive'),
v.maxValue(100, 'Max 100'),
v.integer('Must be integer'),
v.multipleOf(5, 'Must be multiple of 5'),
v.finite('Must be finite'),
v.safeInteger('Must be safe integer'),
)
Object
const userSchema = v.object({
name: v.string(),
email: v.pipe(v.string(), v.email()),
age: v.optional(v.number()),
});
// Strict (no extra keys)
const strictSchema = v.strictObject({
id: v.number(),
name: v.string(),
});
// Loose (allow extra keys)
const looseSchema = v.looseObject({
id: v.number(),
});
Array
v.array(v.string())
v.pipe(
v.array(v.string()),
v.minLength(1, 'At least one item'),
v.maxLength(10, 'Max 10 items'),
)
// Tuple
v.tuple([v.string(), v.number()])
Union & Intersection
// Union (OR)
const statusSchema = v.union([
v.literal('active'),
v.literal('inactive'),
v.literal('pending'),
]);
// Variant (discriminated union)
const eventSchema = v.variant('type', [
v.object({ type: v.literal('click'), x: v.number(), y: v.number() }),
v.object({ type: v.literal('scroll'), offset: v.number() }),
]);
// Intersection (AND)
const combined = v.intersect([
v.object({ id: v.number() }),
v.object({ name: v.string() }),
]);
Optional & Nullable
// Optional (undefined allowed)
v.optional(v.string())
// Nullable (null allowed)
v.nullable(v.string())
// Nullish (null or undefined)
v.nullish(v.string())
// With default
v.optional(v.string(), 'default value')
v.nullable(v.number(), 0)
Pipe System
Valibot uses pipe() to chain validations and transformations:
const schema = v.pipe(
v.string(),
v.trim(), // Transform
v.minLength(1), // Validate
v.toLowerCase(), // Transform
v.email(), // Validate
);
// Order matters!
const result = v.parse(schema, ' [email protected] ');
// Output: '[email protected]'
Validation
parse() - Throws on Error
try {
const data = v.parse(schema, input);
} catch (error) {
if (error instanceof v.ValiError) {
console.log(error.issues);
}
}
safeParse() - Returns Result
const result = v.safeParse(schema, input);
if (result.success) {
console.log(result.output);
} else {
console.log(result.issues);
}
is() - Type Guard
if (v.is(schema, input)) {
// input is typed
}
Type Inference
import * as v from 'valibot';
const userSchema = v.object({
id: v.number(),
name: v.string(),
email: v.pipe(v.string(), v.email()),
roles: v.array(v.string()),
});
// Infer TypeScript type
type User = v.InferOutput<typeof userSchema>;
// { id: number; name: string; email: string; roles: string[] }
// Infer input type (before transforms)
type UserInput = v.InferInput<typeof userSchema>;
Custom Validation
check() - Custom Predicate
const schema = v.pipe(
v.string(),
v.check((value) => value.includes('@'), 'Must contain @'),
);
transform() - Custom Transform
const schema = v.pipe(
v.string(),
v.transform((value) => value.split(',').map((s) => s.trim())),
);
Custom Schema
const passwordSchema = v.pipe(
v.string(),
v.minLength(8, 'At least 8 characters'),
v.regex(/[A-Z]/, 'Need uppercase'),
v.regex(/[a-z]/, 'Need lowercase'),
v.regex(/[0-9]/, 'Need number'),
);
Common Patterns
User Registration
const registrationSchema = v.object({
email: v.pipe(
v.string(),
v.email('Invalid email'),
),
password: v.pipe(
v.string(),
v.minLength(8, 'At least 8 characters'),
v.regex(/[A-Z]/, 'Need uppercase'),
v.regex(/[0-9]/, 'Need number'),
),
confirmPassword: v.string(),
age: v.pipe(
v.number(),
v.minValue(18, 'Must be 18+'),
),
terms: v.pipe(
v.boolean(),
v.value(true, 'Must accept terms'),
),
});
// Add cross-field validation
const fullSchema = v.pipe(
registrationSchema,
v.forward(
v.partialCheck(
[['password'], ['confirmPassword']],
(input) => input.password === input.confirmPassword,
'Passwords must match',
),
['confirmPassword'],
),
);
API Response
const apiResponseSchema = v.object({
success: v.boolean(),
data: v.optional(v.object({
users: v.array(v.object({
id: v.number(),
name: v.string(),
})),
})),
error: v.optional(v.string()),
});
Environment Variables
const envSchema = v.object({
NODE_ENV: v.picklist(['development', 'production', 'test']),
PORT: v.pipe(v.string(), v.transform(Number), v.integer()),
DATABASE_URL: v.pipe(v.string(), v.url()),
API_KEY: v.pipe(v.string(), v.minLength(32)),
});
const env = v.parse(envSchema, process.env);
React Hook Form Integration
import { useForm } from 'react-hook-form';
import { valibotResolver } from '@hookform/resolvers/valibot';
import * as v from 'valibot';
const schema = v.object({
email: v.pipe(v.string(), v.email()),
password: v.pipe(v.string(), v.minLength(8)),
});
type FormData = v.InferOutput<typeof schema>;
function Form() {
const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
resolver: valibotResolver(schema),
});
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('email')} />
{errors.email && <span>{errors.email.message}</span>}
<input {...register('password')} type="password" />
{errors.password && <span>{errors.password.message}</span>}
<button type="submit">Submit</button>
</form>
);
}
Bundle Size Comparison
| Library | Basic Form |
|---|---|
| Valibot | ~1.4 KB |
| Zod | ~12 KB |
| Yup | ~15 KB |
Valibot achieves this through modular imports - only used functions are bundled.
See [references/methods.md](references/methods.md) for complete method reference.