D3What it costs the developer
One invoice. Four descriptions of it.
The Go struct, the TypeScript type, the validation schema, the mobile client. Kept in step by memory. Nothing fails to compile when they drift.
What actually goes wrong
The same record is described in the Go model, in a TypeScript interface, in a validation schema and again in whatever the mobile app holds. Four files, four authors, one shape.
The failure is silent. Rename a column and the frontend keeps compiling, the form keeps submitting, and the field is quietly dropped on the way through. You find it when a customer asks why their phone number vanished.
What Grit does about it
- The Go model is the source. One command reads it and rewrites the TypeScript interface, the three Zod schemas and the admin resource fields.
- Renaming a column then makes the editor underline every screen that used the old name, before anything runs.
- The create schema drops the server-assigned columns and the update schema is the create schema partialled, so a PATCH cannot blank a field the form did not show.
The commands
After changing a Go model
grit migrategrit sync
Or let the generator write all of it from one description
grit generate resource Invoice --fields "number:string, total:money, due:date"
What it does not do
Sync keeps the type, the schema and the admin in step. It does not update generated mobile or desktop screens; it names the fields they never saw and leaves them to you.
