Tutorial 3: Frontend Metadata Sharing
BasicIn this tutorial, one prompt lets AI show the reverse chain of Cabloy’s fullstack contract loop: backend field metadata can reference frontend render resources.
You start with the simplest path first: reuse the existing built-in rendering resources for the level field.
NOTE
This tutorial still uses the standalone demo-student sandbox introduced in Tutorial 1. Keep that sandbox separate from the repo's real suite-owned a-training/training-student example so you can experiment and compare the two paths side by side.
Goal
By the end of this tutorial, you will understand:
- why Cabloy fullstack sharing is bidirectional
- how a backend field can reuse frontend rendering resources through metadata
- how one
levelfield can participate in schema-driven form and table behavior without a custom component yet
AI Prompt
Give AI a prompt like this:
Please add a level field to the Student resource. It should be a required number field with these enum values:
- 1: beginner
- 2: intermediate
- 3: advanced2
3
4
5
Why this step matters
This is the right step because it teaches one very specific Cabloy distinction.
The goal is not to make backend and frontend share arbitrary component code. The goal is to keep the backend field contract in charge while letting that contract reference frontend render resources through metadata.
In other words, this step is about frontend metadata sharing: the backend field contract references frontend render resources through metadata.
CLI commands to inspect/use
This tutorial is mainly a contract-refinement step, so the most important habit is inspection before editing.
Useful discovery commands from the repo root:
npm run vona :
npm run zova :
npm run zova :create2
3
You usually do not need to generate a custom bean in this tutorial.
Instead, inspect the current contract surfaces first:
vona/src/module/demo-student/src/entity/student.tsxvona/src/module/demo-student/src/dto/studentSelectReq.tsx
Usage notes:
- keep the backend entity as the main source of truth for the
levelfield - prefer built-in frontend render resources first
- delay custom renderer authoring to the next tutorial
Generated or affected files
The key backend contract anchor is:
vona/src/module/demo-student/src/entity/student.tsx
By the end of this tutorial, the level field should follow a built-in path like this:
@Api.field(
v.title($locale('Level')),
v.required(),
ZovaRender.order(3),
ZovaRender.field('basic-select:formFieldSelect', {
items: levelItems,
placeholder: $locale('LevelPlaceholder'),
}),
ZovaRender.cell('basic-select:select', { items: levelItems }),
levelSchema,
)
level: number;2
3
4
5
6
7
8
9
10
11
12
A related DTO anchor is:
vona/src/module/demo-student/src/dto/studentSelectReq.tsx
That DTO already shows how filter-side field metadata can also participate in schema-driven UI.
What those files mean in the business thread
This tutorial teaches one core mental model:
- the backend still owns the business field contract
- the frontend still owns the render resources
- metadata is the bridge between them
Concretely:
entity/student.tsxdefineslevelas a real business fieldlevelItemsgives that field a stable set of business optionsZovaRender.field('basic-select:formFieldSelect', ...)makes the form side schema-awareZovaRender.cell('basic-select:select', ...)makes the table side schema-awaredto/studentSelectReq.tsxreminds you that filter-side metadata is also part of the same contract story
At this stage, you do not need a custom frontend component to understand the reverse-sharing model.
Verification
- make sure the local dev workflow is running:
npm run dev- open
http://localhost:7102/admin/ - enter the Student list page from the Student menu
- verify that the
levelfield appears with select-style behavior in the relevant schema-driven surfaces - inspect
vona/src/module/demo-student/src/entity/student.tsxand confirm that the backend field contract now points to built-in frontend render resources instead of page-local hard-coded UI logic
Read more
Next step
Continue to Tutorial 4: Custom Form/Table Renderers for Level.