One schema, two runtimes: API contracts with Zod
Treating the Laravel resource as a contract and letting the frontend refuse anything that breaks it.
Written by
TubagusFull Stack Developer
Published
Reading
6 min
Topics
Frontend · #TypeScript · #Zod · #Laravel

The bug that hurts most is the one where the API changed and the UI kept rendering undefined politely.
The resource is the contract
Every Laravel JsonResource on this site has a matching Zod schema on the frontend. If a field is renamed, the page fails loudly in development instead of quietly in production.
export const NoteSchema = z.object({
slug: z.string(),
title: z.string(),
views: z.number(),
})
Parse at the edge
Responses are parsed once, inside the API client. Components only ever see typed, validated data — no optional chaining scattered through the tree.
Keep it boring
- One schema per resource, named after the resource.
- Infer types from schemas; never write them twice.
- Let the error message point at the exact field that broke.
It is a small habit that removes a whole category of "but it worked yesterday".
Next note
Moving from Next.js to TanStack Start: honest notes→