Three layers
1
Schema validators (Convex)
v.string(), v.number(), v.union(...) — enforced at the database level. Bad shapes are rejected before your handler runs.2
Business rules (in mutations)
“Email must be lowercase”, “Quantity must be ≥ 1”, “Future date for due-by”. Throw with a clear message.
3
Sanitization (for user-provided HTML / markdown)
Use DOMPurify or a markdown renderer with safe defaults. Don’t render
dangerouslySetInnerHTML on raw user input.In a Convex mutation
Client-side validation
Use react-hook-form + zod for client-side. The samezod schema can be used to validate before submission and to type the form.
But: server-side validation is the truth. Client-side is for UX.
Sanitization for rendered content
If users paste HTML or markdown that will be rendered:Related
Convex schema
Validators reference.
Error handling
What to do when validation fails.
XSS / CSRF
Defending against rendered attacks.
