After months of wrestling with forms across multiple projects, my team and I decided enough was enough. Today, I'm excited to share Veli - our first open-source project that reimagines how developers handle form validation.
The Problem We Kept Running Into
Picture this: You're building a web application that needs user registration, contact forms, and data entry screens. The typical workflow looks something like:
- Install React Hook Form (or Formik)
- Add Yup or Zod for validation
- Write CSS or install a UI library for styling
- Copy-paste your validation rules to the backend
- Add security checks manually
- Realize your phone validation doesn't support African numbers
- Fix bugs in both frontend AND backend
Sound familiar? We were tired of this dance.
What We Built Instead
Veli is a full-stack form validation library that handles everything from a single source of truth. Here's what makes it different:
π― True Full-Stack Validation
Write your rules once, use them everywhere:
- Frontend (HTML attributes - no JS required!)
<form id="myForm" data-veli-design="classic">
<div class="veli-field-wrapper">
<label>Name</label>
<input
type="text"
name="username"
data-veli-rules='{"type":"text", "name":"username", "minChar":"3", "required":"true"}'
/>
<span class="veli-error"></span>
</div>
<button type="submit">Submit</button>
</form>
- Backend (Node js, express etc...)
const schema = [
{
value: "user@example.com",
rules: {type: "email", name: "email", provider: "gmail"},
},
{
value: "password123",
rules: {
type: "password",
name: "password",
minLen: "8@@Password too short", //if password is not 8, show error `Password too short(this is custom error and it overides the default color)`
},
},
];
const result = validate(schema)
No duplication. No sync issues. One schema, everywhere.
π Security Built-In
Veli includes a security scanner that checks for common vulnerabilities:
- XSS (Cross-Site Scripting)
- SQL Injection
- NoSQL Injection
- Path Traversal
- Token Leakage
const scanner = new Scanner({strictMode: true});
//scan any form of thread (xss, sql injection etc....)
const result = scanner.scanAll([
{name: "email", value: "user@example.com", type: "email"},
{
name: "comment",
value: "<script>alert(1)</script>",
type: "html",
allowedTags: ["p"],
},
]);
//scan only sql injection
const result2 = scanner.scan([
{name: "email", value: "user@example.com", type: "email"},
{
name: "comment",
value: "<script>alert(1)</script>",
type: "html",
allowedTags: ["p"],
},
], 'sqlInjection');
π Africa-First Phone Validation
We built proper phone number validation for 26 African countries, including:
- cameroon
- ghana
- nigeria
- southafrica
- uganda
- zimbabwe
- kenya
- tanzania
- egypt
- algeria
- morocco
- ivorycoast
- ethiopia
- angola
- senegal
- zambia
- malawi
- rwanda
- botswana
- namibia
<div class="veli-field-wrapper">
<label>Phone</label>
<input
type="tel"
name="phone"
data-veli-rules='{"type":"tel","name":"phone","country":"cameroon"}' //accepts only phone numbers from cameroon
placeholder="237679587645"
/>
<span class="veli-error"></span>
</div>
No more regex nightmares for international phone formats.
π¨ Beautiful UI Out of the Box
Three pre-built themes included:
- Classic
<form data-veli-design="classic">
<!-- fields -->
</form>
<!-- field structure -->
<div class="veli-field-wrapper">
<label>Field Label</label>
<input type="text" name="fieldname" data-veli-rules="..." />
<span class="veli-error"></span>
</div>
- Floating Labels
<form data-veli-design="floating-label">
<!-- fields -->
</form>
<!-- field structure -->
<div class="veli-field-wrapper">
<input type="text" name="fieldname" placeholder=" " data-veli-rules="..." />
<label>Field Label</label>
<span class="veli-error"></span>
</div>
- Ifta Label(IOS inspired)
<form data-veli-design="ifta-label">
<!-- fields -->
</form>
<!-- field structure -->
<fieldset class="veli-field-wrapper">
<legend>Field Label</legend>
<input type="text" name="fieldname" data-veli-rules="..." />
<span class="veli-error"></span>
</fieldset>
You can contumise input colors by adding the following anywhere in your code
import {VeliConfig} from "@gd3v/veli";
VeliConfig({
colors: {
error: "#d32f2f",
success: "#388e3c",
warning: "#f57c00",
info: "#1976d2",
},
});
Complete Example
<body>
<div id="container">
<form id="contactForm" data-veli-design="floating-label" data-veli-lang="en">
<h1>Contact Us</h1>
<div class="veli-field-wrapper">
<input type="text" name="fieldname" placeholder=" " data-veli-rules='{"type":"text","name":"fullname","minChar":"2"}' />
<label>Field Label</label>
<span class="veli-error"></span>
</div>
<div class="veli-field-wrapper">
<input type="email" name="email" placeholder=" " data-veli-rules='{"type":"email","name":"email", "provider":"gmail"}' />
<label>Email</label>
<span class="veli-error"></span>
</div>
<div class="veli-field-wrapper">
<input type="tel" name="phone" placeholder=" " data-veli-rules='{"type":"tel","name":"phone","country":"cameroon"}' />
<label>Phone</label>
<span class="veli-error"></span>
</div>
<button type="submit">Submit</button>
</form>
</div>
<script type="module" src="https://cdn.jsdelivr.net/npm/@gd3v/veli@latest/dist/veli.js">
//getting validation response
const form = document.getElementById('contactForm');
form.addEventListener('onCompleteValidation', () => {
const result = validationResponse.contactForm;
console.log(result); // { status: true/false, values: {...}}
});
</script>
</body>
Developer Experience Features
Veli comes with a React hooks-like API and Watcher that feels familiar:
- isDirty() β boolean
- isValid() β boolean
- getCurrentValues() β object
- getDirtyFields() β object
- reset() β void
- on(event, callback) β unsubscribe function
- off(event, callback) β void
Technical Details
- Zero dependencies - No bloat
- Framework agnostic - Works with React, Vue, Svelte, vanilla JS, Node.js
- TypeScript support - Full type inference
- 35KB gzipped - Smaller than most validation libraries alone
- Tree-shakeable - Only bundle what you use
What We Learned
Building Veli taught us invaluable lessons:
- Building for real-world use cases - We used our own pain points as a guide
- API design matters - Spent weeks iterating on the developer experience
- Documentation is crucial - Built a live editor so devs can try before installing
- Shipping beats perfection - We launched with v1.0 despite wanting to add more features
- Community matters - Early feedback shaped the direction significantly
Try It Out
π Documentation & Live Editor: https://veli.gd3v.com
π» GitHub: https://github.com/gd3v-cameroon/veli
We Need Your Feedback
This is our first open-source project, and honestly, it's nerve-wracking to put it out there. But Veli is already solving real problems for our team at Eschuul, and we believe it can help yours too.
If you:
- Work with forms regularly
- Are tired of duplicating validation logic
- Need better security out of the box
- Want proper African phone number support
- Value developer experience
Give Veli a try and let us know what you think!
If you find it useful, a β on GitHub would mean the world to us.
What's Next?
We have big plans:
- More African country support
- Integration with popular frameworks (Next.js, Nuxt, SvelteKit)
- Visual form builder
- Advanced field types (file uploads, date ranges, etc.)
- i18n support for error messages
This is just the beginning. Join us on this journey!
Questions? Feedback? Feature requests? Drop them in the comments below or open an issue on GitHub. We'd love to hear from you!
Built with β€οΈ by the GD3V team

Top comments (0)