How to use same validation rules across client and server sides

I’m trying to figure out the best way to keep validation consistent between my frontend and backend code. Previously when using TypeScript everywhere, I could write Zod schemas once and reuse them on both ends which was really convenient.

Now I’m working with Rust for the backend and need a similar solution. I looked into protovalidate for protocol buffers but there’s no Rust support yet. JSON Schema doesn’t work well for my needs because it can’t handle things like checking if two fields match (like password confirmation).

I’m considering two options:

  1. Building a custom protovalidate implementation for Rust
  2. Creating a WebAssembly module that exposes my Rust validation logic to the frontend

Before diving into either approach, I want to know what solutions others are using. How do you handle shared validation between your frontend and backend applications?

I hit the same issue when switching from full TypeScript to Rust backend. Tried a bunch of different ways, but here’s what worked for me: define your validation schemas in JSON Schema, then generate both Rust and TypeScript validation code from those schemas. JSON Schema can’t handle complex cross-field validations well, so I just write custom validators separately for each side but keep the naming and error formats consistent. You get consistency for basic stuff while staying flexible for complex rules. The code generation keeps everything in sync without dealing with WASM headaches.

tbh, was d this approach might complicate things. I’ve done that too n it just brings more chaos. Maybe keeping two similar validation sets is better? I mean, sure it’s some extra work, but it’s easier to manage in the long run. Writing tests could help keep em aligned!