cabloy 5.1.59 → 5.1.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/contract-loop-gate.ts +296 -0
- package/.claude/settings.json +16 -0
- package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +1 -0
- package/.claude/skills/cabloy-contract-loop/SKILL.md +103 -14
- package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +126 -12
- package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +148 -0
- package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +49 -13
- package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +11 -0
- package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +2 -0
- package/.claude/skills/cabloy-module-removal/SKILL.md +144 -0
- package/.claude/skills/cabloy-resource-field-update/SKILL.md +274 -0
- package/.claude/skills/cabloy-resource-field-update/evals/evals.json +53 -0
- package/.claude/skills/cabloy-resource-field-update/references/custom-renderer-demo-checklist.md +102 -0
- package/.claude/skills/cabloy-resource-field-update/references/field-update-decision-tree.md +120 -0
- package/.claude/skills/cabloy-resource-field-update/references/follow-up-checklist.md +80 -0
- package/.claude/skills/cabloy-resource-field-update/references/verification-checklist.md +97 -0
- package/.claude/skills/cabloy-zova-source-reading/SKILL.md +221 -0
- package/.claude/skills/cabloy-zova-source-reading/references/analysis-modes.md +91 -0
- package/.claude/skills/cabloy-zova-source-reading/references/core-reading-paths.md +117 -0
- package/.github/workflows/docs-pages.yml +2 -0
- package/.github/workflows/vona-cov-pg.yml +2 -0
- package/.github/workflows/vona-test-crud.yml +4 -2
- package/.github/workflows/vona-test-mysql.yml +2 -0
- package/.github/workflows/vona-test-pg.yml +2 -0
- package/.github/workflows/vona-test-sqlite3.yml +2 -0
- package/.github/workflows/vona-tsc.yml +2 -0
- package/.github/workflows/zova-ui.yml +2 -0
- package/.gitignore +0 -4
- package/CHANGELOG.md +52 -0
- package/CLAUDE.md +12 -0
- package/README.md +15 -0
- package/cabloy-docs/.vitepress/config.mjs +89 -0
- package/cabloy-docs/ai/class-placement-rule.md +2 -0
- package/cabloy-docs/ai/cli-to-skill-map.md +14 -0
- package/cabloy-docs/ai/docs-skills-rules-mapping.md +14 -0
- package/cabloy-docs/ai/future-skill-roadmap.md +27 -9
- package/cabloy-docs/ai/introduction.md +1 -0
- package/cabloy-docs/ai/playbook-backend-module.md +6 -0
- package/cabloy-docs/ai/playbook-module-removal.md +164 -0
- package/cabloy-docs/ai/skills.md +11 -0
- package/cabloy-docs/backend/bean-scene-authoring.md +350 -0
- package/cabloy-docs/backend/cli.md +26 -1
- package/cabloy-docs/backend/dto-guide.md +6 -0
- package/cabloy-docs/backend/entity-guide.md +18 -0
- package/cabloy-docs/backend/foundation.md +28 -3
- package/cabloy-docs/backend/introduction.md +10 -0
- package/cabloy-docs/backend/serialization-guide.md +10 -0
- package/cabloy-docs/backend/service-guide.md +2 -0
- package/cabloy-docs/backend/status-guide.md +271 -0
- package/cabloy-docs/backend/websocket-call-flow.md +435 -0
- package/cabloy-docs/backend/websocket-guide.md +455 -0
- package/cabloy-docs/backend/websocket-protocol-guide.md +381 -0
- package/cabloy-docs/backend/websocket-usage-guide.md +356 -0
- package/cabloy-docs/frontend/api-guide.md +2 -0
- package/cabloy-docs/frontend/bean-scene-authoring.md +374 -0
- package/cabloy-docs/frontend/behavior-guide.md +449 -0
- package/cabloy-docs/frontend/cli.md +24 -0
- package/cabloy-docs/frontend/command-scene-authoring.md +495 -0
- package/cabloy-docs/frontend/design-principles.md +6 -0
- package/cabloy-docs/frontend/fetch-interceptor-guide.md +440 -0
- package/cabloy-docs/frontend/form-guide.md +795 -0
- package/cabloy-docs/frontend/foundation.md +29 -0
- package/cabloy-docs/frontend/introduction.md +17 -1
- package/cabloy-docs/frontend/ioc-and-beans.md +16 -9
- package/cabloy-docs/frontend/mock-guide.md +1 -0
- package/cabloy-docs/frontend/model-architecture.md +252 -39
- package/cabloy-docs/frontend/model-resource-best-practices.md +379 -0
- package/cabloy-docs/frontend/model-resource-cookbook.md +505 -0
- package/cabloy-docs/frontend/model-resource-owner-pattern.md +382 -0
- package/cabloy-docs/frontend/model-resource-usage-guide.md +318 -0
- package/cabloy-docs/frontend/model-state-guide.md +366 -13
- package/cabloy-docs/frontend/openapi-sdk-guide.md +5 -2
- package/cabloy-docs/frontend/page-guide.md +6 -0
- package/cabloy-docs/frontend/quickstart.md +4 -0
- package/cabloy-docs/frontend/reading-zova-for-vue-developers.md +266 -0
- package/cabloy-docs/frontend/router-tabs-admin-web-comparison.md +206 -0
- package/cabloy-docs/frontend/router-tabs-introduction.md +106 -0
- package/cabloy-docs/frontend/router-tabs-mechanism.md +469 -0
- package/cabloy-docs/frontend/router-tabs-overview.md +227 -0
- package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +343 -0
- package/cabloy-docs/frontend/server-data.md +2 -0
- package/cabloy-docs/frontend/ssr-architecture-overview.md +211 -0
- package/cabloy-docs/frontend/ssr-build-deploy-guide.md +308 -0
- package/cabloy-docs/frontend/ssr-review-checklist.md +184 -0
- package/cabloy-docs/frontend/ssr-troubleshooting-guide.md +301 -0
- package/cabloy-docs/frontend/zova-form-source-reading-map.md +295 -0
- package/cabloy-docs/frontend/zova-form-under-the-hood.md +556 -0
- package/cabloy-docs/frontend/zova-reactivity-under-the-hood.md +320 -0
- package/cabloy-docs/frontend/zova-source-reading-map.md +327 -0
- package/cabloy-docs/frontend/zova-vs-vue3-comparison.md +308 -0
- package/cabloy-docs/fullstack/contract-loop-playbook.md +350 -0
- package/cabloy-docs/fullstack/framework-performance.md +3 -3
- package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +44 -1
- package/cabloy-docs/fullstack/introduction.md +40 -0
- package/cabloy-docs/fullstack/openapi-to-sdk.md +19 -9
- package/cabloy-docs/fullstack/quickstart.md +7 -1
- package/cabloy-docs/fullstack/tutorial-1-first-module.md +111 -0
- package/cabloy-docs/fullstack/tutorial-2-first-crud.md +122 -0
- package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +131 -0
- package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +144 -0
- package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +146 -0
- package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +170 -0
- package/cabloy-docs/fullstack/tutorials-overview.md +192 -0
- package/cabloy-docs/index.md +4 -3
- package/cabloy-docs/reference/bean-scene-boilerplates.md +75 -0
- package/cabloy-docs/reference/cli-reference.md +2 -0
- package/package.json +7 -2
- package/scripts/initTestData.ts +25 -0
- package/scripts/upgrade.ts +17 -2
- package/vona/packages-cli/cabloy-cli/package.json +2 -2
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.create.module.ts +4 -0
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/pnpm-lock.yaml +226 -1091
- package/vona/pnpm-workspace.yaml +0 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/assets/static/img/vona.svg +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +2 -2
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/package.original.json +1 -1
- package/zova/packages-cli/cli/package.json +3 -3
- package/zova/packages-cli/cli-set-front/cli/templates/init/icon/boilerplate/icons/default/zova.svg +1 -1
- package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/module/openapi.config.ts +6 -1
- package/zova/packages-cli/cli-set-front/package.json +3 -3
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.module.ts +4 -0
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +34 -4
- package/zova/packages-cli/cli-set-front/src/lib/command/create.bean.ts +5 -1
- package/zova/packages-utils/zova-vite/package.json +2 -2
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +282 -1311
- package/zova/pnpm-workspace.yaml +0 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/cabloy.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/vona.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/zova.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/src/.metadata/icons/groups/social.svg +3 -3
- package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +9 -0
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +66 -16
- package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/modules/a-routertabs/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-routertabs/src/model/tabs.ts +60 -18
- package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableActionRow/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableCell/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +4 -4
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Tutorial 4: Custom Form/Table Renderers for Level
|
|
2
|
+
|
|
3
|
+
<Badge type="info" text="Basic" />
|
|
4
|
+
|
|
5
|
+
In this tutorial, one prompt lets AI upgrade the `level` field from built-in render resources to custom frontend renderers owned by the `demo-student` module.
|
|
6
|
+
|
|
7
|
+
This is the **reverse chain** custom-resource handoff branch of the contract loop.
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
By the end of this tutorial, you will understand:
|
|
12
|
+
|
|
13
|
+
- when built-in render metadata is enough and when a custom renderer is worth adding
|
|
14
|
+
- how a frontend table cell bean and a frontend form-field component can both serve the same backend field
|
|
15
|
+
- how backend metadata points to module-owned frontend render resources
|
|
16
|
+
|
|
17
|
+
## AI Prompt
|
|
18
|
+
|
|
19
|
+
Give AI a prompt like this:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
Please make the level UI more business-specific in the Student list page and form.
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Why this step matters
|
|
26
|
+
|
|
27
|
+
This is the right follow-up step because built-in render resources are a good starting point, but some business fields eventually need module-specific behavior.
|
|
28
|
+
|
|
29
|
+
The `level` field is a good teaching example because this step deepens the UI in two concrete ways:
|
|
30
|
+
|
|
31
|
+
- a custom table cell that renders a more business-specific badge style
|
|
32
|
+
- a custom form field that adds helper text, readonly behavior, or module-specific select styling
|
|
33
|
+
|
|
34
|
+
This is where Cabloy’s contract model becomes more practical: the backend field still owns the business contract, while the frontend module progressively deepens the UI behavior behind that contract.
|
|
35
|
+
|
|
36
|
+
## CLI commands to inspect/use
|
|
37
|
+
|
|
38
|
+
Inspect the Zova create surface first:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm run zova :create
|
|
42
|
+
npm run zova :create:bean --help
|
|
43
|
+
npm run zova :create:component --help
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Representative generation commands for this tutorial:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run zova :create:bean tableCell level -- --module=demo-student
|
|
50
|
+
npm run zova :create:component formFieldLevel -- --module=demo-student
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Usage notes:
|
|
54
|
+
|
|
55
|
+
- use `:create:bean` when you need a table-cell render resource under the bean scene
|
|
56
|
+
- use `:create:component` when you need a custom frontend component/controller surface
|
|
57
|
+
- generation gives you the structural starting point, but this tutorial still expects manual refinement so the result matches the `demo-student` teaching implementation
|
|
58
|
+
- after frontend resources exist, return to the backend entity and point `ZovaRender.field(...)` and `ZovaRender.cell(...)` at the custom module resources
|
|
59
|
+
- once backend metadata starts consuming those new frontend resources, treat the next step as a reverse fullstack handoff rather than frontend-only cleanup: refresh generated output, rebuild the relevant flavor, and re-sync Vona dependencies
|
|
60
|
+
|
|
61
|
+
## Generated or affected files
|
|
62
|
+
|
|
63
|
+
By the end of this tutorial, your module should provide these teaching anchors:
|
|
64
|
+
|
|
65
|
+
- custom table cell bean:
|
|
66
|
+
- `zova/src/module/demo-student/src/bean/tableCell.level.tsx`
|
|
67
|
+
- custom form-field controller:
|
|
68
|
+
- `zova/src/module/demo-student/src/component/formFieldLevel/controller.tsx`
|
|
69
|
+
- form-field metadata wrapper:
|
|
70
|
+
- `zova/src/module/demo-student/src/.metadata/component/formFieldLevel.ts`
|
|
71
|
+
- backend field contract to update:
|
|
72
|
+
- `vona/src/module/demo-student/src/entity/student.tsx`
|
|
73
|
+
|
|
74
|
+
Representative custom metadata targets are:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
ZovaRender.field('demo-student:formFieldLevel', {
|
|
78
|
+
items: levelItems,
|
|
79
|
+
helper: $locale('LevelPlaceholder'),
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
and:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
ZovaRender.cell('demo-student:level', { items: levelItems })
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## What those files mean in the business thread
|
|
90
|
+
|
|
91
|
+
This tutorial makes the split of responsibilities explicit:
|
|
92
|
+
|
|
93
|
+
- `tableCell.level.tsx` owns the custom table-cell rendering behavior for `level`
|
|
94
|
+
- `component/formFieldLevel/controller.tsx` owns the custom form-field behavior for `level`
|
|
95
|
+
- `.metadata/component/formFieldLevel.ts` exposes that component through the module registration surface
|
|
96
|
+
- `entity/student.tsx` remains the backend-owned business contract that chooses which frontend resources should render the field
|
|
97
|
+
|
|
98
|
+
That means the backend still defines the business field, validation, and metadata entry point, while the frontend module owns the implementation details of the richer UI behavior.
|
|
99
|
+
|
|
100
|
+
## Verification
|
|
101
|
+
|
|
102
|
+
1. refresh the generated handoff surfaces before checking backend consumers:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm run zova :tools:metadata demo-student
|
|
106
|
+
npm run build:zova:admin
|
|
107
|
+
npm run deps:vona
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If the same renderer path must also be available for Web, also run:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm run build:zova:web
|
|
114
|
+
npm run deps:vona
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
If backend-side type consumers still cannot see the new shared renderer types even though generated `.zova-rest` output is already correct, rebuild `vona/node_modules` and reinstall dependencies:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
cd vona && rm -rf node_modules && pnpm install
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
2. make sure the local dev workflow is running:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm run dev
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
3. open `http://localhost:7102/admin/`
|
|
130
|
+
4. enter the **Student** list page and verify that the `level` column now uses the custom table-cell presentation
|
|
131
|
+
5. open a Student create, update, or view form and verify that the `level` field now uses the custom form-field behavior
|
|
132
|
+
6. inspect `vona/src/module/demo-student/src/entity/student.tsx` and confirm that the backend metadata now points to `demo-student:formFieldLevel` and `demo-student:level`
|
|
133
|
+
|
|
134
|
+
## Read more
|
|
135
|
+
|
|
136
|
+
- [Frontend Metadata Back to Backend](/fullstack/frontend-metadata-to-backend)
|
|
137
|
+
- [Frontend CLI](/frontend/cli)
|
|
138
|
+
- [Component Guide](/frontend/component-guide)
|
|
139
|
+
- [Zova Form Under the Hood](/frontend/zova-form-under-the-hood)
|
|
140
|
+
- [Bean Scene Boilerplate Variants](/reference/bean-scene-boilerplates)
|
|
141
|
+
|
|
142
|
+
## Next step
|
|
143
|
+
|
|
144
|
+
Continue to [Tutorial 5: Backend Contract Sharing](/fullstack/tutorial-5-backend-contract-sharing).
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Tutorial 5: Backend Contract Sharing
|
|
2
|
+
|
|
3
|
+
<Badge type="info" text="Basic" />
|
|
4
|
+
|
|
5
|
+
In this tutorial, one prompt lets AI show the **forward chain** of Cabloy’s fullstack contract loop: backend API contracts that generate and refresh the frontend consumption surface.
|
|
6
|
+
|
|
7
|
+
The teaching thread in this page is the pair of Student actions:
|
|
8
|
+
|
|
9
|
+
- `summary/:id`
|
|
10
|
+
- `deleteForce/:id`
|
|
11
|
+
|
|
12
|
+
## Goal
|
|
13
|
+
|
|
14
|
+
By the end of this tutorial, you will understand:
|
|
15
|
+
|
|
16
|
+
- how a backend controller and DTO change becomes frontend generated API output
|
|
17
|
+
- how backend row-action metadata can drive frontend table actions
|
|
18
|
+
- how generated API, thin frontend model helpers, and row-action beans fit into one forward-chain workflow
|
|
19
|
+
- why custom resource endpoints that still belong to the same resource should reuse the existing resource-owner instead of creating a competing cache owner
|
|
20
|
+
|
|
21
|
+
## AI Prompt
|
|
22
|
+
|
|
23
|
+
Give AI a prompt like this:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
Please add two custom actions to the Student list:
|
|
27
|
+
|
|
28
|
+
- Summary: return or display a student summary for the selected row
|
|
29
|
+
- Force Delete: permanently delete the selected student through a dedicated row action
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Why this step matters
|
|
33
|
+
|
|
34
|
+
This is the right step because it reduces duplicated type work across backend and frontend.
|
|
35
|
+
|
|
36
|
+
Instead of manually synchronizing request and response shapes in two places, this workflow keeps the backend as the source of truth and regenerates the frontend artifacts from that contract.
|
|
37
|
+
|
|
38
|
+
This step also shows that contract sharing is not only about API methods. It also affects how backend row-action metadata becomes frontend table behavior.
|
|
39
|
+
|
|
40
|
+
## CLI commands to inspect/use
|
|
41
|
+
|
|
42
|
+
Inspect the relevant command surfaces first:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm run zova :openapi
|
|
46
|
+
npm run zova :openapi:config demo-student
|
|
47
|
+
npm run zova :openapi:generate demo-student
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
If your workflow also needs refreshed rest-contract output for Cabloy Basic, the related build commands are:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd zova && npm run build:rest:cabloyBasicAdmin
|
|
54
|
+
cd zova && npm run build:rest:cabloyBasicWeb
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Usage notes:
|
|
58
|
+
|
|
59
|
+
- use the backend controller and DTOs as the starting point
|
|
60
|
+
- inspect the module OpenAPI config before generation
|
|
61
|
+
- prefer regeneration over hand-written duplicate API layers when the module already owns an OpenAPI contract surface
|
|
62
|
+
- keep frontend follow-up thin: treat the module model as a semantic facade over generated API consumers rather than a second contract-definition layer
|
|
63
|
+
- if the custom endpoint still belongs to the existing resource, reuse the existing resource-owner for server-state ownership
|
|
64
|
+
|
|
65
|
+
## Generated or affected files
|
|
66
|
+
|
|
67
|
+
The backend contract anchors are:
|
|
68
|
+
|
|
69
|
+
- `vona/src/module/demo-student/src/controller/student.ts`
|
|
70
|
+
- `vona/src/module/demo-student/src/dto/studentSummary.tsx`
|
|
71
|
+
- `vona/src/module/demo-student/src/dto/studentSelectResItem.tsx`
|
|
72
|
+
|
|
73
|
+
By the end of this tutorial, your `demo-student` controller should expose:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
@Web.get('summary/:id')
|
|
77
|
+
async summary(...) { ... }
|
|
78
|
+
|
|
79
|
+
@Web.delete('deleteForce/:id')
|
|
80
|
+
async deleteForce(...) { ... }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The frontend contract and consumption anchors are:
|
|
84
|
+
|
|
85
|
+
- OpenAPI config:
|
|
86
|
+
- `zova/src/module/demo-student/cli/openapi.config.ts`
|
|
87
|
+
- generated frontend API:
|
|
88
|
+
- `zova/src/module/demo-student/src/api/demoStudent.ts`
|
|
89
|
+
- frontend model wrapper:
|
|
90
|
+
- `zova/src/module/demo-student/src/model/student.ts`
|
|
91
|
+
- custom row-action cells:
|
|
92
|
+
- `zova/src/module/demo-student/src/bean/tableCell.actionSummary.tsx`
|
|
93
|
+
- `zova/src/module/demo-student/src/bean/tableCell.actionDeleteForce.tsx`
|
|
94
|
+
|
|
95
|
+
After regeneration, `src/api/demoStudent.ts` should contain generated methods such as:
|
|
96
|
+
|
|
97
|
+
- `summary(...)`
|
|
98
|
+
- `deleteForce(...)`
|
|
99
|
+
|
|
100
|
+
## What those files mean in the business thread
|
|
101
|
+
|
|
102
|
+
This tutorial is easiest to understand as one contract chain:
|
|
103
|
+
|
|
104
|
+
1. `controller/student.ts` defines the backend action endpoints
|
|
105
|
+
2. `dto/studentSummary.tsx` defines the response contract for the summary action
|
|
106
|
+
3. `dto/studentSelectResItem.tsx` defines the row-action metadata that exposes those actions in the Student list page
|
|
107
|
+
4. `cli/openapi.config.ts` tells the frontend module which backend operations it owns
|
|
108
|
+
5. `src/api/demoStudent.ts` is the generated typed API surface created from that backend contract
|
|
109
|
+
6. `src/model/student.ts` wraps the generated API in a thin frontend semantic facade
|
|
110
|
+
7. the model should reuse the existing resource-owner for server-state ownership when the new API still belongs to the Student resource
|
|
111
|
+
8. `tableCell.actionSummary.tsx` and `tableCell.actionDeleteForce.tsx` turn those model methods into visible row actions
|
|
112
|
+
|
|
113
|
+
That is the practical forward chain: backend controller and DTO truth flows into generated frontend API output, then into thin frontend model helpers, and finally into visible table actions.
|
|
114
|
+
|
|
115
|
+
## Verification
|
|
116
|
+
|
|
117
|
+
1. make sure the local dev workflow is running:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm run dev
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
2. open `http://localhost:7102/admin/`
|
|
124
|
+
3. enter the **Student** list page
|
|
125
|
+
4. trigger the **Summary** row action and verify that it uses the regenerated frontend API and returns the expected Student summary data
|
|
126
|
+
5. trigger the **Force Delete** row action and verify that it reaches the custom backend deleteForce contract path
|
|
127
|
+
6. inspect the source chain and confirm that each layer is present:
|
|
128
|
+
- `controller/student.ts`
|
|
129
|
+
- `dto/studentSummary.tsx`
|
|
130
|
+
- `dto/studentSelectResItem.tsx`
|
|
131
|
+
- `src/api/demoStudent.ts`
|
|
132
|
+
- `src/model/student.ts`
|
|
133
|
+
- `tableCell.actionSummary.tsx`
|
|
134
|
+
- `tableCell.actionDeleteForce.tsx`
|
|
135
|
+
|
|
136
|
+
## Read more
|
|
137
|
+
|
|
138
|
+
- [Backend OpenAPI to Frontend SDK](/fullstack/openapi-to-sdk)
|
|
139
|
+
- [OpenAPI Guide](/backend/openapi-guide)
|
|
140
|
+
- [OpenAPI SDK Guide](/frontend/openapi-sdk-guide)
|
|
141
|
+
- [SDK Guide](/frontend/sdk-guide)
|
|
142
|
+
- [Server Data](/frontend/server-data)
|
|
143
|
+
|
|
144
|
+
## Next step
|
|
145
|
+
|
|
146
|
+
Continue to [Tutorial 6: One Contract Surface, Four Uses](/fullstack/tutorial-6-one-contract-four-uses).
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Tutorial 6: One Contract Surface, Four Uses
|
|
2
|
+
|
|
3
|
+
<Badge type="info" text="Basic" />
|
|
4
|
+
|
|
5
|
+
In this tutorial, one prompt lets AI close the series by showing Cabloy’s core fullstack idea: one field-oriented contract surface can drive several behaviors across backend and frontend.
|
|
6
|
+
|
|
7
|
+
This capstone sits on top of both the forward chain and the reverse chain rather than replacing either one.
|
|
8
|
+
|
|
9
|
+
This time the main teaching field is `mobile`, while `level` stays as the supporting example for table and form rendering.
|
|
10
|
+
|
|
11
|
+
## Goal
|
|
12
|
+
|
|
13
|
+
By the end of this tutorial, you will understand how one business field thread can participate in:
|
|
14
|
+
|
|
15
|
+
1. validation
|
|
16
|
+
2. OpenAPI generation
|
|
17
|
+
3. table and form rendering
|
|
18
|
+
4. serialization or desensitization
|
|
19
|
+
|
|
20
|
+
## AI Prompt
|
|
21
|
+
|
|
22
|
+
Give AI a prompt like this:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
Please add a mobile field to the Student resource. It should be required, be at least 11 characters long, and show the middle 4 digits as asterisks in returned data.
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Why this step matters
|
|
29
|
+
|
|
30
|
+
This is the right capstone step because many frameworks force the same field knowledge to be repeated in many places:
|
|
31
|
+
|
|
32
|
+
- validation rules
|
|
33
|
+
- backend DTOs
|
|
34
|
+
- API documentation
|
|
35
|
+
- frontend forms
|
|
36
|
+
- frontend tables
|
|
37
|
+
- response masking logic
|
|
38
|
+
|
|
39
|
+
Cabloy tries to reduce that duplication through a field-oriented contract and metadata model, and this tutorial lets you inspect that reduction through one concrete field story.
|
|
40
|
+
|
|
41
|
+
## CLI commands to inspect/use
|
|
42
|
+
|
|
43
|
+
This tutorial is mainly a source-inspection and verification capstone.
|
|
44
|
+
|
|
45
|
+
Useful commands include:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm run zova :openapi:generate demo-student
|
|
49
|
+
npm run dev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Usage notes:
|
|
53
|
+
|
|
54
|
+
- regenerate the frontend contract if your backend field changes affect the generated output
|
|
55
|
+
- treat the backend entity and DTO surfaces as the first place to inspect
|
|
56
|
+
- use the admin UI to confirm both the visible rendering result and the exposed mobile behavior
|
|
57
|
+
|
|
58
|
+
## Generated or affected files
|
|
59
|
+
|
|
60
|
+
The key backend field contract anchor is:
|
|
61
|
+
|
|
62
|
+
- `vona/src/module/demo-student/src/entity/student.tsx`
|
|
63
|
+
|
|
64
|
+
By the end of this tutorial, the `mobile` field should show the main capstone pattern:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
@Api.field(
|
|
68
|
+
v.title($locale('Mobile')),
|
|
69
|
+
v.required(),
|
|
70
|
+
v.min(11),
|
|
71
|
+
studentMobileSerializer(),
|
|
72
|
+
ZovaRender.order(4),
|
|
73
|
+
)
|
|
74
|
+
mobile: string;
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The serializer helper lives in:
|
|
78
|
+
|
|
79
|
+
- `vona/src/module/demo-student/src/lib/studentMobile.ts`
|
|
80
|
+
|
|
81
|
+
The summary DTO also participates in the same thread:
|
|
82
|
+
|
|
83
|
+
- `vona/src/module/demo-student/src/dto/studentSummary.tsx`
|
|
84
|
+
|
|
85
|
+
The supporting render example remains:
|
|
86
|
+
|
|
87
|
+
- `vona/src/module/demo-student/src/entity/student.tsx`
|
|
88
|
+
- `ZovaRender.field(...)` for `level`
|
|
89
|
+
- `ZovaRender.cell(...)` for `level`
|
|
90
|
+
|
|
91
|
+
## What those files mean in the business thread
|
|
92
|
+
|
|
93
|
+
This tutorial works best when you read `mobile` as one continuous contract thread.
|
|
94
|
+
|
|
95
|
+
That is why `mobile` is the main capstone field, while `level` remains the supporting rendering field.
|
|
96
|
+
|
|
97
|
+
### Use 1: Validation
|
|
98
|
+
|
|
99
|
+
In `entity/student.tsx`, `mobile` already carries validation decisions such as:
|
|
100
|
+
|
|
101
|
+
- `v.required()`
|
|
102
|
+
- `v.min(11)`
|
|
103
|
+
|
|
104
|
+
That means the field definition is part of the request-contract story, not only a persistence concern.
|
|
105
|
+
|
|
106
|
+
### Use 2: OpenAPI generation
|
|
107
|
+
|
|
108
|
+
The same field contract participates in DTO and controller flows, which then feed machine-readable API output.
|
|
109
|
+
|
|
110
|
+
That is why backend field and DTO changes can later affect what frontend regeneration sees.
|
|
111
|
+
|
|
112
|
+
### Use 3: Table and form rendering
|
|
113
|
+
|
|
114
|
+
The main rendering example in this series remains `level`, not `mobile`.
|
|
115
|
+
|
|
116
|
+
That is intentional.
|
|
117
|
+
|
|
118
|
+
`level` shows how the same field-oriented contract can carry:
|
|
119
|
+
|
|
120
|
+
- `ZovaRender.field(...)`
|
|
121
|
+
- `ZovaRender.cell(...)`
|
|
122
|
+
- built-in or custom frontend render resources
|
|
123
|
+
|
|
124
|
+
This keeps the “four uses” explanation complete without forcing `mobile` to act like the best rendering example.
|
|
125
|
+
|
|
126
|
+
### Use 4: Serialization and desensitization
|
|
127
|
+
|
|
128
|
+
The most practical `mobile` lesson is response exposure policy.
|
|
129
|
+
|
|
130
|
+
In `studentMobile.ts`, the helper:
|
|
131
|
+
|
|
132
|
+
- defines the masking pattern
|
|
133
|
+
- returns `v.serializerReplace(...)`
|
|
134
|
+
|
|
135
|
+
That keeps the masking rule close to the field contract ecosystem instead of scattering it into ad hoc controller or service post-processing.
|
|
136
|
+
|
|
137
|
+
## Verification
|
|
138
|
+
|
|
139
|
+
1. make sure the local dev workflow is running:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npm run dev
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
2. open `http://localhost:7102/admin/`
|
|
146
|
+
3. enter the relevant **Student** page
|
|
147
|
+
4. verify that `level` still shows the expected render-driven behavior
|
|
148
|
+
5. verify that `mobile` follows the validation and serialization policy you defined
|
|
149
|
+
6. inspect these anchors and confirm that the four-use story is concrete rather than abstract:
|
|
150
|
+
- `vona/src/module/demo-student/src/entity/student.tsx`
|
|
151
|
+
- `vona/src/module/demo-student/src/lib/studentMobile.ts`
|
|
152
|
+
- `vona/src/module/demo-student/src/dto/studentSummary.tsx`
|
|
153
|
+
|
|
154
|
+
## Read more
|
|
155
|
+
|
|
156
|
+
- [Validation Guide](/backend/validation-guide)
|
|
157
|
+
- [OpenAPI Guide](/backend/openapi-guide)
|
|
158
|
+
- [API Schema Guide](/frontend/api-schema-guide)
|
|
159
|
+
- [Server Data](/frontend/server-data)
|
|
160
|
+
- [Serialization Guide](/backend/serialization-guide)
|
|
161
|
+
- [Backend OpenAPI to Frontend SDK](/fullstack/openapi-to-sdk)
|
|
162
|
+
- [Frontend Metadata Back to Backend](/fullstack/frontend-metadata-to-backend)
|
|
163
|
+
|
|
164
|
+
## Next step
|
|
165
|
+
|
|
166
|
+
After finishing this series, choose the next path based on your current task:
|
|
167
|
+
|
|
168
|
+
- if you want deeper backend contract detail, continue with [Entity Guide](/backend/entity-guide) and [DTO Guide](/backend/dto-guide)
|
|
169
|
+
- if you want deeper frontend contract consumption, continue with [OpenAPI SDK Guide](/frontend/openapi-sdk-guide) and [API Schema Guide](/frontend/api-schema-guide)
|
|
170
|
+
- if you want more CLI-oriented workflow depth, continue with [CLI Reference](/reference/cli-reference)
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Fullstack Quick Start Tutorials
|
|
2
|
+
|
|
3
|
+
<Badge type="info" text="Basic" />
|
|
4
|
+
|
|
5
|
+
This six-part tutorial series gives you one connected, AI-guided path into Cabloy fullstack development.
|
|
6
|
+
|
|
7
|
+
## Why this series exists
|
|
8
|
+
|
|
9
|
+
Cabloy already has strong reference guides for CRUD, OpenAPI, DTO and entity contracts, schema-driven frontend rendering, and serialization. This series packages those capabilities into one simple workflow: each page gives you one focused prompt, AI completes the next increment, and you use the result to understand the framework model behind it.
|
|
10
|
+
|
|
11
|
+
The core rhythm is:
|
|
12
|
+
|
|
13
|
+
1. each page provides one focused prompt
|
|
14
|
+
2. AI completes the tutorial-sized increment
|
|
15
|
+
3. the generated or affected files become the next teaching surface
|
|
16
|
+
4. the result is verified in the running app or generated contract output
|
|
17
|
+
5. deeper reference docs remain available when more background is needed
|
|
18
|
+
|
|
19
|
+
That makes the series practical as a guided, interactive workflow: each tutorial reduces the user action to one prompt, while the generated result becomes the teaching material for the next step.
|
|
20
|
+
|
|
21
|
+
## The business scenario
|
|
22
|
+
|
|
23
|
+
Throughout the series, you will build and refine a small **Student Training Center** example.
|
|
24
|
+
|
|
25
|
+
The main business object is `student`, and the teaching fields are:
|
|
26
|
+
|
|
27
|
+
- `name`
|
|
28
|
+
- `description`
|
|
29
|
+
- `level`
|
|
30
|
+
- `mobile`
|
|
31
|
+
|
|
32
|
+
Why these fields?
|
|
33
|
+
|
|
34
|
+
- `level` is a good field for schema-driven form and table rendering
|
|
35
|
+
- `mobile` is a good field for validation, OpenAPI output, and serialization or masking
|
|
36
|
+
|
|
37
|
+
This keeps the storyline small enough for beginners while still showing Cabloy’s fullstack contract model.
|
|
38
|
+
|
|
39
|
+
At the beginning of the series, the `demo-student` module does not exist yet. The tutorials build it step by step.
|
|
40
|
+
|
|
41
|
+
## What you should prepare first
|
|
42
|
+
|
|
43
|
+
Before starting this tutorial series, make sure you already know:
|
|
44
|
+
|
|
45
|
+
- how to bootstrap a Cabloy Basic project
|
|
46
|
+
- how to run the repo from the root
|
|
47
|
+
- how to discover command families through `npm run vona` and `npm run zova`
|
|
48
|
+
|
|
49
|
+
Read these pages first:
|
|
50
|
+
|
|
51
|
+
- [Fullstack Quickstart](/fullstack/quickstart)
|
|
52
|
+
- [Fullstack CLI](/fullstack/cli)
|
|
53
|
+
- [CLI Reference](/reference/cli-reference)
|
|
54
|
+
|
|
55
|
+
Those pages explain the repo entrypoints and the CLI-first workflow model that the tutorial prompts will reuse throughout this series.
|
|
56
|
+
|
|
57
|
+
## The learning path
|
|
58
|
+
|
|
59
|
+
### Phase 1: Create the module and CRUD thread
|
|
60
|
+
|
|
61
|
+
- [Tutorial 1: Create Your First Module](/fullstack/tutorial-1-first-module)
|
|
62
|
+
- [Tutorial 2: Create Your First CRUD](/fullstack/tutorial-2-first-crud)
|
|
63
|
+
|
|
64
|
+
### Phase 2: Reverse chain — share frontend rendering metadata through the backend contract
|
|
65
|
+
|
|
66
|
+
- [Tutorial 3: Frontend Metadata Sharing](/fullstack/tutorial-3-frontend-metadata-sharing)
|
|
67
|
+
- [Tutorial 4: Custom Form/Table Renderers for Level](/fullstack/tutorial-4-custom-level-renderers)
|
|
68
|
+
|
|
69
|
+
Important handoff note for this phase:
|
|
70
|
+
|
|
71
|
+
- this phase teaches the **reverse chain** of the Cabloy contract loop
|
|
72
|
+
- Tutorial 3 uses the built-in metadata branch
|
|
73
|
+
- Tutorial 4 uses the custom resource handoff branch
|
|
74
|
+
- once a frontend resource created in these tutorials is later consumed by backend metadata, do not stop at frontend source edits alone
|
|
75
|
+
- refresh the generated frontend output, run the relevant flavor build, then run `npm run deps:vona`
|
|
76
|
+
- if backend-side shared types still look stale after that normal sync flow, rebuild `vona/node_modules` and reinstall dependencies
|
|
77
|
+
|
|
78
|
+
See [Contract Loop Playbook](/fullstack/contract-loop-playbook) and [Frontend Metadata Back to Backend](/fullstack/frontend-metadata-to-backend) for the full reverse-chain explanation.
|
|
79
|
+
|
|
80
|
+
### Phase 3: Forward chain — share backend contracts into frontend consumption
|
|
81
|
+
|
|
82
|
+
- [Tutorial 5: Backend Contract Sharing](/fullstack/tutorial-5-backend-contract-sharing)
|
|
83
|
+
|
|
84
|
+
This phase teaches the **forward chain** of the contract loop: backend contract truth changes first, generated frontend consumers are refreshed second, and frontend follow-up stays thin and resource-owner-aware.
|
|
85
|
+
|
|
86
|
+
### Phase 4: One field story across multiple contract surfaces
|
|
87
|
+
|
|
88
|
+
- [Tutorial 6: One Contract Surface, Four Uses](/fullstack/tutorial-6-one-contract-four-uses)
|
|
89
|
+
|
|
90
|
+
## The standard tutorial structure
|
|
91
|
+
|
|
92
|
+
All six tutorials in this series follow the same learning structure:
|
|
93
|
+
|
|
94
|
+
1. `Goal`
|
|
95
|
+
2. `AI Prompt`
|
|
96
|
+
3. `Why this step matters`
|
|
97
|
+
4. `CLI commands to inspect/use`
|
|
98
|
+
5. `Generated or affected files`
|
|
99
|
+
6. `What those files mean in the business thread`
|
|
100
|
+
7. `Verification`
|
|
101
|
+
8. `Read more`
|
|
102
|
+
9. `Next step`
|
|
103
|
+
|
|
104
|
+
This makes the series easier to execute one page at a time: each page gives AI one clear increment, and the resulting output teaches why that step fits the Cabloy architecture.
|
|
105
|
+
|
|
106
|
+
## How to use this series with AI
|
|
107
|
+
|
|
108
|
+
Keep this series simple.
|
|
109
|
+
|
|
110
|
+
In each tutorial, your main job is to copy the prompt from the page and give it to AI.
|
|
111
|
+
|
|
112
|
+
That prompt already tells AI how to work in the Cabloy way, including things like:
|
|
113
|
+
|
|
114
|
+
- inspect the CLI first
|
|
115
|
+
- perform only the current tutorial increment
|
|
116
|
+
- explain the commands it used
|
|
117
|
+
- explain the business meaning of the generated or changed files
|
|
118
|
+
- tell you what to verify next
|
|
119
|
+
|
|
120
|
+
So for the user, the workflow is intentionally lightweight:
|
|
121
|
+
|
|
122
|
+
1. open the current tutorial
|
|
123
|
+
2. copy the prompt
|
|
124
|
+
3. send it to AI
|
|
125
|
+
4. review the result and continue to the next tutorial when ready
|
|
126
|
+
|
|
127
|
+
## CLI-first rule
|
|
128
|
+
|
|
129
|
+
This series assumes that AI should follow Cabloy’s CLI-first workflow before attempting manual scaffolding.
|
|
130
|
+
|
|
131
|
+
In practice, the tutorial prompt should push AI to follow this rule:
|
|
132
|
+
|
|
133
|
+
1. inspect the existing CLI family
|
|
134
|
+
2. run the matching generator or tooling command
|
|
135
|
+
3. inspect the generated result
|
|
136
|
+
4. make only the minimal manual follow-up changes that the business case still needs
|
|
137
|
+
|
|
138
|
+
Shared discovery commands from the repo root:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm run vona :
|
|
142
|
+
npm run vona :create
|
|
143
|
+
npm run vona :tools
|
|
144
|
+
|
|
145
|
+
npm run zova :
|
|
146
|
+
npm run zova :create
|
|
147
|
+
npm run zova :openapi
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
This is one of the most important Cabloy rules for AI-driven development in this series.
|
|
151
|
+
|
|
152
|
+
## Suggested reading rhythm
|
|
153
|
+
|
|
154
|
+
This series is designed to progress one prompt at a time.
|
|
155
|
+
|
|
156
|
+
Each tutorial assumes that the previous result remains in place, so the workflow should stay incremental:
|
|
157
|
+
|
|
158
|
+
1. complete the current tutorial prompt
|
|
159
|
+
2. keep the generated result
|
|
160
|
+
3. continue to the next tutorial on top of that result
|
|
161
|
+
|
|
162
|
+
If a tutorial creates a new module, the local dev workflow may need `npm run dev` again so the new module is picked up before the next step.
|
|
163
|
+
|
|
164
|
+
Do not jump directly to SDK generation or custom renderers before the module and CRUD thread are in place.
|
|
165
|
+
|
|
166
|
+
## What you will understand by the end
|
|
167
|
+
|
|
168
|
+
After the six tutorials, the completed workflow should make these Cabloy ideas clear:
|
|
169
|
+
|
|
170
|
+
- when to use Vona and when to use Zova
|
|
171
|
+
- why CRUD generation usually comes before hand-written backend boilerplate
|
|
172
|
+
- how backend field metadata can reuse frontend render resources
|
|
173
|
+
- how to evolve from built-in renderers to custom renderers
|
|
174
|
+
- how backend OpenAPI contracts regenerate frontend SDKs and model helpers
|
|
175
|
+
- how validation, rendering, OpenAPI, and serialization fit into one field-oriented contract model
|
|
176
|
+
|
|
177
|
+
## Read together with
|
|
178
|
+
|
|
179
|
+
The deeper reference guides behind this workflow include:
|
|
180
|
+
|
|
181
|
+
- [CRUD Workflow](/backend/crud-workflow)
|
|
182
|
+
- [Entity Guide](/backend/entity-guide)
|
|
183
|
+
- [DTO Guide](/backend/dto-guide)
|
|
184
|
+
- [Validation Guide](/backend/validation-guide)
|
|
185
|
+
- [OpenAPI Guide](/backend/openapi-guide)
|
|
186
|
+
- [Backend OpenAPI to Frontend SDK](/fullstack/openapi-to-sdk)
|
|
187
|
+
- [Frontend Metadata Back to Backend](/fullstack/frontend-metadata-to-backend)
|
|
188
|
+
- [OpenAPI SDK Guide](/frontend/openapi-sdk-guide)
|
|
189
|
+
- [API Schema Guide](/frontend/api-schema-guide)
|
|
190
|
+
- [Serialization Guide](/backend/serialization-guide)
|
|
191
|
+
|
|
192
|
+
This series is not meant to replace those guides. It is meant to help you move through them in one practical, task-driven order.
|
package/cabloy-docs/index.md
CHANGED
|
@@ -51,9 +51,10 @@ Start here to learn the shared Cabloy architecture, see how Vona and Zova fit to
|
|
|
51
51
|
### For getting started
|
|
52
52
|
|
|
53
53
|
1. [Fullstack Quickstart](/fullstack/quickstart)
|
|
54
|
-
2. [
|
|
55
|
-
3. [
|
|
56
|
-
4. [
|
|
54
|
+
2. [Fullstack Quick Start Tutorials](/fullstack/tutorials-overview)
|
|
55
|
+
3. [Editions Overview](/editions/overview)
|
|
56
|
+
4. [Choosing Between Cabloy Basic and Cabloy Start](/editions/choosing-between-basic-and-start)
|
|
57
|
+
5. [Fullstack Introduction](/fullstack/introduction)
|
|
57
58
|
|
|
58
59
|
### For contributors and AI vibe coding workflows
|
|
59
60
|
|