Backend OpenAPI to Frontend SDK
This page is the forward chain deep dive for Cabloy’s bidirectional contract loop.
Why this path matters
In the bidirectional Contract Loop Playbook, this page covers the forward chain:
NOTE
The fullstack tutorial series intentionally uses a standalone demo-student sandbox so readers can experiment without colliding with the repo's real suite-owned a-training/training-student implementation. This guide focuses on the current repo implementation as its forward-chain specimen.
- Vona emits backend API metadata through Swagger/OpenAPI
- Zova consumes that metadata to generate frontend SDKs and schema-aware helpers
- frontend pages, models, and services build on those generated contracts instead of re-declaring everything manually
This is one of the strongest AI-leverage paths in the repo because it reduces duplicated type work and keeps backend/frontend coordination closer to source truth.
The forward chain in practical terms
A useful split is:
- backend docs define the authoring side of the contract
- fullstack docs define the bridge from emitted contract to generated SDK
- frontend docs define the consumption side of the generated contract
That means this page is the forward-chain bridge page, not the backend authoring page and not the frontend usage page.
If the changed source is actually a frontend-owned resource that backend consumers later depend on, switch to the reverse-chain guide: Frontend Metadata Back to Backend.
If your real question is how one backend-owned row action becomes a visible frontend table action through metadata, page blocks, tableCell resources, and optionally generated API/model layers, continue with Backend Metadata to Frontend Table Actions.
Backend side: Vona emits the contract
On the backend side, OpenAPI metadata is driven by:
- controller argument and return contracts
- DTO and entity field definitions
- validation rules and
vhelpers a-openapiconfiguration
For the deeper backend perspective, see:
- Controller Guide
- OpenAPI Guide
- Validation Guide
- DTO Infer and Generation
- Backend Resource/Module Contract Chain
Frontend side: Zova consumes the contract
On the frontend side, the generated-contract path typically includes:
- OpenAPI configuration
- SDK generation
- API services or schema-driven helpers based on the generated output
For the deeper frontend perspective, see:
Source-to-consumer chain
If you want the shortest accurate mental model, use this forward chain:
- backend controller signatures define request and response entry surfaces
- backend DTO and entity fields shape named and shared contract structure
- validation rules and
vhelpers refine the machine-readable contract - Vona emits OpenAPI output from those backend declarations
- Zova OpenAPI config decides which generated contract slice belongs to which frontend module
- frontend generation produces SDK and rest/schema-related contract output
- frontend code consumes the generated contract through:
- generated SDK methods
- schema-driven helpers
$sdkand$apiSchema-adjacent runtime surfaces- thin model facades and existing resource-owner consumers when the API belongs to an existing resource
That means this bridge is not only “generate the SDK.”
It is the whole path that moves backend-authored truth into frontend-usable contract material.
Which page owns which question?
Use this split to avoid reading the wrong layer too deeply.
Backend authoring semantics
Use these when the real question is how the backend contract is authored:
- Controller Guide
- DTO Guide
- DTO Infer and Generation
- OpenAPI Guide
- Backend Resource/Module Contract Chain
Forward-chain bridge and regeneration workflow
Use this page when the real question is:
- how backend-authored truth crosses the stack boundary
- which generation steps to run
- where module ownership and regeneration decisions belong
- how to keep frontend follow-up thin after regeneration
Frontend generation and usage setup
Use these when the generated contract has already crossed the boundary and you are configuring or consuming it in Zova:
Frontend runtime and deeper consumption internals
Use these when the real question is how generated contract material is consumed inside Zova runtime layers:
Cabloy Basic workflow
In the current public monorepo, Basic-specific Zova flavors include:
cabloyBasicAdmincabloyBasicWeb
Representative frontend-side contract-generation commands include:
npm run zova :openapi:config training-student
npm run zova :openapi:generate training-student
cd zova && npm run build:rest:cabloyBasicAdmin
cd zova && npm run build:rest:cabloyBasicWebA practical forward-chain sequence is:
- author or change the backend contract
- emit or inspect backend OpenAPI output
- if the frontend generator reads from a local Swagger endpoint, start the backend service first so the endpoint is reachable — in this repo,
npm run devis the normal path and exposes Swagger athttp://localhost:7102/swagger/json?version=V31 - configure frontend module ownership if needed
- generate module-level OpenAPI SDK output
- run the rest build for the active flavor when needed
- consume the generated contract from frontend code instead of re-declaring it manually
- keep frontend follow-up thin by wrapping generated consumers with semantic facades instead of re-declaring the contract
- when the custom API still belongs to an existing resource, reuse the existing resource-owner instead of creating a competing cache owner
A practical responsibility split is:
- project-level OpenAPI config decides where the backend Swagger/OpenAPI source comes from
- module-level OpenAPI config decides which generated contract slice belongs to which frontend module
- module-level ownership should be declared explicitly with
operations.matchoroperations.ignore
If both operations.match and operations.ignore are empty, frontend SDK generation should fail fast instead of generating a large unrelated contract surface for the module. That fail-fast behavior helps both developers and AI agents notice the missing ownership boundary immediately and repair the config before the wrong SDK slice is generated.
A practical regeneration rule is:
- if the backend contract changed, prefer regenerating the SDK/rest layer before hand-editing frontend request code
- if
npm run zova :openapi:generate ...fails because the local Swagger source is unavailable, first start the backend service and confirmhttp://localhost:7102/swagger/json?version=V31is reachable before treating generation as broken - if the generated consumer path is already correct, but frontend behavior still looks stale, stop patching generated files and diagnose consumer drift or local dependency drift instead
training-student as a compact forward-chain specimen
A compact specimen helps make the bridge more concrete.
A practical training-student forward chain looks like this:
- backend contract truth changes in places such as:
controller/student.tsentity/student.tsxdto/studentCreate.tsxdto/studentUpdate.tsxdto/studentView.tsxdto/studentSelectReq.tsx
- backend OpenAPI output changes because those controller/DTO/entity/validation surfaces changed
- frontend OpenAPI generation refreshes the module-owned consumer slice
- flavor-specific rest output is rebuilt when the workflow depends on generated rest output
- frontend code consumes the generated result through module-owned SDK/schema surfaces, then keeps follow-up thin with semantic wrappers or existing resource owners
This is the main point of the forward chain:
backend contract truth moves first, generated handoff moves second, frontend consumers stay thin and downstream.
Thin frontend follow-up after generation
After the generated contract crosses the boundary, the best frontend move is usually not to recreate the contract by hand.
A practical split is:
- use generated SDKs when the module already follows the OpenAPI-generated API-service path
- use schema-driven helpers when the workflow is contract/schema oriented
- use thin model facades when the UI needs business semantics over generated APIs
- reuse the existing resource-owner when the custom API still belongs to the same resource
That last point matters especially for resource-driven pages.
If the endpoint still belongs to an existing business resource, prefer keeping ModelResource or the existing resource-owner story as the stable state owner rather than introducing a competing second owner.
Cabloy Start workflow
In the sibling private Start repo, the same collaboration idea applies, but the frontend flavor names differ.
Representative Start-specific flavors include:
cabloyStartAdmincabloyStartWeb
Before documenting or automating this path for Start, confirm:
- the
__CABLOY_START__marker - the Start repo’s
package.json - the exact frontend flavor names and generated output paths
Where to read next
- If your next question is still on the backend authoring side, continue with OpenAPI Guide, Backend Contract Emission Specimen, Backend Contract Emission Output Inspection, DTO Guide, DTO Infer and Generation, and Backend Resource/Module Contract Chain.
- If your next question is about frontend SDK setup and module ownership, continue with OpenAPI SDK Guide.
- If your next question is about what generated contract consumption looks like in one practical frontend path, continue with Generated Contract Consumption Specimen, then choose Generated Contract Consumption: List Branch or Generated Contract Consumption: Entry Branch as needed.
- If your next question becomes one mixed Student row-action thread spanning backend metadata, generated contract follow-up, and frontend action resources, continue with Backend Metadata to Frontend Table Actions Source Reading Map.
- If your next question is about schema-driven frontend consumption, continue with API Schema Guide.
- If your next question is about the lower-level frontend runtime under generated OpenAPI/schema usage, continue with A-OpenAPI Under the Hood.
- If your next question is about resource-owner or model-level consumption after regeneration, continue with ModelResource Internals Deep Dive and Rest Resource Source Reading Map.
- If the problem is actually about deciding which direction the contract loop is moving, return to Contract Loop Playbook.
Implementation checks for backend-to-frontend contract changes
When changing a backend API contract, ask:
- does OpenAPI output change?
- does the frontend SDK or schema layer need regeneration?
- is the active edition Basic or Start?
- is the right next step to regenerate contracts instead of hand-editing frontend request code?
- is the current task on the backend authoring side, the bridge step, or the frontend consumption side?
That keeps the backend/frontend contract loop coherent.