TkDodo 🔮
TkDodo 🔮2y ago

Sharing schemas between server and client

In a typical nextJs setup, what is the idiomatic way to share zod schemas between frontend and backend? Suppose the following use-case: we have a mutation that takes an input:
const schema = z.object({
email: z.string().email({ message: 'Enter a valid email address' }),
subject: z.string()
message: z.string()
})
const schema = z.object({
email: z.string().email({ message: 'Enter a valid email address' }),
subject: z.string()
message: z.string()
})
on the frontend, we are building a form with react-hook-form that would also like to use this schema to validate the user input. The main question is: Where would we put this schema so that we can use it in both places. In terms of colocation, I think I would like to have it somewhere close on the server and then maybe just import it on the client from there? How are you all handling this? Thanks 🙏
4 Replies
TkDodo 🔮
TkDodo 🔮2y ago
it would be pretty awesome if the input schema would be available on the frontend somehow. for example:
// on the server
const router = t.router({
greeting: t.procedure
.input(z.object({ name: z.string() }))
.query(({ input }) => `Hello ${input.name}`),
});
// on the server
const router = t.router({
greeting: t.procedure
.input(z.object({ name: z.string() }))
.query(({ input }) => `Hello ${input.name}`),
});
// on the client
const query = trpc.hello.useQuery({ name: 'client' });
const input = trpc.hello.useInput() // just an idea, would yield the zod schema z.object({ name: z.string() })
// on the client
const query = trpc.hello.useQuery({ name: 'client' });
const input = trpc.hello.useInput() // just an idea, would yield the zod schema z.object({ name: z.string() })
is something like that possible?
Alex / KATT 🐱
I usually do a shared folder where I keep stuff that can be used by both FE and BE But you can also import straight from the FE https://kitchen-sink.trpc.io/react-hook-form I've thought of doing it so the client could pull the input validators but zod schemas aren't serializable
TkDodo 🔮
TkDodo 🔮2y ago
yeah I've created a separate file next to the router now, which works. I'd like to keep the schemas close to the backend rather than have the frontend control them. why would the schema need to be serializable?
Alex / KATT 🐱
If they were serializable we could fetch the input schema when needed There's probably some transpilation magic possible too but that's not my jam