Golden Path — Schema (*.schema.ts)
TypeBox schemas describe request bodies, responses, and shared shapes. Registering them with fastify.registerSchema feeds HTTP validation and can feed generated shared types so backend and frontend can align on the same definitions where you choose to use them.
What we recommend structurally
For each datatype, keep a clear split so routes and future frontend validation can reuse the same pieces:
| Piece | Role |
|---|---|
| Base / full document schema | Fields common to stored documents (often includes _id, timestamps). |
| Create | Body for POST — usually omits backend-generated fields. |
| Update | Body for PATCH — optional fields only. |
| Delete / hard-delete | If you expose delete semantics, separate narrow schemas keep routes honest. |
Use stable $id / title metadata on each Type.Object so generated artifacts and OpenAPI-style tooling stay traceable. The cooking-step example below is the reference layout.
When you later add client-side validation in the docs, aim to reuse the same TypeBox definitions (or generated static types) so create/update payloads cannot drift between backend routes and UI forms.
Responsibilities
- One schema module per datatype (or a deliberate split if a datatype is huge).
- Export
register…Schemas(fastify)and call it from the pluginindex.ts.
Registering schemas from the plugin entry
Export register…Schemas(fastify) from your schema module and call it from the datatype or plugin index.ts alongside models, routes, and payload — same registration phase as the rest of the Golden Path.
registerExampleSchemas(fastify)Replace Example with the PascalCase name of your datatype’s schema module. The cooking-step example shows the full TypeBox graph and this call in context.
Full example (base, create, update, registration)
The complete TypeBox layout (base, create, update, register…Schemas) lives in the cooking-step file — it has its own frontmatter, so we link instead of embedding (avoids a broken second --- block in this page):