Custom Software Development

Introducing IsoValid: A Lightweight Isomorphic Data Validation Library

processor with isovalid written on it.
Isovalid architecture image
Isovalid architecture image

🚀 Why Data Validation Matters

Data validation is a crucial part of modern web applications, ensuring data integrity, security, and a smooth user experience. However, developers often struggle with:

  • Writing separate validation logic for frontend and backend
  • Managing multiple validation libraries across environments
  • Keeping validation consistent between client and server

Introducing IsoValid—a powerful, isomorphic validation library that allows you to use the same validation logic across both browser and Node.js environments.

🔥 What is IsoValid?

IsoValid is a lightweight, TypeScript-first validation library designed to unify validation across your entire application stack. Whether you're validating user input in a React form or ensuring API request integrity in an Express server, IsoValid makes it seamless.

🌟 Key Features

✅ True Isomorphic Support – The same validation code runs in both frontend and backend ✅ TypeScript-First – Fully typed API for strong type inference ✅ Minimal Bundle Size – No unnecessary dependencies or bloat ✅ Intuitive API – Developer-friendly, chainable syntax ✅ High Performance – Optimized validation with minimal overhead ✅ Extensible – Easily add custom validators and error messages

📦 Installation

Get started with IsoValid in seconds:

npm install isovalid

🔹 Core Architecture

IsoValid is built on a flexible, extensible architecture that includes:

Base Schema Class

  • Foundation for all validation schemas
  • Handles optional/nullable states
  • Common validation logic across types

Type-Specific Schemas

  • StringSchema – Length, regex, email, trimming, etc.
  • NumberSchema – Min/max, integer, positive/negative checks
  • More types coming soon (Boolean, Array, Object)

Validation Pipeline

  • Multi-stage validation process
  • Supports custom validation functions
  • Returns detailed error reporting

⚡ Usage Examples

String Validation

import { v } from 'isovalid';

const stringSchema = v.string() .min(2) // Minimum length .max(50) // Maximum length .email() // Must be a valid email .matches(/regex/) // Custom pattern .trimmed() // Remove extra whitespace .setOptional() // Allow undefined .setNullable(); // Allow null

Number Validation

const numberSchema = v.number() .min(0) // Minimum value .max(100) // Maximum value .integer() // Must be an integer .positive(); // Must be > 0

Validation Results

interface ValidationResult { valid: boolean; errors: Array<{ path: string[]; message: string; }>; }

🎯 Real-World Examples

1. React Form Validation

import { v } from 'isovalid'; import { useState, FormEvent } from 'react';

const userSchema = { username: v.string().min(3).max(20), email: v.string().email(), age: v.number().integer().min(18) };

function RegistrationForm() { const [formData, setFormData] = useState({ username: '', email: '', age: '' }); const [errors, setErrors] = useState<Record<string, string>>({});

const validateField = (field: keyof typeof userSchema, value: any) => { const result = userSchema[field].validate(value); return result.valid ? null : result.errors[0].message; };

const handleSubmit = (e: FormEvent) => { e.preventDefault(); const newErrors: Record<string, string> = {};

Object.entries(formData).forEach(([field, value]) => { const error = validateField(field as keyof typeof userSchema, value); if (error) newErrors[field] = error; });

if (Object.keys(newErrors).length === 0) { console.log('Submitting:', formData); } else { setErrors(newErrors); } };

return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Username" onChange={e => setFormData(prev => ({ ...prev, username: e.target.value }))} /> {errors.username && <span>{errors.username}</span>} <button type="submit">Register</button> </form> ); }

2. Express API Validation

import express from 'express'; import { v } from 'isovalid';

const app = express(); app.use(express.json());

const productSchema = { name: v.string().min(3).max(100), price: v.number().min(0), category: v.string().custom(value => ['electronics', 'books', 'clothing'].includes(value) ? null : 'Invalid category' ) };

app.post('/api/products', (req, res) => { const errors = Object.entries(productSchema) .map(([field, schema]) => ({ field, result: schema.validate(req.body[field]) })) .filter(({ result }) => !result.valid) .map(({ field, result }) => ({ field, message: result.errors[0].message }));

if (errors.length > 0) { return res.status(400).json({ errors }); }

res.status(201).json(req.body); });

🎯 Best Practices

✅ Schema Reuse – Define schemas once & share across frontend/backend ✅ Type Safety – Leverage TypeScript’s inference capabilities ✅ Performance Optimization – Cache schema instances for reuse ✅ Error Handling – Always check .valid before using data

🛠️ Roadmap

🚀 Upcoming Features:

-

📌 Get Started with IsoValid

IsoValid is open-source and welcomes contributions! Try it today and share your feedback.

🔗 NPM Package: IsoValid on NPM 🔗 GitHub Repository: GitHub Repo

Let’s make data validation simpler together! 🚀

Not sure what you need yet? That's the usual starting point.

Tell us the problem in your own words. We'll scope it with you and put the plan in writing, free, and yours to keep either way.

Start here