@jskit-ai/agent-docs 0.1.130 → 0.1.132

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 (171) hide show
  1. package/guide/agent/app-extras/assistant.md +29 -605
  2. package/guide/agent/app-extras/mobile-capacitor.md +29 -362
  3. package/guide/agent/app-extras/realtime.md +29 -277
  4. package/guide/agent/app-setup/a-more-interesting-shell.md +44 -815
  5. package/guide/agent/app-setup/authentication.md +43 -1073
  6. package/guide/agent/app-setup/console.md +26 -298
  7. package/guide/agent/app-setup/database-layer.md +110 -790
  8. package/guide/agent/app-setup/initial-scaffolding.md +50 -784
  9. package/guide/agent/app-setup/multi-homing.md +39 -712
  10. package/guide/agent/app-setup/quickstart.md +43 -179
  11. package/guide/agent/app-setup/users.md +34 -353
  12. package/guide/agent/index.md +16 -23
  13. package/package.json +2 -2
  14. package/patterns/INDEX.md +7 -7
  15. package/patterns/child-cruds.md +3 -3
  16. package/patterns/client-requests.md +6 -6
  17. package/patterns/crud-authoring.md +94 -0
  18. package/patterns/crud-links.md +1 -1
  19. package/patterns/feature-package/PATTERN.md +108 -0
  20. package/patterns/feature-package/example/booking-engine/package.json +48 -0
  21. package/patterns/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +33 -0
  22. package/patterns/feature-package/example/booking-engine/src/server/actions.js +26 -0
  23. package/patterns/feature-package/example/booking-engine/src/server/inputSchemas.js +19 -0
  24. package/patterns/feature-package/example/variations/AvailabilityEngineProvider.js +31 -0
  25. package/patterns/feature-package/example/variations/InvoiceRollupProvider.js +36 -0
  26. package/patterns/feature-package/example/variations/customKnexRepository.js +34 -0
  27. package/patterns/feature-package/example/variations/orchestratorService.js +23 -0
  28. package/patterns/filters.md +8 -8
  29. package/patterns/live-actions.md +5 -18
  30. package/patterns/minimal-foundation/PATTERN.md +98 -0
  31. package/patterns/minimal-foundation/example/.nvmrc +1 -0
  32. package/patterns/minimal-foundation/example/AGENTS.md +17 -0
  33. package/patterns/minimal-foundation/example/Procfile +2 -0
  34. package/patterns/minimal-foundation/example/app.json +14 -0
  35. package/patterns/minimal-foundation/example/bin/develop.js +71 -0
  36. package/patterns/minimal-foundation/example/bin/server.js +8 -0
  37. package/patterns/minimal-foundation/example/config/public.js +40 -0
  38. package/patterns/minimal-foundation/example/config/server.js +1 -0
  39. package/patterns/minimal-foundation/example/config/surfaceAccessPolicies.js +3 -0
  40. package/patterns/minimal-foundation/example/eslint.config.mjs +19 -0
  41. package/patterns/minimal-foundation/example/favicon.svg +7 -0
  42. package/patterns/minimal-foundation/example/gitignore +9 -0
  43. package/patterns/minimal-foundation/example/index.html +13 -0
  44. package/patterns/minimal-foundation/example/jsconfig.json +8 -0
  45. package/patterns/minimal-foundation/example/package.json +57 -0
  46. package/patterns/minimal-foundation/example/packages/main/package.json +42 -0
  47. package/patterns/minimal-foundation/example/packages/main/src/shared/index.js +10 -0
  48. package/patterns/minimal-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  49. package/patterns/minimal-foundation/example/playwright.config.mjs +31 -0
  50. package/patterns/minimal-foundation/example/server/lib/runtimeEnv.js +45 -0
  51. package/patterns/minimal-foundation/example/server/lib/surfaceRuntime.js +10 -0
  52. package/patterns/minimal-foundation/example/server.js +195 -0
  53. package/patterns/minimal-foundation/example/src/App.vue +13 -0
  54. package/patterns/minimal-foundation/example/src/main.js +85 -0
  55. package/patterns/minimal-foundation/example/src/pages/home/index.vue +48 -0
  56. package/patterns/minimal-foundation/example/src/pages/home.vue +13 -0
  57. package/patterns/minimal-foundation/example/src/views/NotFound.vue +13 -0
  58. package/patterns/minimal-foundation/example/tests/client/smoke.vitest.js +7 -0
  59. package/patterns/minimal-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  60. package/patterns/minimal-foundation/example/tests/server/smoke.test.js +16 -0
  61. package/patterns/minimal-foundation/example/vite.config.mjs +81 -0
  62. package/patterns/page-scaffolding.md +20 -17
  63. package/patterns/placements.md +17 -15
  64. package/patterns/row-policies.md +4 -5
  65. package/patterns/server-search.md +3 -3
  66. package/patterns/shell-foundation/PATTERN.md +104 -0
  67. package/patterns/shell-foundation/example/.nvmrc +1 -0
  68. package/patterns/shell-foundation/example/AGENTS.md +17 -0
  69. package/patterns/shell-foundation/example/Procfile +2 -0
  70. package/patterns/shell-foundation/example/app.json +14 -0
  71. package/patterns/shell-foundation/example/bin/develop.js +71 -0
  72. package/patterns/shell-foundation/example/bin/server.js +8 -0
  73. package/patterns/shell-foundation/example/config/public.js +40 -0
  74. package/patterns/shell-foundation/example/config/server.js +1 -0
  75. package/patterns/shell-foundation/example/config/surfaceAccessPolicies.js +3 -0
  76. package/patterns/shell-foundation/example/eslint.config.mjs +19 -0
  77. package/patterns/shell-foundation/example/favicon.svg +7 -0
  78. package/patterns/shell-foundation/example/gitignore +9 -0
  79. package/patterns/shell-foundation/example/index.html +13 -0
  80. package/patterns/shell-foundation/example/jsconfig.json +8 -0
  81. package/patterns/shell-foundation/example/package.json +59 -0
  82. package/patterns/shell-foundation/example/packages/main/package.json +56 -0
  83. package/patterns/shell-foundation/example/packages/main/src/client/index.js +9 -0
  84. package/patterns/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +18 -0
  85. package/patterns/shell-foundation/example/packages/main/src/shared/index.js +10 -0
  86. package/patterns/shell-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  87. package/patterns/shell-foundation/example/playwright.config.mjs +31 -0
  88. package/patterns/shell-foundation/example/server/lib/runtimeEnv.js +45 -0
  89. package/patterns/shell-foundation/example/server/lib/surfaceRuntime.js +10 -0
  90. package/patterns/shell-foundation/example/server.js +195 -0
  91. package/patterns/shell-foundation/example/src/App.vue +11 -0
  92. package/patterns/shell-foundation/example/src/components/ShellLayout.vue +12 -0
  93. package/patterns/shell-foundation/example/src/components/menus/MenuLinkItem.vue +30 -0
  94. package/patterns/shell-foundation/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  95. package/patterns/shell-foundation/example/src/components/menus/TabLinkItem.vue +42 -0
  96. package/patterns/shell-foundation/example/src/error.js +19 -0
  97. package/patterns/shell-foundation/example/src/main.js +85 -0
  98. package/patterns/shell-foundation/example/src/pages/home/index.vue +116 -0
  99. package/patterns/shell-foundation/example/src/pages/home/settings/general/index.vue +40 -0
  100. package/patterns/shell-foundation/example/src/pages/home/settings/index.vue +7 -0
  101. package/patterns/shell-foundation/example/src/pages/home/settings.vue +109 -0
  102. package/patterns/shell-foundation/example/src/pages/home.vue +20 -0
  103. package/patterns/shell-foundation/example/src/placement.js +56 -0
  104. package/patterns/shell-foundation/example/src/placementTopology.js +149 -0
  105. package/patterns/shell-foundation/example/src/views/NotFound.vue +13 -0
  106. package/patterns/shell-foundation/example/tests/client/smoke.vitest.js +7 -0
  107. package/patterns/shell-foundation/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  108. package/patterns/shell-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  109. package/patterns/shell-foundation/example/tests/server/smoke.test.js +16 -0
  110. package/patterns/shell-foundation/example/vite.config.mjs +81 -0
  111. package/patterns/ui-contract.md +56 -0
  112. package/patterns/ui-testing.md +10 -12
  113. package/reference/autogen/KERNEL_MAP.md +29 -107
  114. package/reference/autogen/PATTERN_INDEX.md +230 -0
  115. package/reference/autogen/README.md +4 -8
  116. package/reference/autogen/packages/agent-docs.md +259 -0
  117. package/reference/autogen/packages/assistant-core.md +3 -3
  118. package/reference/autogen/packages/assistant-runtime.md +32 -17
  119. package/reference/autogen/packages/auth-core.md +31 -33
  120. package/reference/autogen/packages/auth-provider-local-core.md +4 -12
  121. package/reference/autogen/packages/auth-provider-local-db-core.md +4 -4
  122. package/reference/autogen/packages/auth-provider-supabase-core.md +14 -18
  123. package/reference/autogen/packages/auth-web.md +42 -22
  124. package/reference/autogen/packages/console-core.md +8 -25
  125. package/reference/autogen/packages/console-web.md +5 -5
  126. package/reference/autogen/packages/crud-core.md +61 -17
  127. package/reference/autogen/packages/database-runtime-mysql.md +12 -2
  128. package/reference/autogen/packages/database-runtime-postgres.md +12 -2
  129. package/reference/autogen/packages/database-runtime.md +26 -25
  130. package/reference/autogen/packages/google-rewarded-core.md +19 -104
  131. package/reference/autogen/packages/http-runtime.md +4 -8
  132. package/reference/autogen/packages/http-web.md +32 -0
  133. package/reference/autogen/packages/json-rest-api-core.md +4 -6
  134. package/reference/autogen/packages/kernel.md +109 -390
  135. package/reference/autogen/packages/mobile-capacitor.md +2 -13
  136. package/reference/autogen/packages/realtime.md +29 -26
  137. package/reference/autogen/packages/resource-crud-core.md +6 -0
  138. package/reference/autogen/packages/shell-web.md +69 -54
  139. package/reference/autogen/packages/storage-runtime.md +3 -3
  140. package/reference/autogen/packages/uploads-image-web.md +0 -1
  141. package/reference/autogen/packages/uploads-runtime.md +3 -3
  142. package/reference/autogen/packages/users-core.md +45 -90
  143. package/reference/autogen/packages/users-web.md +5 -7
  144. package/reference/autogen/packages/workspaces-core.md +53 -74
  145. package/reference/autogen/packages/workspaces-web.md +15 -16
  146. package/reference/autogen/tooling/jskit-catalog.md +34 -0
  147. package/reference/autogen/tooling/testUtils.md +4 -4
  148. package/skills/jskit/SKILL.md +36 -28
  149. package/skills/jskit/agents/openai.yaml +2 -2
  150. package/skills/jskit/references/app-operations.md +68 -53
  151. package/skills/jskit/references/crud-operations.md +58 -106
  152. package/skills/jskit/references/material-3.md +105 -0
  153. package/skills/jskit/references/ui-operations.md +41 -44
  154. package/templates/app/AGENTS.md +7 -3
  155. package/guide/agent/app-setup/upgrade-beta-1-to-final.md +0 -252
  156. package/guide/agent/app-setup/working-with-the-jskit-cli.md +0 -325
  157. package/guide/agent/generators/advanced-cruds.md +0 -1935
  158. package/guide/agent/generators/crud-generators.md +0 -948
  159. package/guide/agent/generators/intro.md +0 -65
  160. package/guide/agent/generators/row-policies.md +0 -537
  161. package/guide/agent/generators/ui-generators.md +0 -690
  162. package/patterns/crud-scaffolding.md +0 -198
  163. package/patterns/generated-ui-contract-tracking.md +0 -66
  164. package/reference/autogen/packages/assistant.md +0 -68
  165. package/reference/autogen/packages/crud-server-generator.md +0 -215
  166. package/reference/autogen/packages/crud-ui-generator.md +0 -192
  167. package/reference/autogen/packages/feature-server-generator.md +0 -65
  168. package/reference/autogen/packages/ui-generator.md +0 -127
  169. package/reference/autogen/tooling/create-app.md +0 -317
  170. package/reference/autogen/tooling/jskit-cli.md +0 -933
  171. package/reference/autogen/tooling/test-support.md +0 -27
@@ -1,690 +0,0 @@
1
- <!-- Generated by `npm run agent-docs:build` from `packages/agent-docs/site/guide/generators/ui-generators.md`. Do not edit manually. -->
2
-
3
- # UI Generators
4
-
5
- The earlier chapters already used `ui-generator` a little when we added:
6
-
7
- - the `Alerts Widget`
8
- - the `Profile` settings page
9
- - the `Notifications` settings page
10
-
11
- This chapter steps back and treats that tool as a subject in its own right.
12
-
13
- Use `ui-generator` when you want app-owned UI that is **not** a CRUD route tree.
14
-
15
- That usually means one of four jobs:
16
-
17
- - create a route page
18
- - create a small placed UI element
19
- - turn an existing page into a host for child routes
20
- - add a generic placement seam to an existing Vue file
21
-
22
- ## `ui-generator` `@jskit-ai/ui-generator` `(0.1.22)`
23
-
24
- `ui-generator` has four subcommands:
25
-
26
- - `page`
27
- - `placed-element`
28
- - `add-subpages`
29
- - `outlet`
30
-
31
- They are all about app-owned UI, but they solve different problems.
32
-
33
- The easiest way to understand them is:
34
-
35
- - `page` creates a route and the link that reaches it
36
- - `placed-element` creates a reusable component and places it somewhere
37
- - `add-subpages` upgrades a page into a routed child-page host
38
- - `outlet` adds only a placement seam, without routed child-page behavior
39
-
40
- ## The simplest case: `page`
41
-
42
- Start with the most common command:
43
-
44
- ```bash
45
- npx jskit generate ui-generator page \
46
- home/reports/index.vue \
47
- --name "Reports"
48
- ```
49
-
50
- This command creates a page at:
51
-
52
- ```text
53
- src/pages/home/reports/index.vue
54
- ```
55
-
56
- and it also appends a matching link placement into:
57
-
58
- ```text
59
- src/placement.js
60
- ```
61
-
62
- That second part is important. `page` is not just a file generator. It also makes the new page reachable inside the shell.
63
-
64
- In a fresh `home` surface app, the generated placement looks like a normal shell menu link. In the throwaway app used to verify this chapter, the command reported:
65
-
66
- ```text
67
- Generated UI page "/reports" at src/pages/home/reports/index.vue.
68
- Touched files (2):
69
- - src/pages/home/reports/index.vue
70
- - src/placement.js
71
- ```
72
-
73
- That is the baseline behavior of `page`:
74
-
75
- - one app-owned page file
76
- - one app-owned placement entry
77
-
78
- The important default is this:
79
-
80
- - if JSKIT sees no nearer routed host, the new page gets a normal shell/menu placement
81
- - if JSKIT does see a nearer routed host, the new page gets linked into that host instead
82
-
83
- Open the app to see a real `/reports` page plus a real shell link for it.
84
-
85
- ### Customizing the generated menu link
86
-
87
- The generated page command does not ask for an icon up front. That is deliberate. The command's job is to create the route and the matching placement entry, not to force every menu detail during generation.
88
-
89
- If you want to customize the link afterwards, edit the placement entry that `page` wrote into `src/placement.js`.
90
-
91
- That is where things such as:
92
-
93
- - `label`
94
- - `order`
95
- - `icon`
96
- - `owner`
97
- - `surfaces`
98
-
99
- normally get adjusted.
100
-
101
- The important icon rule is this:
102
-
103
- - inside `src/placement.js` menu metadata, import app-specific icons from `@mdi/js` and pass the path constant
104
- - only use raw `mdi-*` strings for the small set of shell-web core icons that JSKIT normalizes
105
- - inside normal Vue component props, use the same `@mdi/js` path constants or a Vuetify alias
106
-
107
- So this is a valid menu-placement customization:
108
-
109
- ```js
110
- import { mdiChartBoxOutline } from "@mdi/js";
111
-
112
- props: {
113
- label: "Reports",
114
- to: "/reports",
115
- icon: mdiChartBoxOutline
116
- }
117
- ```
118
-
119
- If you later open the generated page file itself and add a Vuetify icon to the template, use the same `@mdi/js` pattern:
120
-
121
- ```vue
122
- <script setup>
123
- import { mdiChartBoxOutline } from "@mdi/js";
124
- </script>
125
-
126
- <v-icon :icon="mdiChartBoxOutline" />
127
- ```
128
-
129
- This keeps icon imports local and tree-shakeable. Do not import the whole `@mdi/js` namespace just to look up icon names dynamically.
130
-
131
- ## What `page` is really good at
132
-
133
- The reason `page` is the primary subcommand is that it understands more than just "create this file".
134
-
135
- It also understands shell topology.
136
-
137
- If you create a page that lives under a parent page which has already been upgraded into a child-page host, `page` does **not** keep treating it as a top-level shell entry. It changes behavior and links the new page into the nearest host instead.
138
-
139
- That is what makes it fit naturally with the rest of JSKIT.
140
-
141
- ### The important `page` overrides
142
-
143
- The happy path is intentionally simple, but `page` also has a small set of override options that matter as soon as you stop accepting the defaults.
144
-
145
- #### `--link-placement`
146
-
147
- Use this when the generated page link should go somewhere other than the generator's inferred default.
148
-
149
- Typical reasons:
150
-
151
- - you want the page in a different shell menu
152
- - you want the page link inside a specific existing semantic placement
153
- - you do not want the link to land in the normal top-level menu
154
-
155
- For example, if a page should appear in a settings menu rather than the shell drawer, `--link-placement` is the override that says so.
156
-
157
- The value should normally be semantic, such as `shell.primary-nav`, `page.section-nav`, or another `area.slot` placement from `jskit list-placements`. Concrete `host:position` outlets remain an escape hatch, not the default authoring path.
158
-
159
- #### `--link-to`
160
-
161
- Use this when you want to override the generated `props.to` value.
162
-
163
- This is especially useful for nested pages, because when JSKIT detects a parent subpages host it normally infers a relative link like:
164
-
165
- ```js
166
- to: "./exports"
167
- ```
168
-
169
- That default is usually correct. But if the host needs a different local target shape, or you are wiring a link into a custom outlet with different expectations, `--link-to` is the escape hatch.
170
-
171
- So the rough rule is:
172
-
173
- - if the link destination is obvious from the route tree, let JSKIT infer it
174
- - if you need a very specific link destination, use `--link-to`
175
-
176
- #### `--force`
177
-
178
- Use this only when the target page file already exists and you intentionally want to overwrite it.
179
-
180
- That is most common when:
181
-
182
- - you are regenerating an experimental page
183
- - you want to throw away the current file and replace it with fresh scaffold
184
-
185
- It is not a routing option. It is simply an overwrite guard.
186
-
187
- ## Turning a page into a child-page host: `add-subpages`
188
-
189
- Suppose `Reports` should stop being a single screen and start becoming a section with child routes under it.
190
-
191
- Run:
192
-
193
- ```bash
194
- npx jskit generate ui-generator add-subpages \
195
- home/reports/index.vue \
196
- --title "Reports" \
197
- --subtitle "View and manage reporting modules."
198
- ```
199
-
200
- This upgrades `src/pages/home/reports/index.vue` into a routed host page.
201
-
202
- On the first use in a fresh app, it also installs the support shell component:
203
-
204
- ```text
205
- src/components/SectionContainerShell.vue
206
- ```
207
-
208
- In the verified throwaway app, the command reported:
209
-
210
- ```text
211
- Enabled subpages in src/pages/home/reports/index.vue for "/reports" using outlet target "reports:sub-pages".
212
- Touched files (2):
213
- - src/components/SectionContainerShell.vue
214
- - src/pages/home/reports/index.vue
215
- ```
216
-
217
- After the command, the page gains three important pieces:
218
-
219
- - `SectionContainerShell`
220
- - a `ShellOutlet` for the child-page tabs
221
- - `RouterView`
222
-
223
- That lets the page keep rendering shared content while child routes render underneath it.
224
-
225
- This is the first big distinction in this chapter:
226
-
227
- - a plain page is just a page
228
- - a subpages host is a page plus routed child-page structure
229
-
230
- If what you need is routed children, `add-subpages` is the right tool.
231
-
232
- ### When `page` becomes a tab-like child instead of a top-level menu entry
233
-
234
- This is the key transition to understand.
235
-
236
- Before `add-subpages`, `page` usually creates:
237
-
238
- - a page file
239
- - a top-level shell link
240
-
241
- After `add-subpages`, that same `page` command may create:
242
-
243
- - a page file
244
- - a child link inside the nearest parent host outlet
245
-
246
- That is why nested pages often feel "tab-like" even though the generator command is still just `page`.
247
-
248
- The route page is still a normal page file. What changes is the inferred placement target:
249
-
250
- - no parent host found -> shell/menu entry
251
- - nearest parent host found -> child link inside that host
252
-
253
- So JSKIT is not switching to a different generator. The route tree has a routed host above the new page, so the inferred placement behavior follows that host.
254
-
255
- ### Making a child page the default landing route
256
-
257
- This is important enough to state explicitly: if a routed host has child pages, and you want the bare parent URL to open one child immediately, use an explicit redirect.
258
-
259
- Do **not** try to make the app "guess the first tab". Do **not** infer it from placement order. Keep the target explicit.
260
-
261
- The standard pattern is:
262
-
263
- ```vue
264
- <script setup>
265
- import { redirectToChild } from "@jskit-ai/kernel/client/pageRedirects";
266
-
267
- definePage({
268
- redirect: redirectToChild("exports")
269
- });
270
- </script>
271
- ```
272
-
273
- If this is placed on the host page, opening `/reports` lands on `/reports/exports`.
274
-
275
- This is also the right pattern when the host page still renders shared content such as a title, tabs, summary panel, or `RouterView`. The parent route remains the host, and the child page simply becomes the default destination under it.
276
-
277
- Why this is the recommended pattern:
278
-
279
- - the destination is explicit and stable
280
- - it survives later placement reordering
281
- - it does not depend on which child link happens to render first
282
- - it is easy to change later by editing one child segment
283
-
284
- This is one of the most common things people want once they start using child-page hosts. Treat it as normal JSKIT routing, not a special hack.
285
-
286
- ## Nested pages under an `index.vue` host
287
-
288
- Once `Reports` is a host, create a child page under it:
289
-
290
- ```bash
291
- npx jskit generate ui-generator page \
292
- home/reports/index/exports/index.vue \
293
- --name "Exports"
294
- ```
295
-
296
- This path shape matters.
297
-
298
- Because the parent host is:
299
-
300
- ```text
301
- src/pages/home/reports/index.vue
302
- ```
303
-
304
- the child belongs under:
305
-
306
- ```text
307
- src/pages/home/reports/index/exports/index.vue
308
- ```
309
-
310
- That `index/...` folder segment is not an odd JSKIT convention. It is the real nesting rule for children of an `index.vue` route host.
311
-
312
- And this is where `page` becomes interesting again.
313
-
314
- In the throwaway app, the command reported:
315
-
316
- ```text
317
- Generated UI page "/reports/exports" at src/pages/home/reports/index/exports/index.vue.
318
- Touched files (2):
319
- - src/pages/home/reports/index/exports/index.vue
320
- - src/placement.js
321
- ```
322
-
323
- But the placement it wrote was **not** another top-level shell link.
324
-
325
- Instead, it targeted the host outlet:
326
-
327
- ```text
328
- page.section-nav
329
- ```
330
-
331
- with the host owner and relative route:
332
-
333
- ```js
334
- owner: "reports",
335
- to: "./exports"
336
- ```
337
-
338
- That is exactly the behavior you want:
339
-
340
- - `Reports` stays the host page
341
- - `Exports` becomes a child tab under it
342
- - the child route renders under the parent instead of becoming another top-level menu entry
343
-
344
- This is also why `--link-placement` and `--link-to` are often unnecessary in the default nested case. Once the host exists, JSKIT already knows the likely semantic placement, owner, and relative `to` value. The link renderer comes from `src/placementTopology.js`.
345
-
346
- ## Nested pages under a file-route host
347
-
348
- There is a second nesting shape that matters just as much.
349
-
350
- Create a dynamic file-route page:
351
-
352
- ```bash
353
- npx jskit generate ui-generator page \
354
- home/contacts/[contactId].vue \
355
- --name "Contact"
356
- ```
357
-
358
- Then upgrade that page into a host:
359
-
360
- ```bash
361
- npx jskit generate ui-generator add-subpages \
362
- home/contacts/[contactId].vue \
363
- --title "Contact" \
364
- --subtitle "Contact activity and notes."
365
- ```
366
-
367
- This time the parent is a file route, not an `index.vue` route.
368
-
369
- So the child-page path is different:
370
-
371
- ```bash
372
- npx jskit generate ui-generator page \
373
- home/contacts/[contactId]/notes/index.vue \
374
- --name "Notes"
375
- ```
376
-
377
- That is the other important nesting rule:
378
-
379
- - if the host is an `index.vue` page, children go under `index/...`
380
- - if the host is a file-route page, children go under that page's directory
381
-
382
- In the verified throwaway app, this command created:
383
-
384
- ```text
385
- src/pages/home/contacts/[contactId]/notes/index.vue
386
- ```
387
-
388
- and its link placement targeted:
389
-
390
- ```text
391
- contacts-contact-id:sub-pages
392
- ```
393
-
394
- So the exact host token changes, but the principle stays the same:
395
-
396
- - a nearer routed host changes where `page` places the new link
397
- - the child page becomes a tab or child link inside that host
398
-
399
- This is one of the most important things to understand about `ui-generator`: nested pages are not a separate feature bolted on afterwards. The generator already knows how to attach them to the right place.
400
-
401
- ### A practical rule for child-page paths
402
-
403
- Use these two rules when deciding where the child page file should go:
404
-
405
- - host is `.../index.vue` -> child pages go under `.../index/...`
406
- - host is `...[param].vue` or another file route -> child pages go under `.../[param]/...`
407
-
408
- That is not only a file-layout preference. It is how the router keeps the parent host visible while the child page renders beneath it.
409
-
410
- ## Adding small placed UI: `placed-element`
411
-
412
- Not everything should be a route.
413
-
414
- If what you need is a small block of UI rendered into an existing placement target, use `placed-element` instead:
415
-
416
- ```bash
417
- npx jskit generate ui-generator placed-element \
418
- --name "Alerts Widget"
419
- ```
420
-
421
- In the verified throwaway app, that command touched:
422
-
423
- ```text
424
- - packages/main/src/client/providers/MainClientProvider.js
425
- - src/components/AlertsWidgetElement.vue
426
- - src/placement.js
427
- ```
428
-
429
- Those three edits explain the feature:
430
-
431
- - the component file is created in `src/components/`
432
- - the app's local client provider registers a new local token for it
433
- - `src/placement.js` adds a placement entry that renders that token
434
-
435
- This is different from `page` in a very important way:
436
-
437
- - `page` gives you a URL and a link
438
- - `placed-element` gives you a component token and a placement entry
439
-
440
- So if the thing you are adding should live *inside* an existing shell region, not at its own route, `placed-element` is the right command.
441
-
442
- By default, the element targets the semantic status placement:
443
-
444
- ```text
445
- shell.status
446
- ```
447
-
448
- That is why this is such a good command for widgets, status panels, and compact shell extensions. The default shell topology maps `shell.status` to the concrete shell status outlet for each layout class.
449
-
450
- ### When `--surface` matters
451
-
452
- `placed-element` only needs `--surface` when JSKIT cannot infer the target surface cleanly.
453
-
454
- The easiest cases are:
455
-
456
- - the app has only one enabled surface
457
- - the chosen placement target clearly belongs to a page-owned outlet on one surface
458
-
459
- In those cases, surface inference is straightforward.
460
-
461
- The ambiguous cases are the ones to watch for:
462
-
463
- - the app has several enabled surfaces
464
- - the target placement is shared shell infrastructure rather than a page-owned outlet
465
- - the placement itself does not tell JSKIT which surface you meant
466
-
467
- That is exactly when `--surface` becomes important.
468
-
469
- A practical example is:
470
-
471
- ```bash
472
- npx jskit generate ui-generator placed-element \
473
- --name "Ops Panel" \
474
- --surface admin \
475
- --placement shell.status
476
- ```
477
-
478
- `shell.status` can be global across several surfaces. If your app has several enabled surfaces, `--surface admin` tells JSKIT which one this element is actually meant for.
479
-
480
- So the rule of thumb is:
481
-
482
- - page-owned semantic placement target -> surface is often inferable
483
- - shared shell semantic placement in a multi-surface app -> pass `--surface`
484
-
485
- ### `--placement`
486
-
487
- Use `--placement` when the default target `shell.status` is not what you want.
488
-
489
- This is the option that answers:
490
-
491
- - *where should this element render?*
492
-
493
- In practice, it is the first override you will use for `placed-element`.
494
-
495
- `--placement` expects a semantic placement id such as `shell.status`, `shell.global-actions`, or `settings.sections`. Concrete `host:position` outlets are exposed through topology, not used as normal placed-element authoring targets.
496
-
497
- ### `--path`
498
-
499
- Use `--path` when the component file should live somewhere other than `src/components`.
500
-
501
- This is not about placement in the UI. It is about placement in the source tree.
502
-
503
- Typical reasons:
504
-
505
- - you want widgets under `src/widgets`
506
- - you want admin-specific pieces under a more specific component directory
507
- - you want support scaffold grouped near a feature area instead of dumped into the default component folder
508
-
509
- So `--path` changes where the new Vue file is written, not where it renders.
510
-
511
- ### `--force`
512
-
513
- Use `--force` when the target component file already exists and you want to replace it with fresh generated scaffold.
514
-
515
- That is most useful when:
516
-
517
- - you are regenerating a throwaway prototype
518
- - you intentionally want to reset the file to generator output
519
-
520
- As with `page`, this is an overwrite guard, not a placement rule.
521
-
522
- ## Adding a plain placement seam: `outlet`
523
-
524
- Now suppose you already have a component and you do **not** need routed child pages. You only need a named place where later UI can render.
525
-
526
- That is what `outlet` is for.
527
-
528
- In the verified throwaway app, after generating `Alerts Widget`, I ran:
529
-
530
- ```bash
531
- npx jskit generate ui-generator outlet \
532
- src/components/AlertsWidgetElement.vue \
533
- --target alerts-widget:actions \
534
- --placement page.actions
535
- ```
536
-
537
- That command touched the Vue file and the topology file:
538
-
539
- ```text
540
- src/components/AlertsWidgetElement.vue
541
- src/placementTopology.js
542
- ```
543
-
544
- and injected:
545
-
546
- ```vue
547
- <ShellOutlet target="alerts-widget:actions" />
548
- ```
549
-
550
- It did **not** add:
551
-
552
- - `RouterView`
553
- - `SectionContainerShell`
554
- - child-page tab structure
555
-
556
- That is the clean boundary between `outlet` and `add-subpages`.
557
-
558
- Use `outlet` when you want:
559
-
560
- - a placement seam inside an existing page or component
561
- - later content to be targetable there
562
- - no routed child-page behavior
563
-
564
- After adding the outlet, `npx jskit list-placements` showed the new semantic placement immediately:
565
-
566
- ```text
567
- - page.actions: ...
568
- - compact -> alerts-widget:actions
569
- - medium -> alerts-widget:actions
570
- - expanded -> alerts-widget:actions
571
- ```
572
-
573
- So `outlet` is the smallest possible way to add a concrete recipient and expose it through the public placement topology in the same change.
574
-
575
- ### When `outlet` is the smaller correct tool
576
-
577
- This is the right command when you want to say:
578
-
579
- - "other things should be able to render here later"
580
-
581
- without also saying:
582
-
583
- - "this file should become a routed host page"
584
-
585
- That is why `outlet` is often the better choice for:
586
-
587
- - summary cards
588
- - header/action regions
589
- - detail panes
590
- - reusable components that need extension points
591
-
592
- If you do **not** need `RouterView` and you do **not** need child routes, `outlet` is usually the cleaner tool.
593
-
594
- ### Choosing a good custom `--target` and `--placement`
595
-
596
- `--target` should be meaningful to humans, not just syntactically valid.
597
-
598
- A target like:
599
-
600
- ```text
601
- customer-view:summary-actions
602
- ```
603
-
604
- is good because it tells you:
605
-
606
- - the host area: `customer-view`
607
- - the position or outlet purpose: `summary-actions`
608
-
609
- That is much better than something vague like:
610
-
611
- ```text
612
- custom-area:slot1
613
- ```
614
-
615
- because the meaningful target name will later show up in:
616
-
617
- - `jskit list-placements --concrete`
618
- - topology mappings
619
- - future generator commands
620
-
621
- So the target should describe the UI seam you are creating, not just satisfy the `host:position` format.
622
-
623
- `--placement` is the public authoring target that other entries should use. It should be semantic, such as:
624
-
625
- ```text
626
- page.actions
627
- ```
628
-
629
- Adding an outlet without adding a semantic mapping would leave a low-level recipient that normal generators and humans will not discover by default.
630
-
631
- ## `add-subpages` versus `outlet`
632
-
633
- This is the distinction that most often causes hesitation.
634
-
635
- Use `add-subpages` when:
636
-
637
- - the page should stay visible while child routes render underneath it
638
- - you need a routed host page
639
- - you want later generated child pages to attach there automatically
640
-
641
- Use `outlet` when:
642
-
643
- - you only want a placement seam
644
- - the file already exists
645
- - you do not want routed children
646
-
647
- So:
648
-
649
- - `add-subpages` changes the routing shape of the page
650
- - `outlet` changes only the placement shape of the file
651
-
652
- `add-subpages` also tends to be the right tool when the parent page is meant to stay visible while a series of related child pages render under it. `outlet` is the right tool when the file just needs extension points.
653
-
654
- ## Picking the right command
655
-
656
- The short rule is:
657
-
658
- - use `page` for new route pages
659
- - use `placed-element` for reusable placed UI
660
- - use `add-subpages` when the page should become a routed host
661
- - use `outlet` when you only need a placement target inside an existing file
662
-
663
- And the slightly longer rule is:
664
-
665
- - if it needs a URL, start from `page`
666
- - if it needs child routes, add `add-subpages`
667
- - if it does not need a URL but should render somewhere, use `placed-element`
668
- - if the file already exists and only needs a target for later UI, use `outlet`
669
-
670
- ## Summary
671
-
672
- `ui-generator` is the non-CRUD side of JSKIT scaffolding.
673
-
674
- It writes app-owned UI structure in four different shapes:
675
-
676
- - route pages
677
- - placed components
678
- - routed host pages
679
- - plain placement seams
680
-
681
- The most important thing to remember is that nested pages are not a special afterthought. Once a page has been upgraded with `add-subpages`, later `page` generation automatically treats that host as the real placement target.
682
-
683
- That is why the commands fit together cleanly:
684
-
685
- - `page` creates routes
686
- - `add-subpages` turns routes into hosts
687
- - `page` can then create nested child routes under those hosts
688
- - `placed-element` and `outlet` handle the non-routed side of the same UI system
689
-
690
- Once the UI you want needs real database-backed list/view/new/edit behavior instead of only page structure, move to the CRUD generators chapter.