cabloy 5.1.61 → 5.1.63

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 (230) 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 +55 -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 +27 -30
  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 +571 -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 +423 -682
  171. package/zova/src/suite/a-demo/modules/demo-basic/src/page/toolOne/render.tsx +5 -3
  172. package/zova/src/suite/a-home/modules/home-login/src/page/login/render.tsx +5 -3
  173. package/zova/src/suite/a-training/modules/training-student/cli/openapi.config.ts +9 -0
  174. package/zova/src/suite/a-training/modules/training-student/package.json +57 -0
  175. package/zova/src/suite/a-training/modules/training-student/src/.metadata/component/formFieldLevel.ts +31 -0
  176. package/zova/src/suite/a-training/modules/training-student/src/.metadata/index.ts +258 -0
  177. package/zova/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +7 -0
  178. package/zova/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
  179. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/baseURL.ts +5 -0
  180. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/index.ts +3 -0
  181. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +196 -0
  182. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +4146 -0
  183. package/zova/src/suite/a-training/modules/training-student/src/api/trainingStudent.ts +151 -0
  184. package/zova/src/suite/a-training/modules/training-student/src/apiSchema/trainingStudent.ts +43 -0
  185. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionDeleteForce.tsx +53 -0
  186. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionSummary.tsx +56 -0
  187. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.level.tsx +63 -0
  188. package/zova/src/suite/a-training/modules/training-student/src/component/formFieldLevel/controller.tsx +117 -0
  189. package/zova/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +9 -0
  190. package/zova/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +9 -0
  191. package/zova/src/suite/a-training/modules/training-student/src/index.ts +2 -0
  192. package/zova/src/suite/a-training/modules/training-student/src/model/student.ts +42 -0
  193. package/zova/src/suite/a-training/modules/training-student/tsconfig.build.json +13 -0
  194. package/zova/src/suite/a-training/modules/training-student/tsconfig.json +5 -0
  195. package/zova/src/suite/a-training/package.json +12 -0
  196. package/zova/src/suite/a-training/tsconfig.base.json +4 -0
  197. package/zova/src/suite/a-training/tsconfig.json +4 -0
  198. package/zova/src/suite/cabloy-basic/modules/basic-app/package.json +60 -0
  199. package/zova/src/suite/cabloy-basic/modules/basic-app/src/.metadata/index.ts +137 -0
  200. package/zova/src/suite/cabloy-basic/modules/basic-app/src/.metadata/locales.ts +7 -0
  201. package/zova/src/suite/cabloy-basic/modules/basic-app/src/.metadata/this.ts +2 -0
  202. package/zova/src/suite/cabloy-basic/modules/basic-app/src/bean/behavior.appModal.tsx +260 -0
  203. package/zova/src/suite/cabloy-basic/modules/basic-app/src/config/config.ts +39 -0
  204. package/zova/src/suite/cabloy-basic/modules/basic-app/src/config/locale/en-us.ts +7 -0
  205. package/zova/src/suite/cabloy-basic/modules/basic-app/src/config/locale/zh-cn.ts +7 -0
  206. package/zova/src/suite/cabloy-basic/modules/basic-app/src/index.ts +4 -0
  207. package/zova/src/suite/cabloy-basic/modules/basic-app/src/lib/appModalItem.ts +16 -0
  208. package/zova/src/suite/cabloy-basic/modules/basic-app/src/lib/index.ts +1 -0
  209. package/zova/src/suite/cabloy-basic/modules/basic-app/src/monkey.ts +38 -0
  210. package/zova/src/suite/cabloy-basic/modules/basic-app/src/monkeySys.ts +14 -0
  211. package/zova/src/suite/cabloy-basic/modules/basic-app/src/service/appModal.ts +89 -0
  212. package/zova/src/suite/cabloy-basic/modules/basic-app/src/types/appModal.ts +52 -0
  213. package/zova/src/suite/cabloy-basic/modules/basic-app/src/types/index.ts +1 -0
  214. package/zova/src/suite/cabloy-basic/modules/basic-app/tsconfig.build.json +13 -0
  215. package/zova/src/suite/cabloy-basic/modules/basic-app/tsconfig.json +5 -0
  216. package/zova/src/suite/cabloy-basic/modules/basic-commands/package.json +6 -1
  217. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/.metadata/index.ts +16 -0
  218. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/bean/command.alert.tsx +8 -14
  219. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/bean/command.confirm.tsx +10 -7
  220. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/bean/command.prompt.tsx +30 -0
  221. package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockForm/controller.tsx +5 -3
  222. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +29 -7
  223. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/select/controller.tsx +34 -11
  224. package/zova/src/suite/cabloy-basic/modules/basic-table/package.json +6 -1
  225. package/zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionDelete.tsx +4 -2
  226. package/zova/src/suite/cabloy-basic/package.json +1 -0
  227. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  228. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +3 -3
  229. package/zova/src/suite-vendor/a-zova/modules/a-table/src/lib/tableCell.ts +1 -1
  230. package/zova/src/suite-vendor/a-zova/package.json +2 -2
@@ -0,0 +1,496 @@
1
+ # Table + Resource CRUD Cookbook
2
+
3
+ This cookbook explains how Zova Table fits into Cabloy Basic’s resource-driven CRUD list pages.
4
+
5
+ Use this page when your next question is practical rather than framework-neutral:
6
+
7
+ - how should I assemble a standard resource list page?
8
+ - where do filter, toolbar, table, and pager blocks come from?
9
+ - how does `ModelResource` feed schema and data into `ZTable`?
10
+ - where should list-page customization happen without breaking the existing runtime?
11
+
12
+ Use this page together with:
13
+
14
+ - [Table Guide](/frontend/table-guide)
15
+ - [TableCell Authoring Cookbook](/frontend/table-cell-cookbook)
16
+ - [Zova Table Under the Hood](/frontend/zova-table-under-the-hood)
17
+ - [Model Resource Owner Pattern](/frontend/model-resource-owner-pattern)
18
+ - [Rest Resource Under the Hood](/frontend/rest-resource-under-the-hood)
19
+ - [Rest Resource Source Reading Map](/frontend/rest-resource-source-reading-map)
20
+ - [Backend Metadata to Frontend Table Actions](/fullstack/backend-metadata-to-frontend-table-actions)
21
+ - [Tutorial 2: Create Your First CRUD](/fullstack/tutorial-2-first-crud)
22
+ - [Tutorial 3: Frontend Metadata Sharing](/fullstack/tutorial-3-frontend-metadata-sharing)
23
+ - [Tutorial 5: Backend Contract Sharing](/fullstack/tutorial-5-backend-contract-sharing)
24
+
25
+ ## What this cookbook is for
26
+
27
+ If your next question is how the resource list page runtime is assembled under the hood, continue with [Resource List Page Deep Dive](/frontend/resource-list-page-deep-dive). If your next question is why row or bulk actions are visible or hidden, continue with [Table Action Visibility and Permission Flow Guide](/frontend/table-action-visibility-permission-flow-guide).
28
+
29
+ A Cabloy Basic CRUD list page is usually not authored as:
30
+
31
+ - one page-local table component
32
+ - one page-local fetch call
33
+ - one page-local pager state
34
+ - one page-local filter form
35
+
36
+ The more typical Zova-native shape is:
37
+
38
+ - one resource-owner model
39
+ - one page block that owns query and permissions
40
+ - several reusable blocks for filter, bulk toolbar, table, and pager
41
+ - schema and metadata driving the visible UI
42
+
43
+ That means the practical CRUD question becomes less:
44
+
45
+ - “how do I hand-build one list page?”
46
+
47
+ and more:
48
+
49
+ - “how do I plug my resource into the existing resource-page runtime?”
50
+
51
+ ## The shortest correct mental model
52
+
53
+ If you only remember one idea, remember this one:
54
+
55
+ > In Cabloy Basic CRUD list pages, `ZTable` is usually one block inside a larger resource-page runtime owned by `basic-page:blockPage` and backed by `ModelResource`.
56
+
57
+ That larger runtime usually owns:
58
+
59
+ - resource bootstrap
60
+ - list query state
61
+ - filter state
62
+ - permissions
63
+ - row schema
64
+ - paged response state
65
+ - coordination among filter, table, and pager
66
+
67
+ ## One running example through this guide: Student list page
68
+
69
+ To keep the guide concrete, the examples below all use the same teaching thread:
70
+
71
+ - resource: `training-student:student`
72
+ - list-page concerns: filter, row actions, create action, pagination
73
+ - metadata sources: backend row DTO and row-action metadata
74
+
75
+ This is the same general shape already used in the built-in specimen:
76
+
77
+ - `vona/src/suite-vendor/a-test/modules/test-rest/src/dto/productSelectResItem.tsx`
78
+
79
+ ## Step 1: Start from the generated CRUD contract, not from page-local UI
80
+
81
+ For a standard CRUD list page, begin with the generated backend thread.
82
+
83
+ The first useful entrypoint is still the CRUD generator:
84
+
85
+ ```bash
86
+ npm run vona :tools:crud student -- --module=training-student
87
+ ```
88
+
89
+ That generated thread already gives you the important contract anchors such as:
90
+
91
+ - backend entity
92
+ - select request DTO
93
+ - select response DTO
94
+ - select row-item DTO
95
+
96
+ A practical rule is:
97
+
98
+ - treat the generated resource contract as the list-page foundation
99
+ - refine schema and metadata before hand-building frontend list code
100
+
101
+ For the first generated CRUD walkthrough, see [Tutorial 2: Create Your First CRUD](/fullstack/tutorial-2-first-crud).
102
+
103
+ ## Step 2: Understand the block chain for a standard list page
104
+
105
+ A standard resource list page is usually declared through backend-owned block metadata like this:
106
+
107
+ ```tsx
108
+ ZovaRender.block('basic-page:blockPage', {
109
+ blocks: [
110
+ ZovaRender.block('basic-page:blockFilter'),
111
+ ZovaRender.block('basic-page:blockToolbarBulk', {
112
+ actions: [ZovaRender.tableActionBulk('basic-table:actionCreate')],
113
+ }),
114
+ ZovaRender.block('basic-page:blockTable'),
115
+ ZovaRender.block('basic-page:blockPager'),
116
+ ],
117
+ });
118
+ ```
119
+
120
+ That declaration is important because it shows the intended authoring direction clearly:
121
+
122
+ - backend or shared contract metadata chooses the block composition
123
+ - frontend block implementations provide the runtime behavior
124
+ - the page is assembled from existing building blocks rather than from ad hoc local wiring
125
+
126
+ A practical reading takeaway is:
127
+
128
+ - **the block list is the public page composition surface**
129
+ - **the frontend block controllers are the runtime owners**
130
+
131
+ ## Step 3: Know what `basic-page:blockPage` owns
132
+
133
+ The main runtime owner for a resource list page is:
134
+
135
+ - `basic-page:blockPage`
136
+
137
+ Its controller is responsible for:
138
+
139
+ - resolving the `ModelResource` selector for the current resource
140
+ - preparing page-level JSX/CEL support
141
+ - creating query state
142
+ - loading schema and paged data
143
+ - exposing `data`, `schemaRow`, `schemaFilter`, `permissions`, and `paged`
144
+ - refreshing table metadata when permissions change
145
+
146
+ This is one of the most important architecture facts about CRUD pages.
147
+
148
+ The page block does not only render layout. It owns the list-page resource state.
149
+
150
+ A practical rule is:
151
+
152
+ - if the concern is about resource query, schema, or permissions, start debugging in `blockPage`
153
+ - if the concern is about one visual block, continue to the corresponding block controller next
154
+
155
+ ## Step 4: Let `blockFilter` own filter-form behavior
156
+
157
+ The standard filter block is:
158
+
159
+ - `basic-page:blockFilter`
160
+
161
+ This block uses `ZForm` with:
162
+
163
+ - `schema={$$page.schemaFilter}`
164
+ - `schemaScene="filter"`
165
+ - inline layout
166
+ - page-owned filter data
167
+
168
+ Its job is not to duplicate the list query logic.
169
+
170
+ Its job is to:
171
+
172
+ - render the filter form from resource filter schema
173
+ - normalize submitted filter data
174
+ - call `$$page.onFilter(...)`
175
+
176
+ A practical rule is:
177
+
178
+ - if you need to refine which filter fields exist, start from backend filter-side metadata and schema
179
+ - if you need to refine how filter submission affects the list, inspect `blockFilter` and `blockPage.onFilter(...)`
180
+
181
+ ## Step 5: Let `blockToolbarBulk` own bulk-action display
182
+
183
+ The standard bulk toolbar block is:
184
+
185
+ - `basic-page:blockToolbarBulk`
186
+
187
+ This block is intentionally thin.
188
+
189
+ Its main job is to:
190
+
191
+ - inspect the configured bulk actions
192
+ - filter them by permission
193
+ - render each action through the page JSX runtime
194
+
195
+ That means the toolbar block usually should not become a second action-semantics layer.
196
+
197
+ A practical rule is:
198
+
199
+ - if the page only needs standard create or other bulk actions, keep the existing block and adjust the metadata
200
+ - if an action is reusable, prefer a reusable action render resource rather than page-local ad hoc code
201
+
202
+ ## Step 6: Let `blockTable` bridge page state into `ZTable`
203
+
204
+ The standard table block is:
205
+
206
+ - `basic-page:blockTable`
207
+
208
+ Its bridge role is very clear:
209
+
210
+ - render `ZTable`
211
+ - pass page data into `data`
212
+ - pass row schema into `schema`
213
+ - pass page CEL scope into `tableScope`
214
+ - capture the table controller through `controllerRef`
215
+
216
+ That means `blockTable` does not own list fetching or pagination logic.
217
+
218
+ It owns the handoff from page resource state to the reusable table runtime.
219
+
220
+ A practical rule is:
221
+
222
+ - if the table shows the wrong rows or wrong schema, inspect `blockPage` first
223
+ - if the handoff from page to table looks wrong, inspect `blockTable`
224
+ - if one column or cell renders incorrectly, continue into `a-table` and `tableCell` logic
225
+
226
+ ## Step 7: Let `blockPager` own page navigation UI
227
+
228
+ The standard pager block is:
229
+
230
+ - `basic-page:blockPager`
231
+
232
+ This block reads the paged response from `$$page.paged` and renders:
233
+
234
+ - total items
235
+ - total pages
236
+ - previous-page button
237
+ - current page indicator
238
+ - next-page button
239
+
240
+ It delegates actual page movement back to the page block through `gotoPage(...)`.
241
+
242
+ That means the pager block owns the visible pager UI, while the page block still owns pagination state.
243
+
244
+ A practical rule is:
245
+
246
+ - if the pager UI looks wrong, inspect `blockPager`
247
+ - if paging requests or totals are wrong, inspect `blockPage` and the resource model/query side
248
+
249
+ ## Step 8: Know where the table columns and row actions really come from
250
+
251
+ In a standard CRUD list page, the table contents are usually not first defined in the block controller.
252
+
253
+ They come from the backend resource contract, especially row DTO metadata.
254
+
255
+ A representative example is:
256
+
257
+ ```tsx
258
+ @Api.field(
259
+ v.title($locale('Operations')),
260
+ ZovaRender.order(1, 'max'),
261
+ ZovaRender.cell('basic-table:actionOperationsRow', {
262
+ actions: [
263
+ ZovaRender.tableActionRow('basic-table:actionUpdate'),
264
+ ZovaRender.tableActionRow('basic-table:actionDelete'),
265
+ ],
266
+ }),
267
+ )
268
+ _operationsRow?: unknown;
269
+ ```
270
+
271
+ This is the practical reverse-sharing model:
272
+
273
+ - the backend row contract chooses the table cell resource identity
274
+ - the frontend table runtime resolves that resource
275
+ - the page block and table block do not need page-local hard-coded row-action wiring
276
+
277
+ For the built-in metadata-sharing teaching path, see [Tutorial 3: Frontend Metadata Sharing](/fullstack/tutorial-3-frontend-metadata-sharing).
278
+
279
+ For the forward-chain row-action teaching path, see [Tutorial 5: Backend Contract Sharing](/fullstack/tutorial-5-backend-contract-sharing).
280
+
281
+ ## Step 9: The common extension points
282
+
283
+ For standard CRUD list pages, most customization should happen in one of these places.
284
+
285
+ ### Extension point A: backend row schema metadata
286
+
287
+ Use this when:
288
+
289
+ - a field should change order
290
+ - a column should be visible or hidden
291
+ - a field should use a different built-in or custom `tableCell`
292
+
293
+ This is usually the first and best extension point.
294
+
295
+ ### Extension point B: backend block composition metadata
296
+
297
+ Use this when:
298
+
299
+ - the page should add or remove a standard block
300
+ - the page should include bulk actions
301
+ - the page should change list-page composition order
302
+
303
+ ### Extension point C: custom `tableCell` resources
304
+
305
+ Use this when:
306
+
307
+ - a field needs business-specific table rendering
308
+ - one action cell should be reusable across pages
309
+ - one operations row should orchestrate several child actions
310
+
311
+ For concrete patterns, continue with [TableCell Authoring Cookbook](/frontend/table-cell-cookbook).
312
+
313
+ ### Extension point D: page-level block implementation
314
+
315
+ Use this only when:
316
+
317
+ - the existing block runtime is structurally insufficient
318
+ - the behavior really belongs to the block runtime rather than to metadata
319
+ - you have already confirmed that schema, metadata, and cell resources are not enough
320
+
321
+ A practical rule is:
322
+
323
+ - prefer metadata and cell resources before changing block controllers
324
+
325
+ ## Step 10: Distinguish list page from entry page
326
+
327
+ A common source-reading mistake is to mix `basic-page` list runtime with `basic-pageentry` form runtime.
328
+
329
+ They are related but they do not own the same concerns.
330
+
331
+ ### `basic-page` list runtime
332
+
333
+ Typical responsibilities:
334
+
335
+ - filter form
336
+ - bulk toolbar
337
+ - table
338
+ - pager
339
+ - list query
340
+ - row schema and permissions
341
+
342
+ ### `basic-pageentry` entry runtime
343
+
344
+ Typical responsibilities:
345
+
346
+ - view/create/edit form scene
347
+ - form schema and form data
348
+ - form submission
349
+ - page dirty state and page title
350
+
351
+ A practical rule is:
352
+
353
+ - if the page is about rows in a list, stay in `basic-page`
354
+ - if the page is about one entry form, stay in `basic-pageentry`
355
+
356
+ This distinction prevents a lot of source-reading confusion.
357
+
358
+ ## Pattern 1: The standard generated CRUD list page
359
+
360
+ Use this pattern when:
361
+
362
+ - the CRUD generator already created the resource thread
363
+ - built-in page blocks are enough
364
+ - backend metadata can express the list behavior
365
+
366
+ Recommended path:
367
+
368
+ 1. generate the CRUD thread
369
+ 2. inspect row DTO metadata
370
+ 3. keep the standard block chain
371
+ 4. verify the list page in Admin
372
+
373
+ This should be the default choice for first CRUD pages.
374
+
375
+ ## Pattern 2: Add a filter field through contract refinement
376
+
377
+ Use this pattern when:
378
+
379
+ - the list page needs one more search field
380
+ - the field belongs in the resource contract
381
+ - the filter form should stay schema-driven
382
+
383
+ Recommended path:
384
+
385
+ 1. refine backend field and query DTO metadata
386
+ 2. verify `schemaFilter`
387
+ 3. reuse `basic-page:blockFilter`
388
+ 4. avoid page-local manual filter UI unless really necessary
389
+
390
+ ## Pattern 3: Add row actions through backend metadata
391
+
392
+ Use this pattern when:
393
+
394
+ - the row should expose update/delete/summary/deleteForce-like actions
395
+ - the action identity belongs in the contract
396
+ - the frontend should reuse `tableCell` resources
397
+
398
+ Recommended path:
399
+
400
+ 1. define or refine backend row-action metadata
401
+ 2. point the action cell to built-in or custom table-cell resources
402
+ 3. if needed, add generated API and thin model helpers
403
+ 4. verify the list page row actions in Admin
404
+
405
+ ## Pattern 4: Add a business-specific cell for one field
406
+
407
+ Use this pattern when:
408
+
409
+ - one field such as `level`, `status`, or `score` needs module-owned UI behavior
410
+ - the list page should remain resource-driven overall
411
+
412
+ Recommended path:
413
+
414
+ 1. create a custom `tableCell` bean
415
+ 2. point backend field metadata to it
416
+ 3. keep `basic-page:blockTable` and `ZTable` unchanged
417
+
418
+ This is the preferred path when the customization belongs to a field rather than to page structure.
419
+
420
+ ## Common mistakes to avoid
421
+
422
+ ### Mistake 1: Rebuilding list-page fetch state inside the table block
423
+
424
+ `blockTable` is only the page-to-table bridge. Query ownership lives in `blockPage` and `ModelResource`.
425
+
426
+ ### Mistake 2: Hand-writing table columns before checking row schema metadata
427
+
428
+ For most CRUD pages, the row schema is the first source of truth.
429
+
430
+ ### Mistake 3: Mixing list-page and entry-page concerns
431
+
432
+ `basic-page` and `basic-pageentry` are related, but they own different runtime responsibilities.
433
+
434
+ ### Mistake 4: Modifying block controllers when metadata or `tableCell` resources are enough
435
+
436
+ Most business customization should happen before block-controller changes.
437
+
438
+ ### Mistake 5: Treating row actions as only frontend-local UI
439
+
440
+ In Cabloy, row actions often belong to a broader contract chain involving backend metadata, generated API, model helpers, and table-cell resources.
441
+
442
+ ## A practical authoring order
443
+
444
+ If you want the shortest path to a real CRUD list page, use this order:
445
+
446
+ 1. generate or confirm the backend CRUD contract thread
447
+ 2. confirm the resource-owner model already exposes the required schemas and permissions
448
+ 3. keep the standard `blockPage -> blockFilter -> blockToolbarBulk -> blockTable -> blockPager` chain
449
+ 4. refine backend row metadata for visible columns and row actions
450
+ 5. reuse built-in `tableCell` resources first
451
+ 6. add custom `tableCell` resources only where the UI becomes business-specific
452
+ 7. change block controllers only when the existing runtime is structurally insufficient
453
+ 8. continue with [Table Guide](/frontend/table-guide) for the public `ZTable` surface
454
+ 9. continue with [TableCell Authoring Cookbook](/frontend/table-cell-cookbook) for custom cell patterns
455
+ 10. continue with [Backend Metadata to Frontend Table Actions](/fullstack/backend-metadata-to-frontend-table-actions) when the visible row actions belong to a larger contract-loop chain
456
+ 11. continue with [Zova Table Under the Hood](/frontend/zova-table-under-the-hood) when you want the controller-level runtime explanation
457
+ 12. continue with [Zova Table Source Reading Map](/frontend/zova-table-source-reading-map) when you need targeted file-order guidance for the table runtime
458
+
459
+ ## Verification checklist
460
+
461
+ When authoring or documenting a resource CRUD list page, verify in this order:
462
+
463
+ 1. confirm the generated or existing backend CRUD contract files are present
464
+ 2. confirm the block composition still matches the intended standard page chain
465
+ 3. confirm row schema metadata points to the intended built-in or custom render resources
466
+ 4. make sure the local dev workflow is running:
467
+
468
+ ```bash
469
+ npm run dev
470
+ ```
471
+
472
+ 5. open `http://localhost:7102/admin/`
473
+ 6. enter the target list page and verify:
474
+ - filter works
475
+ - bulk actions render correctly
476
+ - table columns and row actions match metadata
477
+ - pager updates the list correctly
478
+ 7. if you changed docs, build the docs site:
479
+
480
+ ```bash
481
+ npm run docs:build
482
+ ```
483
+
484
+ ## Final takeaway
485
+
486
+ A good Cabloy Basic CRUD list page is usually not a custom page-local table stack.
487
+
488
+ It is a resource-driven composition of:
489
+
490
+ - one resource-owner model
491
+ - one page block
492
+ - one schema-driven table runtime
493
+ - several reusable page blocks
494
+ - optional custom `tableCell` resources
495
+
496
+ That is the path that keeps CRUD list pages consistent, extensible, and aligned with the Zova-native architecture.