cabloy 5.1.61 → 5.1.62

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.
Files changed (201) hide show
  1. package/.claude/skills/cabloy-backend-scaffold/SKILL.md +2 -0
  2. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +1 -1
  3. package/.claude/skills/cabloy-domain-planning/SKILL.md +212 -0
  4. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +2 -0
  5. package/CHANGELOG.md +42 -0
  6. package/CLAUDE.md +1 -0
  7. package/cabloy-docs/.vitepress/config.mjs +158 -12
  8. package/cabloy-docs/ai/docs-skills-rules-mapping.md +8 -0
  9. package/cabloy-docs/ai/future-skill-roadmap.md +2 -0
  10. package/cabloy-docs/ai/skills.md +1 -0
  11. package/cabloy-docs/backend/backend-contract-emission-output-inspection.md +189 -0
  12. package/cabloy-docs/backend/backend-contract-emission-source-reading-map.md +160 -0
  13. package/cabloy-docs/backend/backend-contract-emission-specimen.md +170 -0
  14. package/cabloy-docs/backend/backend-resource-module-contract-chain.md +323 -0
  15. package/cabloy-docs/backend/backend-source-reading-debug-checklist.md +173 -0
  16. package/cabloy-docs/backend/backend-source-reading-roadmap.md +129 -0
  17. package/cabloy-docs/backend/backend-source-reading-verify-playbook.md +166 -0
  18. package/cabloy-docs/backend/bean-scene-authoring.md +4 -4
  19. package/cabloy-docs/backend/broadcast-guide.md +3 -3
  20. package/cabloy-docs/backend/cli.md +20 -11
  21. package/cabloy-docs/backend/config-guide.md +4 -4
  22. package/cabloy-docs/backend/controller-aop-guide.md +10 -10
  23. package/cabloy-docs/backend/controller-guide.md +12 -2
  24. package/cabloy-docs/backend/crud-workflow.md +7 -3
  25. package/cabloy-docs/backend/dto-guide.md +12 -2
  26. package/cabloy-docs/backend/dto-infer-generation.md +201 -25
  27. package/cabloy-docs/backend/election-guide.md +2 -2
  28. package/cabloy-docs/backend/entity-guide.md +12 -3
  29. package/cabloy-docs/backend/error-guide.md +3 -3
  30. package/cabloy-docs/backend/event-guide.md +4 -4
  31. package/cabloy-docs/backend/external-aop-guide.md +2 -2
  32. package/cabloy-docs/backend/field-indexes.md +9 -3
  33. package/cabloy-docs/backend/foundation.md +8 -8
  34. package/cabloy-docs/backend/i18n-guide.md +6 -6
  35. package/cabloy-docs/backend/internal-aop-guide.md +2 -2
  36. package/cabloy-docs/backend/introduction.md +13 -0
  37. package/cabloy-docs/backend/migration-and-changes.md +3 -3
  38. package/cabloy-docs/backend/model-guide.md +16 -6
  39. package/cabloy-docs/backend/openapi-guide.md +3 -0
  40. package/cabloy-docs/backend/queue-guide.md +3 -3
  41. package/cabloy-docs/backend/redlock-guide.md +2 -2
  42. package/cabloy-docs/backend/schedule-guide.md +2 -2
  43. package/cabloy-docs/backend/scripts.md +8 -0
  44. package/cabloy-docs/backend/serialization-guide.md +2 -2
  45. package/cabloy-docs/backend/service-guide.md +18 -9
  46. package/cabloy-docs/backend/startup-guide.md +5 -5
  47. package/cabloy-docs/backend/status-guide.md +7 -7
  48. package/cabloy-docs/backend/unit-testing.md +3 -3
  49. package/cabloy-docs/backend/vona-source-reading-map.md +157 -0
  50. package/cabloy-docs/backend/websocket-protocol-guide.md +5 -5
  51. package/cabloy-docs/backend/websocket-usage-guide.md +15 -8
  52. package/cabloy-docs/frontend/a-model-under-the-hood.md +281 -0
  53. package/cabloy-docs/frontend/a-openapi-under-the-hood.md +248 -0
  54. package/cabloy-docs/frontend/a-router-guide.md +307 -0
  55. package/cabloy-docs/frontend/api-guide.md +4 -4
  56. package/cabloy-docs/frontend/api-schema-guide.md +1 -0
  57. package/cabloy-docs/frontend/app-startup-guide.md +7 -4
  58. package/cabloy-docs/frontend/bean-scene-authoring.md +1 -1
  59. package/cabloy-docs/frontend/behavior-guide.md +16 -16
  60. package/cabloy-docs/frontend/cli.md +5 -5
  61. package/cabloy-docs/frontend/command-scene-authoring.md +17 -8
  62. package/cabloy-docs/frontend/component-guide.md +5 -5
  63. package/cabloy-docs/frontend/component-props-guide.md +1 -1
  64. package/cabloy-docs/frontend/component-v-model-guide.md +2 -2
  65. package/cabloy-docs/frontend/filter-query-select-data-flow-guide.md +260 -0
  66. package/cabloy-docs/frontend/form-guide.md +19 -28
  67. package/cabloy-docs/frontend/form-scene-to-page-meta-guide.md +303 -0
  68. package/cabloy-docs/frontend/foundation.md +10 -6
  69. package/cabloy-docs/frontend/frontend-source-reading-roadmap.md +249 -0
  70. package/cabloy-docs/frontend/generated-contract-consumption-debug-checklist.md +190 -0
  71. package/cabloy-docs/frontend/generated-contract-consumption-entry-branch.md +205 -0
  72. package/cabloy-docs/frontend/generated-contract-consumption-list-branch.md +157 -0
  73. package/cabloy-docs/frontend/generated-contract-consumption-specimen.md +203 -0
  74. package/cabloy-docs/frontend/generated-contract-consumption-verify-playbook.md +189 -0
  75. package/cabloy-docs/frontend/generic-component-guide.md +1 -1
  76. package/cabloy-docs/frontend/introduction.md +29 -7
  77. package/cabloy-docs/frontend/model-architecture.md +38 -2
  78. package/cabloy-docs/frontend/model-resource-cookbook.md +11 -8
  79. package/cabloy-docs/frontend/model-resource-internals-deep-dive.md +238 -0
  80. package/cabloy-docs/frontend/model-resource-owner-pattern.md +22 -2
  81. package/cabloy-docs/frontend/model-resource-usage-guide.md +22 -6
  82. package/cabloy-docs/frontend/model-state-guide.md +12 -9
  83. package/cabloy-docs/frontend/module-scope.md +8 -8
  84. package/cabloy-docs/frontend/modules-and-suites.md +2 -1
  85. package/cabloy-docs/frontend/navigation-guards-guide.md +7 -0
  86. package/cabloy-docs/frontend/openapi-sdk-guide.md +12 -4
  87. package/cabloy-docs/frontend/page-guide.md +9 -9
  88. package/cabloy-docs/frontend/page-meta-guide.md +466 -0
  89. package/cabloy-docs/frontend/page-params-guide.md +3 -3
  90. package/cabloy-docs/frontend/page-query-guide.md +2 -2
  91. package/cabloy-docs/frontend/page-route-guide.md +6 -0
  92. package/cabloy-docs/frontend/permission-formscene-action-visibility-guide.md +263 -0
  93. package/cabloy-docs/frontend/quickstart.md +14 -2
  94. package/cabloy-docs/frontend/resource-entry-page-deep-dive.md +271 -0
  95. package/cabloy-docs/frontend/resource-list-page-deep-dive.md +279 -0
  96. package/cabloy-docs/frontend/rest-resource-source-reading-map.md +522 -0
  97. package/cabloy-docs/frontend/rest-resource-under-the-hood.md +622 -0
  98. package/cabloy-docs/frontend/root-behaviors-guide.md +282 -0
  99. package/cabloy-docs/frontend/route-alias-guide.md +6 -0
  100. package/cabloy-docs/frontend/router-stack-guide.md +229 -0
  101. package/cabloy-docs/frontend/router-tabs-introduction.md +26 -3
  102. package/cabloy-docs/frontend/router-tabs-layout-integration.md +367 -0
  103. package/cabloy-docs/frontend/router-tabs-mechanism.md +6 -0
  104. package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +7 -0
  105. package/cabloy-docs/frontend/router-tabs-vs-stack.md +167 -0
  106. package/cabloy-docs/frontend/router-view-hosts-guide.md +450 -0
  107. package/cabloy-docs/frontend/server-data.md +2 -1
  108. package/cabloy-docs/frontend/system-startup-guide.md +2 -2
  109. package/cabloy-docs/frontend/table-action-visibility-permission-flow-guide.md +263 -0
  110. package/cabloy-docs/frontend/table-cell-cookbook.md +568 -0
  111. package/cabloy-docs/frontend/table-guide.md +373 -0
  112. package/cabloy-docs/frontend/table-resource-crud-cookbook.md +496 -0
  113. package/cabloy-docs/frontend/zova-app-guide.md +251 -0
  114. package/cabloy-docs/frontend/zova-form-source-reading-map.md +7 -9
  115. package/cabloy-docs/frontend/zova-form-under-the-hood.md +5 -0
  116. package/cabloy-docs/frontend/zova-router-under-the-hood.md +561 -0
  117. package/cabloy-docs/frontend/zova-source-reading-map.md +101 -7
  118. package/cabloy-docs/frontend/zova-table-controller-render-supplement.md +225 -0
  119. package/cabloy-docs/frontend/zova-table-source-reading-map.md +317 -0
  120. package/cabloy-docs/frontend/zova-table-under-the-hood.md +532 -0
  121. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-debug-checklist.md +245 -0
  122. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-source-reading-map.md +139 -0
  123. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-verify-playbook.md +248 -0
  124. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions.md +511 -0
  125. package/cabloy-docs/fullstack/contract-loop-playbook.md +8 -2
  126. package/cabloy-docs/fullstack/edition-collaboration-differences.md +6 -0
  127. package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +181 -48
  128. package/cabloy-docs/fullstack/introduction.md +3 -0
  129. package/cabloy-docs/fullstack/openapi-to-sdk.md +116 -2
  130. package/cabloy-docs/fullstack/suites-and-modules.md +333 -0
  131. package/cabloy-docs/fullstack/tutorial-1-first-module.md +3 -0
  132. package/cabloy-docs/fullstack/tutorial-2-first-crud.md +4 -0
  133. package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +4 -0
  134. package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +31 -19
  135. package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +5 -0
  136. package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +4 -0
  137. package/cabloy-docs/fullstack/tutorials-overview.md +1 -1
  138. package/cabloy-docs/reference/bean-scene-boilerplates.md +13 -13
  139. package/cabloy-docs/reference/package-map.md +4 -3
  140. package/package.json +1 -1
  141. package/vona/pnpm-lock.yaml +22 -258
  142. package/vona/src/suite/a-training/modules/training-student/package.json +53 -0
  143. package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +400 -0
  144. package/vona/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +18 -0
  145. package/vona/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
  146. package/vona/src/suite/a-training/modules/training-student/src/bean/meta.index.ts +12 -0
  147. package/vona/src/suite/a-training/modules/training-student/src/bean/meta.version.ts +21 -0
  148. package/vona/src/suite/a-training/modules/training-student/src/bean/ssrMenu.student.ts +29 -0
  149. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +15 -0
  150. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +15 -0
  151. package/vona/src/suite/a-training/modules/training-student/src/controller/student.ts +74 -0
  152. package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +28 -0
  153. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectReq.tsx +44 -0
  154. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectRes.tsx +11 -0
  155. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +45 -0
  156. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSummary.tsx +42 -0
  157. package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +28 -0
  158. package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +25 -0
  159. package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +84 -0
  160. package/vona/src/suite/a-training/modules/training-student/src/index.ts +2 -0
  161. package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +10 -0
  162. package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +57 -0
  163. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +173 -0
  164. package/vona/src/suite/a-training/modules/training-student/tsconfig.build.json +11 -0
  165. package/vona/src/suite/a-training/modules/training-student/tsconfig.json +7 -0
  166. package/vona/src/suite/a-training/package.json +12 -0
  167. package/vona/src/suite/a-training/tsconfig.base.json +4 -0
  168. package/vona/src/suite/a-training/tsconfig.json +10 -0
  169. package/zova/packages-zova/zova/package.json +2 -2
  170. package/zova/pnpm-lock.yaml +406 -680
  171. package/zova/src/suite/a-training/modules/training-student/cli/openapi.config.ts +9 -0
  172. package/zova/src/suite/a-training/modules/training-student/package.json +52 -0
  173. package/zova/src/suite/a-training/modules/training-student/src/.metadata/component/formFieldLevel.ts +31 -0
  174. package/zova/src/suite/a-training/modules/training-student/src/.metadata/index.ts +258 -0
  175. package/zova/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +7 -0
  176. package/zova/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
  177. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/baseURL.ts +5 -0
  178. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/index.ts +3 -0
  179. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +196 -0
  180. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +4146 -0
  181. package/zova/src/suite/a-training/modules/training-student/src/api/trainingStudent.ts +151 -0
  182. package/zova/src/suite/a-training/modules/training-student/src/apiSchema/trainingStudent.ts +43 -0
  183. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionDeleteForce.tsx +51 -0
  184. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionSummary.tsx +56 -0
  185. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.level.tsx +63 -0
  186. package/zova/src/suite/a-training/modules/training-student/src/component/formFieldLevel/controller.tsx +117 -0
  187. package/zova/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +9 -0
  188. package/zova/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +9 -0
  189. package/zova/src/suite/a-training/modules/training-student/src/index.ts +2 -0
  190. package/zova/src/suite/a-training/modules/training-student/src/model/student.ts +42 -0
  191. package/zova/src/suite/a-training/modules/training-student/tsconfig.build.json +13 -0
  192. package/zova/src/suite/a-training/modules/training-student/tsconfig.json +5 -0
  193. package/zova/src/suite/a-training/package.json +12 -0
  194. package/zova/src/suite/a-training/tsconfig.base.json +4 -0
  195. package/zova/src/suite/a-training/tsconfig.json +4 -0
  196. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +29 -7
  197. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/select/controller.tsx +34 -11
  198. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  199. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +3 -3
  200. package/zova/src/suite-vendor/a-zova/modules/a-table/src/lib/tableCell.ts +1 -1
  201. package/zova/src/suite-vendor/a-zova/package.json +2 -2
@@ -0,0 +1,333 @@
1
+ # Suites and Modules
2
+
3
+ This guide explains how to think about suites and modules in the current Cabloy monorepo.
4
+
5
+ Use it when you need to answer these questions clearly:
6
+
7
+ 1. what a suite is
8
+ 2. when to create a suite instead of only a module
9
+ 3. how suite naming works
10
+ 4. where suite-owned modules should live
11
+ 5. which CLI workflows should create the structure
12
+
13
+ ## Why suites exist
14
+
15
+ As a project evolves, business capabilities do not usually grow as one isolated feature at a time.
16
+
17
+ In real business scenarios, one business domain often requires multiple related modules that evolve together. A training domain, for example, may later grow into modules for:
18
+
19
+ - training-student
20
+ - training-course
21
+ - training-record
22
+ - training-attendance
23
+ - training-certificate
24
+
25
+ Because of that, the default architectural decision should usually start from a **suite** rather than from an isolated standalone module.
26
+
27
+ A suite is the business-level composition boundary for a domain. A module is the feature-level implementation boundary inside that domain.
28
+
29
+ A practical mental model is:
30
+
31
+ - use a **suite** for the business domain
32
+ - use **modules** for the concrete capabilities inside that domain
33
+
34
+ ## Suite and module roles
35
+
36
+ The two units serve different jobs.
37
+
38
+ ### Suite
39
+
40
+ A suite groups related modules into one larger business scenario or architectural area.
41
+
42
+ That grouping matters because it gives the domain:
43
+
44
+ - a stable ownership boundary
45
+ - a clear place for future module growth
46
+ - consistent source-tree organization
47
+ - a shared naming anchor across backend and frontend
48
+
49
+ ### Module
50
+
51
+ A module is the concrete implementation unit for one feature area.
52
+
53
+ That usually means a module owns the code for things such as:
54
+
55
+ - backend controllers, services, entities, DTOs, and models
56
+ - frontend pages, components, APIs, models, and metadata
57
+ - module-local config, locale, and other scoped resources
58
+
59
+ A useful rule is:
60
+
61
+ - the **suite** answers "which business domain does this belong to?"
62
+ - the **module** answers "which capability inside that domain owns this work?"
63
+
64
+ ## Recommended decision path
65
+
66
+ In the current Cabloy monorepo, the preferred decision path is:
67
+
68
+ 1. identify the business domain
69
+ 2. create a suite for that domain
70
+ 3. create one or more modules inside the suite
71
+ 4. continue feature growth inside those suite-owned modules
72
+
73
+ In other words, for real business work, **suite-first** is usually the best choice.
74
+
75
+ ### When suite-first is the default
76
+
77
+ Create a suite first when:
78
+
79
+ - the work belongs to a real business domain
80
+ - the domain is expected to grow beyond one small feature
81
+ - backend and frontend will both evolve around the same domain
82
+ - you want to avoid later structural migration from standalone modules into a domain boundary
83
+
84
+ In practice, this is the normal path for long-lived product work.
85
+
86
+ ### When a standalone module is still acceptable
87
+
88
+ A standalone module can still be acceptable for cases such as:
89
+
90
+ - very small experiments
91
+ - disposable demos
92
+ - isolated utilities that are intentionally not the start of a larger domain
93
+ - short tutorials where introducing a domain suite would add noise
94
+
95
+ But this should be the exception, not the default path for real business architecture.
96
+
97
+ ## Naming
98
+
99
+ Suite naming follows the same high-level model on both sides:
100
+
101
+ ```text
102
+ Vona: FullName = vona-suite-{providerId}-{suiteName}
103
+ Zova: FullName = zova-suite-{providerId}-{suiteName}
104
+ ShortName = {providerId}-{suiteName}
105
+ ```
106
+
107
+ ### Important suiteName rule
108
+
109
+ In this repository, `suiteName` must follow this rule:
110
+
111
+ - `suiteName` must use lowercase English letters only
112
+ - `suiteName` must not contain another `-`
113
+
114
+ This rule matters because the `-` already separates `{providerId}` and `{suiteName}` in the short name.
115
+
116
+ So the supported shape is:
117
+
118
+ ```text
119
+ {providerId}-{suiteName}
120
+ ```
121
+
122
+ not:
123
+
124
+ ```text
125
+ {providerId}-{part1-part2}
126
+ ```
127
+
128
+ ### Examples
129
+
130
+ Representative examples from the current repo include:
131
+
132
+ - `a-home`
133
+ - `a-demo`
134
+ - `cabloy-basic`
135
+
136
+ These can be read as:
137
+
138
+ - `a-home` -> providerId: `a`, suiteName: `home`
139
+ - `a-demo` -> providerId: `a`, suiteName: `demo`
140
+ - `cabloy-basic` -> providerId: `cabloy`, suiteName: `basic`
141
+
142
+ For a training-oriented suite, the valid short name is:
143
+
144
+ - `a-training`
145
+
146
+ where:
147
+
148
+ - providerId: `a`
149
+ - suiteName: `training`
150
+
151
+ A practical rule is:
152
+
153
+ - keep `suiteName` simple, lowercase, and single-segment
154
+ - do not add another `-` inside `suiteName`
155
+ - if you need more semantic detail, express it through module names inside the suite rather than by making the suite name longer
156
+
157
+ ## Supported directory pattern
158
+
159
+ To keep the code style consistent and reduce cognitive overhead, this repository supports only one suite layout for normal authoring work:
160
+
161
+ - **suite-contained modules**
162
+
163
+ That means when a suite exists, its modules belong under that suite.
164
+
165
+ ### Backend pattern
166
+
167
+ ```text
168
+ vona/src/suite/<suite>/modules/<module>/
169
+ ```
170
+
171
+ ### Frontend pattern
172
+
173
+ ```text
174
+ zova/src/suite/<suite>/modules/<module>/
175
+ ```
176
+
177
+ ### Example
178
+
179
+ ```text
180
+ vona/src/suite/a-training/
181
+ ├── modules/
182
+ │ ├── training-student/
183
+ │ ├── training-course/
184
+ │ └── training-record/
185
+ └── package.json
186
+ ```
187
+
188
+ ```text
189
+ zova/src/suite/a-training/
190
+ ├── modules/
191
+ │ ├── training-student/
192
+ │ ├── training-course/
193
+ │ └── training-record/
194
+ └── package.json
195
+ ```
196
+
197
+ ## Unsupported pattern for normal project authoring
198
+
199
+ For consistency, do not treat a suite as a loose composition package that only depends on standalone modules located elsewhere.
200
+
201
+ In other words, do not use a suite as a separate conceptual wrapper while keeping its real modules outside the suite tree.
202
+
203
+ Use the suite as the real ownership boundary, and keep the suite-owned modules physically inside:
204
+
205
+ - `vona/src/suite/<suite>/modules/`
206
+ - `zova/src/suite/<suite>/modules/`
207
+
208
+ This keeps the source tree easier to read and avoids extra mental branching about whether a module is only logically related to a suite or actually owned by it.
209
+
210
+ ## CLI-first workflow
211
+
212
+ Do not scaffold suite/module structure manually when the CLI already supports it.
213
+
214
+ Use the framework CLI first, then make only the minimal follow-up edits that the task still needs.
215
+
216
+ ### Create a backend suite
217
+
218
+ ```bash
219
+ npm run vona :create:suite suiteName
220
+ ```
221
+
222
+ ### Create a frontend suite
223
+
224
+ ```bash
225
+ npm run zova :create:suite suiteName
226
+ ```
227
+
228
+ ### Create a backend module inside a suite
229
+
230
+ ```bash
231
+ npm run vona :create:module moduleName -- --suite=suiteName
232
+ ```
233
+
234
+ ### Create a frontend module inside a suite
235
+
236
+ ```bash
237
+ npm run zova :create:module moduleName -- --suite=suiteName
238
+ ```
239
+
240
+ A practical fullstack rule is:
241
+
242
+ - use `npm run vona` to create the backend side of the domain
243
+ - use `npm run zova` to create the frontend side of the domain
244
+ - for a real business domain, create the suite first on both sides, then create the suite-owned modules
245
+
246
+ ## Recommended workflow for real business domains
247
+
248
+ A practical suite-first workflow is:
249
+
250
+ 1. decide the domain boundary
251
+ 2. choose a valid suite short name
252
+ 3. create the suite in Vona
253
+ 4. create the suite in Zova
254
+ 5. create the first backend and frontend modules inside that suite
255
+ 6. continue all later domain growth inside the same suite
256
+
257
+ For example, for a training domain:
258
+
259
+ ```bash
260
+ npm run vona :create:suite a-training
261
+ npm run zova :create:suite a-training
262
+
263
+ npm run vona :create:module training-student -- --suite=a-training
264
+ npm run zova :create:module training-student -- --suite=a-training
265
+ ```
266
+
267
+ Later domain growth can continue with modules such as:
268
+
269
+ - training-course
270
+ - training-record
271
+ - training-attendance
272
+
273
+ This keeps the domain boundary stable while the capabilities inside it expand.
274
+
275
+ ## How to choose between a suite and only a module
276
+
277
+ Use this rule:
278
+
279
+ ### Choose a suite first when
280
+
281
+ - the work belongs to a real domain
282
+ - more related modules are likely
283
+ - the feature will grow across backend and frontend
284
+ - you want the structure to remain stable as the domain expands
285
+
286
+ ### Choose only a standalone module when
287
+
288
+ - the work is intentionally isolated
289
+ - the scope is very small
290
+ - the code is exploratory or disposable
291
+ - creating a domain suite would add more ceremony than value
292
+
293
+ For most real business scenarios, the correct answer is to create the suite first.
294
+
295
+ ## Relationship to repo structure
296
+
297
+ This guide should be read together with:
298
+
299
+ - [Package Map](/reference/package-map)
300
+ - [Backend Directory Structure](/reference/backend-directory-structure)
301
+ - [Frontend Directory Structure](/reference/frontend-directory-structure)
302
+ - [Backend CLI](/backend/cli)
303
+ - [Frontend CLI](/frontend/cli)
304
+ - [Fullstack CLI](/fullstack/cli)
305
+
306
+ A practical split is:
307
+
308
+ - this page explains the decision model for suites and modules
309
+ - the reference pages explain where those units live in the repo
310
+ - the CLI pages explain how to generate them correctly
311
+
312
+ ## Verification
313
+
314
+ After creating or restructuring suites and modules, verify with the narrowest useful checks first.
315
+
316
+ Typical checks include:
317
+
318
+ ```bash
319
+ npm run vona :
320
+ npm run zova :
321
+
322
+ npm run deps:vona
323
+ npm run deps:zova
324
+
325
+ npm run tsc
326
+ ```
327
+
328
+ If the change affects broader cross-stack output, also use the relevant build flow from the repo root.
329
+
330
+ The key rule is:
331
+
332
+ - verify that the suite and module were created in the intended structural location
333
+ - verify that later commands and dependency refresh flows still recognize that structure
@@ -52,6 +52,8 @@ Usage notes:
52
52
  - use `npm run vona :create:module` for the backend module boundary
53
53
  - use `npm run zova :create:module` for the frontend module boundary
54
54
  - use an empty `--suite=` when you want an independent module rather than a suite-owned module
55
+ - this tutorial intentionally uses a standalone `demo-student` sandbox so readers can experiment without colliding with the repo's real `a-training/training-student` example
56
+ - for the normal suite-first domain decision path, see [Suites and Modules](/fullstack/suites-and-modules)
55
57
  - rerun `npm run dev` after module creation so the local workflow picks up the new modules cleanly
56
58
 
57
59
  ## Generated or affected files
@@ -82,6 +84,7 @@ At this stage, the key idea is ownership, not business logic yet.
82
84
  - the backend module root is where the Student resource, entity, DTOs, controller, tests, and backend metadata will live later
83
85
  - the frontend module root is where generated OpenAPI output, model helpers, render resources, and frontend metadata will live later
84
86
  - the frontend `.metadata` entrypoint is part of how the module exposes its local registration surface
87
+ - because this tutorial path is intentionally standalone, you can compare its generated result against the repo's real suite-owned `a-training/training-student` implementation without overwriting it
85
88
 
86
89
  A good beginner rule is: do not rush into editing business logic until you can explain which module roots were created and why they will own the next tutorials.
87
90
 
@@ -27,6 +27,10 @@ Once the module exists, this is the next useful step because the prompt can driv
27
27
 
28
28
  That keeps the conversation focused on the generated business thread rather than on repetitive scaffolding details.
29
29
 
30
+ > [!NOTE]
31
+ > This tutorial continues the standalone `demo-student` sandbox from Tutorial 1.
32
+ > That sandbox is intentional: it lets you run the full tutorial flow without colliding with the repo's real suite-owned `a-training/training-student` implementation.
33
+
30
34
  ## CLI commands to inspect/use
31
35
 
32
36
  Inspect the CRUD family first:
@@ -6,6 +6,10 @@ In this tutorial, one prompt lets AI show the **reverse chain** of Cabloy’s fu
6
6
 
7
7
  You start with the simplest path first: reuse the existing built-in rendering resources for the `level` field.
8
8
 
9
+ > [!NOTE]
10
+ > This tutorial still uses the standalone `demo-student` sandbox introduced in Tutorial 1.
11
+ > 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.
12
+
9
13
  ## Goal
10
14
 
11
15
  By the end of this tutorial, you will understand:
@@ -2,13 +2,21 @@
2
2
 
3
3
  <Badge type="info" text="Basic" />
4
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.
5
+ In this tutorial, one prompt lets the user express a simple product need: the `level` field in the Student experience should feel less generic and more like a real training-stage workflow.
6
6
 
7
- This is the **reverse chain** custom-resource handoff branch of the contract loop.
7
+ From that user need, AI can infer that the next step is no longer just relabeling the field. It now needs a more dedicated rendering experience owned by the `demo-student` module.
8
+
9
+ This tutorial covers the **reverse chain** custom-resource handoff branch of the contract loop.
10
+
11
+ > [!NOTE]
12
+ > Like the earlier tutorials in this series, this page keeps using the standalone `demo-student` sandbox.
13
+ > That keeps the custom-renderer experiment isolated from the repo's real suite-owned `a-training/training-student` implementation.
8
14
 
9
15
  ## Goal
10
16
 
11
- By the end of this tutorial, you will understand:
17
+ By the end of this tutorial, you will understand how a user-facing request about a more business-specific `level` experience turns into a concrete custom-renderer implementation.
18
+
19
+ In particular, you will understand:
12
20
 
13
21
  - when built-in render metadata is enough and when a custom renderer is worth adding
14
22
  - how a frontend table cell bean and a frontend form-field component can both serve the same backend field
@@ -19,17 +27,17 @@ By the end of this tutorial, you will understand:
19
27
  Give AI a prompt like this:
20
28
 
21
29
  ```text
22
- Please make the level UI more business-specific in the Student list page and form.
30
+ For demo purposes, use custom renderer components to give the `level` field on the Student list page and form a more distinctive look and feel.
23
31
  ```
24
32
 
25
33
  ## Why this step matters
26
34
 
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.
35
+ This is the right follow-up step because built-in render resources are a good starting point, but some fields eventually need a more distinctive user experience to match the business workflow.
28
36
 
29
- The `level` field is a good teaching example because this step deepens the UI in two concrete ways:
37
+ The `level` field is a good teaching example because users often expect two improvements once a training workflow becomes more realistic:
30
38
 
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
39
+ - the list should make each training stage easier to recognize at a glance
40
+ - the form should guide the user more clearly when choosing a training stage
33
41
 
34
42
  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
43
 
@@ -52,15 +60,15 @@ npm run zova :create:component formFieldLevel -- --module=demo-student
52
60
 
53
61
  Usage notes:
54
62
 
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
63
+ - use `:create:bean` when AI determines that the list needs a dedicated table-cell render resource under the bean scene
64
+ - use `:create:component` when AI determines that the form needs a custom frontend component/controller surface
57
65
  - generation gives you the structural starting point, but this tutorial still expects manual refinement so the result matches the `demo-student` teaching implementation
58
66
  - after frontend resources exist, return to the backend entity and point `ZovaRender.field(...)` and `ZovaRender.cell(...)` at the custom module resources
59
67
  - 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
68
 
61
69
  ## Generated or affected files
62
70
 
63
- By the end of this tutorial, your module should provide these teaching anchors:
71
+ To satisfy the user-facing need above, AI will usually converge on a small set of implementation anchors like these:
64
72
 
65
73
  - custom table cell bean:
66
74
  - `zova/src/module/demo-student/src/bean/tableCell.level.tsx`
@@ -71,34 +79,38 @@ By the end of this tutorial, your module should provide these teaching anchors:
71
79
  - backend field contract to update:
72
80
  - `vona/src/module/demo-student/src/entity/student.tsx`
73
81
 
74
- Representative custom metadata targets are:
82
+ Representative metadata targets after AI makes that implementation decision are:
75
83
 
76
84
  ```typescript
77
85
  ZovaRender.field('demo-student:formFieldLevel', {
78
86
  items: levelItems,
79
87
  helper: $locale('LevelPlaceholder'),
80
- })
88
+ });
81
89
  ```
82
90
 
83
91
  and:
84
92
 
85
93
  ```typescript
86
- ZovaRender.cell('demo-student:level', { items: levelItems })
94
+ ZovaRender.cell('demo-student:level', { items: levelItems });
87
95
  ```
88
96
 
89
- ## What those files mean in the business thread
97
+ This is the point where a user request about “better list presentation” and “better form guidance” starts turning into explicit renderer resources and backend metadata links.
90
98
 
91
- This tutorial makes the split of responsibilities explicit:
99
+ ## How those files support the user experience
92
100
 
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`
101
+ These files work together to deliver the richer `level` experience:
102
+
103
+ - `tableCell.level.tsx` makes the training stage easier to recognize in the list
104
+ - `component/formFieldLevel/controller.tsx` makes the form interaction more guided and business-specific
95
105
  - `.metadata/component/formFieldLevel.ts` exposes that component through the module registration surface
96
106
  - `entity/student.tsx` remains the backend-owned business contract that chooses which frontend resources should render the field
97
107
 
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.
108
+ That means the backend still defines the business field, validation, and metadata entry point, while the frontend module owns the implementation details that make the experience feel more tailored to the Student Training Center workflow.
99
109
 
100
110
  ## Verification
101
111
 
112
+ These checks are the reverse-chain synchronization steps AI must complete so the user-facing renderer change is actually available to backend consumers and the running app.
113
+
102
114
  1. refresh the generated handoff surfaces before checking backend consumers:
103
115
 
104
116
  ```bash
@@ -9,6 +9,10 @@ The teaching thread in this page is the pair of Student actions:
9
9
  - `summary/:id`
10
10
  - `deleteForce/:id`
11
11
 
12
+ > [!NOTE]
13
+ > This tutorial still runs inside the standalone `demo-student` sandbox from the earlier pages.
14
+ > Use that sandbox for OpenAPI regeneration experiments so you do not interfere with the repo's real suite-owned `a-training/training-student` implementation.
15
+
12
16
  ## Goal
13
17
 
14
18
  By the end of this tutorial, you will understand:
@@ -135,6 +139,7 @@ npm run dev
135
139
 
136
140
  ## Read more
137
141
 
142
+ - [Backend Metadata to Frontend Table Actions](/fullstack/backend-metadata-to-frontend-table-actions)
138
143
  - [Backend OpenAPI to Frontend SDK](/fullstack/openapi-to-sdk)
139
144
  - [OpenAPI Guide](/backend/openapi-guide)
140
145
  - [OpenAPI SDK Guide](/frontend/openapi-sdk-guide)
@@ -8,6 +8,10 @@ This capstone sits on top of both the forward chain and the reverse chain rather
8
8
 
9
9
  This time the main teaching field is `mobile`, while `level` stays as the supporting example for table and form rendering.
10
10
 
11
+ > [!NOTE]
12
+ > This capstone still uses the standalone `demo-student` sandbox carried through the tutorial series.
13
+ > That keeps the final experiment path isolated while preserving a clean comparison against the repo's real suite-owned `a-training/training-student` implementation.
14
+
11
15
  ## Goal
12
16
 
13
17
  By the end of this tutorial, you will understand how one business field thread can participate in:
@@ -36,7 +36,7 @@ Why these fields?
36
36
 
37
37
  This keeps the storyline small enough for beginners while still showing Cabloy’s fullstack contract model.
38
38
 
39
- At the beginning of the series, the `demo-student` module does not exist yet. The tutorials build it step by step.
39
+ At the beginning of the series, the `demo-student` module does not exist yet. The tutorials build it step by step. This standalone tutorial track is intentional: it gives readers a safe experiment surface that does not collide with the repo's real `a-training/training-student` implementation and also makes side-by-side comparison easier.
40
40
 
41
41
  ## What you should prepare first
42
42
 
@@ -28,15 +28,15 @@ A practical contributor rule is:
28
28
 
29
29
  ### Current built-in scenes with variants
30
30
 
31
- | Scene | Default metadata key | Named variant keys | Example command | Source module |
32
- | -------------- | -------------------- | ------------------- | --------------------------------------------------------------------------------------------- | ---------------------- |
33
- | `filter` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean filter log -- --module=demo-student --boilerplate=global` | `vona-module-a-aspect` |
34
- | `pipe` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean pipe log -- --module=demo-student --boilerplate=global` | `vona-module-a-aspect` |
35
- | `interceptor` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean interceptor log -- --module=demo-student --boilerplate=global` | `vona-module-a-aspect` |
36
- | `guard` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean guard auth -- --module=demo-student --boilerplate=global` | `vona-module-a-aspect` |
37
- | `middleware` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean middleware trace -- --module=demo-student --boilerplate=global` | `vona-module-a-aspect` |
38
- | `ssrMenu` | `boilerplate` | `boilerplateWeb` | `npm run vona :create:bean ssrMenu menuTest -- --module=demo-student --boilerplate=web` | `vona-module-a-ssr` |
39
- | `ssrMenuGroup` | `boilerplate` | `boilerplateWeb` | `npm run vona :create:bean ssrMenuGroup groupTest -- --module=demo-student --boilerplate=web` | `vona-module-a-ssr` |
31
+ | Scene | Default metadata key | Named variant keys | Example command | Source module |
32
+ | -------------- | -------------------- | ------------------- | ------------------------------------------------------------------------------------------------- | ---------------------- |
33
+ | `filter` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean filter log -- --module=training-student --boilerplate=global` | `vona-module-a-aspect` |
34
+ | `pipe` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean pipe log -- --module=training-student --boilerplate=global` | `vona-module-a-aspect` |
35
+ | `interceptor` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean interceptor log -- --module=training-student --boilerplate=global` | `vona-module-a-aspect` |
36
+ | `guard` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean guard auth -- --module=training-student --boilerplate=global` | `vona-module-a-aspect` |
37
+ | `middleware` | `boilerplate` | `boilerplateGlobal` | `npm run vona :create:bean middleware trace -- --module=training-student --boilerplate=global` | `vona-module-a-aspect` |
38
+ | `ssrMenu` | `boilerplate` | `boilerplateWeb` | `npm run vona :create:bean ssrMenu menuTest -- --module=training-student --boilerplate=web` | `vona-module-a-ssr` |
39
+ | `ssrMenuGroup` | `boilerplate` | `boilerplateWeb` | `npm run vona :create:bean ssrMenuGroup groupTest -- --module=training-student --boilerplate=web` | `vona-module-a-ssr` |
40
40
 
41
41
  These backend entries come from the current `vonaModule.onions` metadata in `a-aspect` and `a-ssr`.
42
42
 
@@ -44,10 +44,10 @@ These backend entries come from the current `vonaModule.onions` metadata in `a-a
44
44
 
45
45
  ### Current built-in scenes with variants
46
46
 
47
- | Scene | Default metadata key | Named variant keys | Example command pattern | Source module |
48
- | ----------- | -------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------- |
49
- | `command` | `boilerplate` | `boilerplateCommandBulk`, `boilerplateCommandRow` | `npm run zova :create:bean command test -- --module=demo-student --boilerplate=commandRow` | `zova-module-a-command` |
50
- | `tableCell` | `boilerplate` | `boilerplateTableActionRow` | `npm run zova :create:bean tableCell test -- --module=demo-student --boilerplate=tableActionRow` | `zova-module-a-table` |
47
+ | Scene | Default metadata key | Named variant keys | Example command pattern | Source module |
48
+ | ----------- | -------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------- |
49
+ | `command` | `boilerplate` | `boilerplateCommandBulk`, `boilerplateCommandRow` | `npm run zova :create:bean command test -- --module=training-student --boilerplate=commandRow` | `zova-module-a-command` |
50
+ | `tableCell` | `boilerplate` | `boilerplateTableActionRow` | `npm run zova :create:bean tableCell test -- --module=training-student --boilerplate=tableActionRow` | `zova-module-a-table` |
51
51
 
52
52
  These frontend entries come from the current `zovaModule.onions` metadata in `a-command` and `a-table`.
53
53
 
@@ -32,10 +32,10 @@ Representative package metadata in the current repo shows the distinction clearl
32
32
 
33
33
  ### Module package
34
34
 
35
- Example: `vona/src/module/demo-student/package.json`
35
+ Example: `vona/src/suite/a-training/modules/training-student/package.json`
36
36
 
37
- - package name: `vona-module-demo-student`
38
- - title: `demo-student`
37
+ - package name: `vona-module-training-student`
38
+ - title: `training-student`
39
39
  - `vonaModule.dependencies` records module-level framework dependencies
40
40
 
41
41
  ### Suite package
@@ -74,6 +74,7 @@ A practical comparison is:
74
74
 
75
75
  Use this package map together with:
76
76
 
77
+ - [Suites and Modules](/fullstack/suites-and-modules)
77
78
  - [Backend Essentials](/backend/backend-essentials)
78
79
  - [Backend Foundation](/backend/foundation)
79
80
  - [Backend CLI](/backend/cli)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cabloy",
3
- "version": "5.1.61",
3
+ "version": "5.1.62",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "A Node.js fullstack framework",
6
6
  "keywords": [