@jskit-ai/agent-docs 0.1.26 → 0.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DISTR_AGENT.md +1 -0
- package/guide/agent/app-extras/assistant.md +9 -20
- package/guide/agent/app-extras/mobile-capacitor.md +381 -0
- package/guide/agent/app-extras/realtime.md +13 -12
- package/guide/agent/app-setup/a-more-interesting-shell.md +102 -87
- package/guide/agent/app-setup/authentication.md +50 -31
- package/guide/agent/app-setup/console.md +8 -8
- package/guide/agent/app-setup/database-layer.md +15 -15
- package/guide/agent/app-setup/initial-scaffolding.md +37 -5
- package/guide/agent/app-setup/multi-homing.md +50 -47
- package/guide/agent/app-setup/quickstart.md +11 -14
- package/guide/agent/app-setup/users.md +24 -24
- package/guide/agent/app-setup/working-with-the-jskit-cli.md +18 -10
- package/guide/agent/generators/advanced-cruds.md +111 -68
- package/guide/agent/generators/crud-generators.md +5 -5
- package/guide/agent/generators/ui-generators.md +44 -36
- package/guide/agent/index.md +3 -2
- package/package.json +1 -1
- package/patterns/INDEX.md +4 -1
- package/patterns/client-requests.md +23 -6
- package/patterns/crud-repository-mapping.md +1 -1
- package/patterns/crud-scaffolding.md +10 -1
- package/patterns/filters.md +28 -10
- package/patterns/generated-ui-contract-tracking.md +62 -0
- package/patterns/page-scaffolding.md +20 -2
- package/patterns/placements.md +67 -1
- package/patterns/surfaces.md +5 -1
- package/patterns/ui-testing.md +3 -0
- package/reference/autogen/KERNEL_MAP.md +46 -1
- package/reference/autogen/README.md +3 -0
- package/reference/autogen/packages/assistant.md +2 -1
- package/reference/autogen/packages/auth-web.md +20 -1
- package/reference/autogen/packages/crud-ui-generator.md +20 -8
- package/reference/autogen/packages/google-rewarded-core.md +222 -0
- package/reference/autogen/packages/google-rewarded-web.md +71 -0
- package/reference/autogen/packages/kernel.md +94 -10
- package/reference/autogen/packages/mobile-capacitor.md +76 -0
- package/reference/autogen/packages/realtime.md +1 -0
- package/reference/autogen/packages/shell-web.md +48 -3
- package/reference/autogen/packages/ui-generator.md +34 -2
- package/reference/autogen/packages/users-core.md +2 -0
- package/reference/autogen/packages/users-web.md +92 -4
- package/reference/autogen/packages/workspaces-web.md +3 -2
- package/reference/autogen/tooling/jskit-cli.md +114 -9
- package/templates/app/AGENTS.md +1 -0
- package/workflow/bootstrap.md +1 -0
|
@@ -63,7 +63,7 @@ npx jskit show @jskit-ai/workspaces-web --details
|
|
|
63
63
|
|
|
64
64
|
That output makes the package feel much less mysterious, because it shows the exact workspace shell contributions, settings outlets, client tokens, app-owned file writes, and capability requirements before you mutate the app.
|
|
65
65
|
|
|
66
|
-
## What
|
|
66
|
+
## What workspaces add
|
|
67
67
|
|
|
68
68
|
This chapter is where the app stops being a collection of global surfaces and starts supporting workspace-dependent ones.
|
|
69
69
|
|
|
@@ -107,13 +107,13 @@ That is why this chapter feels larger than the previous ones. It is not just add
|
|
|
107
107
|
|
|
108
108
|
### The shell and account surface gain workspace-aware controls
|
|
109
109
|
|
|
110
|
-
The placement registry
|
|
110
|
+
The placement registry gets a workspace selector in `shell.identity`, pending-invites and workspace tools in `shell.status`, and an `Invites` section in the existing `/account` settings screen through the account-settings extension seam that `users-web` exposes. The default shell topology maps identity/status placements to the visible shell chrome.
|
|
111
111
|
|
|
112
112
|
That means the shell itself starts adapting to workspace context.
|
|
113
113
|
|
|
114
|
-
- on any authenticated surface, the shell can
|
|
115
|
-
- signed-in users can
|
|
116
|
-
- on admin workspace surfaces, the shell can
|
|
114
|
+
- on any authenticated surface, the shell can expose a workspace selector
|
|
115
|
+
- signed-in users can see a pending-invites cue without `users-web` owning that workspace feature
|
|
116
|
+
- on admin workspace surfaces, the shell can expose workspace-specific tools and settings
|
|
117
117
|
|
|
118
118
|
This is the first time the guide shows the shell reacting not just to authentication state, but to workspace state as well.
|
|
119
119
|
|
|
@@ -139,7 +139,7 @@ This is also important to notice:
|
|
|
139
139
|
|
|
140
140
|
The new workspace surfaces are added on top of the existing app, not instead of it.
|
|
141
141
|
|
|
142
|
-
That is exactly what multi-homing should feel like. The app
|
|
142
|
+
That is exactly what multi-homing should feel like. The app has both:
|
|
143
143
|
|
|
144
144
|
- global surfaces
|
|
145
145
|
- workspace-scoped surfaces
|
|
@@ -153,7 +153,7 @@ npm run dev
|
|
|
153
153
|
npm run server
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
After you sign in, the app
|
|
156
|
+
After you sign in, the app has the routing structure needed for workspace-aware paths such as:
|
|
157
157
|
|
|
158
158
|
```text
|
|
159
159
|
/w/your-personal-slug
|
|
@@ -166,15 +166,15 @@ At this stage of the guide, the starter workspace pages are still intentionally
|
|
|
166
166
|
|
|
167
167
|
The most important new visible ideas are:
|
|
168
168
|
|
|
169
|
-
- a workspace slug
|
|
169
|
+
- a workspace slug appears in the route
|
|
170
170
|
- the shell can expose workspace selection and workspace tools
|
|
171
171
|
- workspace-dependent surfaces can show a dedicated unavailable-state card when the requested workspace cannot be resolved
|
|
172
172
|
|
|
173
|
-
First, even the
|
|
173
|
+
First, even the global `/home` surface reacts to workspace state. The selector and invites cue come from semantic placement entries and workspace bootstrap context, not from the `home` page itself.
|
|
174
174
|
|
|
175
|
-
Then open your personal workspace route. The page itself is deliberately light. `src/pages/w/[workspaceSlug]/index.vue` mostly exists to prove that the `app` surface is
|
|
175
|
+
Then open your personal workspace route. The page itself is deliberately light. `src/pages/w/[workspaceSlug]/index.vue` mostly exists to prove that the `app` surface is real and ready to host later modules.
|
|
176
176
|
|
|
177
|
-
Next open the admin surface for the same workspace. This is the matching pattern on the admin side: `src/pages/w/[workspaceSlug]/admin.vue` is the shell wrapper, `src/pages/w/[workspaceSlug]/admin/index.vue` is the starter page, and the
|
|
177
|
+
Next open the admin surface for the same workspace. This is the matching pattern on the admin side: `src/pages/w/[workspaceSlug]/admin.vue` is the shell wrapper, `src/pages/w/[workspaceSlug]/admin/index.vue` is the starter page, and the workspace tools button is coming from placements rather than being hand-built into that page file.
|
|
178
178
|
|
|
179
179
|
Finally open the nested workspace settings route. This is useful to inspect because it shows the container pattern most clearly. `src/pages/w/[workspaceSlug]/admin/workspace/settings.vue` owns the section frame and the child outlet, while the actual settings sub-pages can keep arriving later under that shell.
|
|
180
180
|
|
|
@@ -231,7 +231,7 @@ config.workspaceInvitations = {
|
|
|
231
231
|
};
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
-
Those lines are the public contract that tells both client and server
|
|
234
|
+
Those lines are the public contract that tells both client and server that this app is workspace-aware.
|
|
235
235
|
|
|
236
236
|
### `config/surfaceAccessPolicies.js` gains `workspace_member`
|
|
237
237
|
|
|
@@ -252,7 +252,7 @@ That is the core idea of multi-homing in JSKIT:
|
|
|
252
252
|
- the server resolves that workspace
|
|
253
253
|
- access depends on whether the current user belongs to it
|
|
254
254
|
|
|
255
|
-
### The migrations
|
|
255
|
+
### The migrations include workspace schema
|
|
256
256
|
|
|
257
257
|
After `workspaces-core`, the migration directory grows again with files such as:
|
|
258
258
|
|
|
@@ -269,7 +269,7 @@ That is why the chapter needs another `npm run db:migrate`. Without those tables
|
|
|
269
269
|
|
|
270
270
|
### The route tree gains workspace-dependent pages
|
|
271
271
|
|
|
272
|
-
The app
|
|
272
|
+
The app gets:
|
|
273
273
|
|
|
274
274
|
```text
|
|
275
275
|
src/pages/w/[workspaceSlug].vue
|
|
@@ -325,16 +325,13 @@ That command does two things:
|
|
|
325
325
|
- it creates `src/pages/w/[workspaceSlug]/admin/workspace/settings/billing/index.vue`
|
|
326
326
|
- it also appends the matching workspace settings menu entry into `src/placement.js`
|
|
327
327
|
|
|
328
|
-
The reason JSKIT can wire that link automatically is that the workspace settings shell already exposes a
|
|
328
|
+
The reason JSKIT can wire that link automatically is that the workspace settings shell already exposes a concrete outlet and topology maps it to semantic section navigation:
|
|
329
329
|
|
|
330
330
|
```vue
|
|
331
|
-
<ShellOutlet
|
|
332
|
-
target="admin-settings:primary-menu"
|
|
333
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
334
|
-
/>
|
|
331
|
+
<ShellOutlet target="admin-settings:primary-menu" />
|
|
335
332
|
```
|
|
336
333
|
|
|
337
|
-
|
|
334
|
+
The route host lets the generator infer `page.section-nav` with owner `admin-settings`. `src/placementTopology.js` then maps that semantic placement to `admin-settings:primary-menu` and supplies the link renderer for compact, medium, and expanded layouts. So a page generated under `w/[workspaceSlug]/admin/workspace/settings/...` automatically lands in the left-side workspace settings menu without you hand-writing the placement entry.
|
|
338
335
|
|
|
339
336
|
### Workspace pages are prepared for missing-workspace states
|
|
340
337
|
|
|
@@ -524,7 +521,8 @@ The workspace packages append a new block of placements:
|
|
|
524
521
|
```js
|
|
525
522
|
addPlacement({
|
|
526
523
|
id: "workspaces.profile.menu.surface-switch",
|
|
527
|
-
target: "auth
|
|
524
|
+
target: "auth.profile-menu",
|
|
525
|
+
kind: "component",
|
|
528
526
|
surfaces: ["*"],
|
|
529
527
|
order: 100,
|
|
530
528
|
componentToken: "workspaces.web.profile.menu.surface-switch-item",
|
|
@@ -533,7 +531,8 @@ addPlacement({
|
|
|
533
531
|
|
|
534
532
|
addPlacement({
|
|
535
533
|
id: "workspaces.workspace.selector",
|
|
536
|
-
target: "shell
|
|
534
|
+
target: "shell.identity",
|
|
535
|
+
kind: "component",
|
|
537
536
|
surfaces: ["*"],
|
|
538
537
|
order: 200,
|
|
539
538
|
componentToken: "workspaces.web.workspace.selector",
|
|
@@ -548,7 +547,8 @@ addPlacement({
|
|
|
548
547
|
|
|
549
548
|
addPlacement({
|
|
550
549
|
id: "workspaces.account.invites.cue",
|
|
551
|
-
target: "shell
|
|
550
|
+
target: "shell.status",
|
|
551
|
+
kind: "component",
|
|
552
552
|
surfaces: ["*"],
|
|
553
553
|
order: 850,
|
|
554
554
|
componentToken: "local.main.account.pending-invites.cue",
|
|
@@ -557,7 +557,8 @@ addPlacement({
|
|
|
557
557
|
|
|
558
558
|
addPlacement({
|
|
559
559
|
id: "workspaces.workspace.tools.widget",
|
|
560
|
-
target: "shell
|
|
560
|
+
target: "shell.status",
|
|
561
|
+
kind: "component",
|
|
561
562
|
surfaces: ["admin"],
|
|
562
563
|
order: 900,
|
|
563
564
|
componentToken: "workspaces.web.workspace.tools.widget"
|
|
@@ -565,7 +566,8 @@ addPlacement({
|
|
|
565
566
|
|
|
566
567
|
addPlacement({
|
|
567
568
|
id: "workspaces.workspace.menu.workspace-settings",
|
|
568
|
-
target: "admin-
|
|
569
|
+
target: "admin.tools-menu",
|
|
570
|
+
kind: "component",
|
|
569
571
|
surfaces: ["admin"],
|
|
570
572
|
order: 100,
|
|
571
573
|
componentToken: "workspaces.web.workspace-settings.menu-item"
|
|
@@ -573,51 +575,52 @@ addPlacement({
|
|
|
573
575
|
|
|
574
576
|
addPlacement({
|
|
575
577
|
id: "workspaces.workspace.menu.members",
|
|
576
|
-
target: "admin-
|
|
578
|
+
target: "admin.tools-menu",
|
|
579
|
+
kind: "component",
|
|
577
580
|
surfaces: ["admin"],
|
|
578
581
|
order: 200,
|
|
579
582
|
componentToken: "workspaces.web.workspace-members.menu-item"
|
|
580
583
|
});
|
|
581
584
|
```
|
|
582
585
|
|
|
583
|
-
That one block explains a lot of the
|
|
586
|
+
That one block explains a lot of the workspace shell behavior.
|
|
584
587
|
|
|
585
|
-
- the authenticated profile menu can
|
|
586
|
-
-
|
|
587
|
-
-
|
|
588
|
-
- the admin surface gets workspace tools
|
|
589
|
-
- the admin workspace settings menu is
|
|
588
|
+
- the authenticated profile menu can switch into workspace surfaces
|
|
589
|
+
- `shell.identity` carries the workspace selector
|
|
590
|
+
- `shell.status` can show a pending-invites cue
|
|
591
|
+
- the admin surface gets workspace tools through `shell.status`
|
|
592
|
+
- the admin workspace settings menu is another nested placement host with both `Settings` and `Members`
|
|
590
593
|
|
|
591
|
-
If you want to add your own app-owned page into that top cog menu, first ask JSKIT which
|
|
594
|
+
If you want to add your own app-owned page into that top cog menu, first ask JSKIT which semantic placements exist:
|
|
592
595
|
|
|
593
596
|
```bash
|
|
594
597
|
npx jskit list-placements
|
|
595
598
|
```
|
|
596
599
|
|
|
597
|
-
In a workspace-enabled app, that list
|
|
600
|
+
In a workspace-enabled app, that list includes:
|
|
598
601
|
|
|
599
602
|
```text
|
|
600
|
-
- admin-
|
|
603
|
+
- admin.tools-menu: Admin surface tools menu actions.
|
|
601
604
|
```
|
|
602
605
|
|
|
603
|
-
If you want
|
|
606
|
+
If you want the underlying outlet inventory, use `npx jskit list-placements --concrete`. If you want more package context, `npx jskit show @jskit-ai/workspaces-web --details` also shows the topology plus the default `Settings` and `Members` entries already targeting it.
|
|
604
607
|
|
|
605
|
-
Once you know the
|
|
608
|
+
Once you know the semantic placement id, generate the page like this:
|
|
606
609
|
|
|
607
610
|
```bash
|
|
608
611
|
npx jskit generate ui-generator page \
|
|
609
612
|
w/[workspaceSlug]/admin/catalogue/index.vue \
|
|
610
613
|
--name "Catalogue" \
|
|
611
|
-
--link-placement admin-
|
|
614
|
+
--link-placement admin.tools-menu
|
|
612
615
|
```
|
|
613
616
|
|
|
614
617
|
That command creates `src/pages/w/[workspaceSlug]/admin/catalogue/index.vue` and appends the matching link entry into `src/placement.js`.
|
|
615
618
|
|
|
616
|
-
`--link-placement` is necessary here because this route is just a normal `admin` page. It is **not** a child page under a local host like `w/[workspaceSlug]/admin/workspace/settings.vue`, so the generator has no nested settings
|
|
619
|
+
`--link-placement` is necessary here because this route is just a normal `admin` page. It is **not** a child page under a local host like `w/[workspaceSlug]/admin/workspace/settings.vue`, so the generator has no nested settings placement to infer automatically. If you omit `--link-placement`, the new page link falls back to the app's default `shell.primary-nav` placement instead of the cog menu.
|
|
617
620
|
|
|
618
|
-
You also do **not** need
|
|
621
|
+
You also do **not** need a renderer flag here. `admin.tools-menu` defines its link renderer in topology, so JSKIT resolves that when it renders the placement entry.
|
|
619
622
|
|
|
620
|
-
So the placement system from the shell chapter is
|
|
623
|
+
So the placement system from the shell chapter is doing the same job with a richer routing and tenancy context.
|
|
621
624
|
|
|
622
625
|
### The local client provider gets one more app-owned token
|
|
623
626
|
|
|
@@ -663,7 +666,7 @@ registerProfileSyncLifecycleContributor(app, "workspaces.core.profileSyncLifecyc
|
|
|
663
666
|
|
|
664
667
|
That means the workspace package does not need to patch auth directly to learn that a user was added. It listens through the `users-core` lifecycle registry instead.
|
|
665
668
|
|
|
666
|
-
For this chapter's `tenancyMode = "personal"` setup, that contributor
|
|
669
|
+
For this chapter's `tenancyMode = "personal"` setup, that contributor does real work. When an authenticated JSKIT user is synchronized from auth, `workspaces-core` ensures that user's personal workspace exists.
|
|
667
670
|
|
|
668
671
|
That detail matters for the retrofit path described earlier in this chapter. If the app started on `none`, then later switched to `personal`, the first sign-in after that switch still needs to backfill the personal workspace for the already-existing user record. The lifecycle contributor handles that because the workspace provision step is idempotent.
|
|
669
672
|
|
|
@@ -709,9 +712,9 @@ Before:
|
|
|
709
712
|
After:
|
|
710
713
|
|
|
711
714
|
- global surfaces still exist
|
|
712
|
-
- workspace-scoped surfaces
|
|
715
|
+
- workspace-scoped surfaces exist too
|
|
713
716
|
- the shell can navigate between workspaces
|
|
714
|
-
- access to some surfaces
|
|
717
|
+
- access to some surfaces depends on workspace membership
|
|
715
718
|
|
|
716
719
|
That is why multi-homing deserves its own chapter. It is not just another feature package. It is the moment the app becomes tenancy-aware.
|
|
717
720
|
|
|
@@ -719,11 +722,11 @@ That is why multi-homing deserves its own chapter. It is not just another featur
|
|
|
719
722
|
|
|
720
723
|
This chapter is the real routing and tenancy pivot in the guide.
|
|
721
724
|
|
|
722
|
-
- the app
|
|
725
|
+
- the app uses `tenancyMode = "personal"`
|
|
723
726
|
- `workspaces-core` added the persistent schema and server runtime for workspaces
|
|
724
727
|
- `workspaces-web` added the first workspace-scoped surfaces, shell controls, and the workspace-owned account invites extension
|
|
725
728
|
|
|
726
|
-
At the end of this chapter, the app
|
|
729
|
+
At the end of this chapter, the app has both:
|
|
727
730
|
|
|
728
731
|
- global surfaces such as `home`, `auth`, `account`, and `console`
|
|
729
732
|
- workspace-scoped surfaces such as `/w/[workspaceSlug]` and `/w/[workspaceSlug]/admin`
|
|
@@ -733,7 +736,7 @@ That is the most important mental shift to keep:
|
|
|
733
736
|
- earlier chapters added features inside one global app shell
|
|
734
737
|
- this chapter changed the topology of the app itself
|
|
735
738
|
|
|
736
|
-
From here on, later modules
|
|
739
|
+
From here on, later modules can add features inside either:
|
|
737
740
|
|
|
738
741
|
- the global surfaces
|
|
739
742
|
- the workspace-specific surfaces
|
|
@@ -85,9 +85,7 @@ npx jskit generate assistant page \
|
|
|
85
85
|
npx jskit generate assistant settings-page \
|
|
86
86
|
console/settings/admin-assistant/index.vue \
|
|
87
87
|
--surface admin \
|
|
88
|
-
--name "Admin Assistant"
|
|
89
|
-
--link-placement console-settings:primary-menu \
|
|
90
|
-
--link-component-token local.main.ui.surface-aware-menu-link-item
|
|
88
|
+
--name "Admin Assistant"
|
|
91
89
|
|
|
92
90
|
npm install
|
|
93
91
|
npm run db:migrate
|
|
@@ -154,7 +152,7 @@ First list the available placement destinations:
|
|
|
154
152
|
npx jskit list-placements
|
|
155
153
|
```
|
|
156
154
|
|
|
157
|
-
In a workspace-enabled app, that output includes `admin-
|
|
155
|
+
In a workspace-enabled app, that output includes the semantic `admin.tools-menu` placement.
|
|
158
156
|
|
|
159
157
|
Then generate the page:
|
|
160
158
|
|
|
@@ -162,7 +160,7 @@ Then generate the page:
|
|
|
162
160
|
npx jskit generate ui-generator page \
|
|
163
161
|
w/[workspaceSlug]/admin/catalogue/index.vue \
|
|
164
162
|
--name "Catalogue" \
|
|
165
|
-
--link-placement admin-
|
|
163
|
+
--link-placement admin.tools-menu
|
|
166
164
|
```
|
|
167
165
|
|
|
168
166
|
`--link-placement` is necessary here because this is just a normal `admin` page. It is not a child page under a local route host that already owns a nested outlet.
|
|
@@ -183,13 +181,10 @@ Because this page is not under a more specific local host, JSKIT falls back to t
|
|
|
183
181
|
|
|
184
182
|
The workspace settings pages in Step 2 auto-linked into the settings menu for two reasons:
|
|
185
183
|
|
|
186
|
-
1. The parent host already exposes a
|
|
184
|
+
1. The parent host already exposes a concrete outlet:
|
|
187
185
|
|
|
188
186
|
```vue
|
|
189
|
-
<ShellOutlet
|
|
190
|
-
target="admin-settings:primary-menu"
|
|
191
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
192
|
-
/>
|
|
187
|
+
<ShellOutlet target="admin-settings:primary-menu" />
|
|
193
188
|
```
|
|
194
189
|
|
|
195
190
|
2. Your generated pages live under that host route:
|
|
@@ -200,12 +195,14 @@ w/[workspaceSlug]/admin/workspace/settings/...
|
|
|
200
195
|
|
|
201
196
|
So JSKIT can infer both:
|
|
202
197
|
|
|
203
|
-
- the placement target: `
|
|
204
|
-
- the
|
|
198
|
+
- the semantic placement target: `page.section-nav`
|
|
199
|
+
- the placement owner: `admin-settings`
|
|
205
200
|
|
|
206
|
-
|
|
201
|
+
The renderer comes from `src/placementTopology.js`, where `page.section-nav` maps to the concrete `admin-settings:primary-menu` outlet for each layout class.
|
|
207
202
|
|
|
208
|
-
|
|
203
|
+
That is why the simple settings-page commands do not need `--link-placement`.
|
|
204
|
+
|
|
205
|
+
The admin cog example is different. `w/[workspaceSlug]/admin/catalogue/index.vue` is just a normal admin page, so there is no local nested host to infer. That is why you must pass `--link-placement admin.tools-menu` there.
|
|
209
206
|
|
|
210
207
|
If you want a little more context than the raw destination list, this is also useful:
|
|
211
208
|
|
|
@@ -42,7 +42,7 @@ This is the first chapter where the migration step is not just "nice to have."
|
|
|
42
42
|
- `AUTH_PROFILE_MODE=users` into `.env`
|
|
43
43
|
- real users/account schema migrations into `migrations/`
|
|
44
44
|
|
|
45
|
-
That means the app is
|
|
45
|
+
That means the app is expected to use the persistent users-backed profile sync service. If you skip `npm run db:migrate`, the code and routes are installed, but the required tables are still missing.
|
|
46
46
|
|
|
47
47
|
So the correct flow is:
|
|
48
48
|
|
|
@@ -57,24 +57,24 @@ Most of the time, step 3 is not needed because `jskit add package users-web` alr
|
|
|
57
57
|
- `jskit migrations changed` writes or refreshes JSKIT-managed migration files in `migrations/`
|
|
58
58
|
- `npm run db:migrate` actually applies pending migrations to MySQL
|
|
59
59
|
|
|
60
|
-
## What
|
|
60
|
+
## What `users-web` adds
|
|
61
61
|
|
|
62
62
|
This chapter is the real transition from "authentication exists" to "the app knows about users."
|
|
63
63
|
|
|
64
64
|
### Authentication becomes users-backed
|
|
65
65
|
|
|
66
|
-
In the database chapter, JSKIT
|
|
66
|
+
In the database chapter, JSKIT used the standalone in-memory profile mirror. After installing `users-web`, JSKIT expects to synchronize authenticated users into real JSKIT tables.
|
|
67
67
|
|
|
68
68
|
That is the biggest architectural change in this chapter.
|
|
69
69
|
|
|
70
70
|
- Supabase still owns the real auth identity and session
|
|
71
|
-
- JSKIT
|
|
71
|
+
- JSKIT owns a persistent users/account data model in MySQL
|
|
72
72
|
|
|
73
|
-
So after this chapter, a signed-in user is
|
|
73
|
+
So after this chapter, a signed-in user is not only "someone Supabase knows about." They are also a persistent JSKIT-side user with settings and profile state in the app database.
|
|
74
74
|
|
|
75
75
|
### The app gets an authenticated account surface
|
|
76
76
|
|
|
77
|
-
The app
|
|
77
|
+
The app has an authenticated surface at `/account`.
|
|
78
78
|
|
|
79
79
|
This is where the starter account settings UI lives. It already has real sections for:
|
|
80
80
|
|
|
@@ -84,17 +84,17 @@ This is where the starter account settings UI lives. It already has real section
|
|
|
84
84
|
|
|
85
85
|
Later chapters can extend this account screen with more sections. For example, the multi-homing chapter adds workspace invitation UI through `workspaces-web`, not through `users-web` itself.
|
|
86
86
|
|
|
87
|
-
The important point is that this is
|
|
87
|
+
The important point is that this is a real account route, not a placeholder. It is the first app-owned screen that assumes there is a persistent user model behind it.
|
|
88
88
|
|
|
89
89
|
### The shell changes for signed-in users
|
|
90
90
|
|
|
91
91
|
Once a user is signed in, the shell becomes noticeably richer.
|
|
92
92
|
|
|
93
93
|
- the profile menu gets a `Settings` entry that leads to `/account`
|
|
94
|
-
- the home surface gets a small users tools widget in
|
|
95
|
-
- the auth bootstrap payload
|
|
94
|
+
- the home surface gets a small users tools widget in `shell.status`
|
|
95
|
+
- the auth bootstrap payload includes persistent user settings instead of only the fallback mirror data
|
|
96
96
|
|
|
97
|
-
So this chapter is also the first one where logging in changes more than just "guest vs signed in." It
|
|
97
|
+
So this chapter is also the first one where logging in changes more than just "guest vs signed in." It changes what persistent user-facing surfaces the app can expose.
|
|
98
98
|
|
|
99
99
|
## What to look at in the browser
|
|
100
100
|
|
|
@@ -107,17 +107,17 @@ npm run server
|
|
|
107
107
|
|
|
108
108
|
Then sign in through `http://localhost:5173/auth/login`.
|
|
109
109
|
|
|
110
|
-
After a successful sign-in,
|
|
110
|
+
After a successful sign-in, check these concrete differences compared with the previous chapter:
|
|
111
111
|
|
|
112
|
-
- the profile menu
|
|
113
|
-
-
|
|
114
|
-
- `/account`
|
|
112
|
+
- the profile menu contains `Settings`
|
|
113
|
+
- `shell.status` includes the users tools widget
|
|
114
|
+
- `/account` exists and is authenticated
|
|
115
115
|
|
|
116
116
|
This is the first chapter where the app starts to feel like it has a real user model behind it.
|
|
117
117
|
|
|
118
118
|
## What `users-web` adds to the app
|
|
119
119
|
|
|
120
|
-
The most interesting files
|
|
120
|
+
The most interesting files are spread across config, migrations, routing, and the app-owned account UI.
|
|
121
121
|
|
|
122
122
|
### `.env` flips auth into users mode
|
|
123
123
|
|
|
@@ -180,10 +180,10 @@ The placement registry also becomes more interesting:
|
|
|
180
180
|
```js
|
|
181
181
|
addPlacement({
|
|
182
182
|
id: "users.profile.menu.settings",
|
|
183
|
-
target: "auth
|
|
183
|
+
target: "auth.profile-menu",
|
|
184
|
+
kind: "link",
|
|
184
185
|
surfaces: ["*"],
|
|
185
186
|
order: 500,
|
|
186
|
-
componentToken: "auth.web.profile.menu.link-item",
|
|
187
187
|
props: {
|
|
188
188
|
label: "Settings",
|
|
189
189
|
to: "/account"
|
|
@@ -239,18 +239,18 @@ src/components/account/settings/
|
|
|
239
239
|
|
|
240
240
|
Those three section components stay app-owned so you can reshape the actual UI freely.
|
|
241
241
|
|
|
242
|
-
The host itself
|
|
242
|
+
The host itself lives in `users-web` and resolves every account section through the semantic `settings.sections` placement with owner `account-settings`, including the default `profile`, `preferences`, and `notifications` entries.
|
|
243
243
|
|
|
244
244
|
So the screen follows the same rule as the rest of JSKIT UI: sections are added by placement rather than being hardcoded into an app-owned host component.
|
|
245
245
|
|
|
246
|
-
That is worth noticing because
|
|
246
|
+
That is worth noticing because this is a higher level of scaffolding:
|
|
247
247
|
|
|
248
248
|
- earlier chapters mostly introduced shells and routes
|
|
249
249
|
- this chapter introduces app-owned leaf section UI while the generic section host stays in the package
|
|
250
250
|
|
|
251
251
|
## Under the hood
|
|
252
252
|
|
|
253
|
-
### Why auth
|
|
253
|
+
### Why auth uses the users layer
|
|
254
254
|
|
|
255
255
|
In the previous chapter, auth still defaulted to the standalone profile sync fallback. The core logic in `AuthSupabaseServiceProvider` looks like this:
|
|
256
256
|
|
|
@@ -268,7 +268,7 @@ if (authProfileMode === AUTH_PROFILE_MODE_USERS) {
|
|
|
268
268
|
}
|
|
269
269
|
```
|
|
270
270
|
|
|
271
|
-
The important part is
|
|
271
|
+
The important part is concrete.
|
|
272
272
|
|
|
273
273
|
After `users-web`:
|
|
274
274
|
|
|
@@ -276,9 +276,9 @@ After `users-web`:
|
|
|
276
276
|
- `users-core` supplies the users-backed sync service
|
|
277
277
|
- the migrations supply the required tables
|
|
278
278
|
|
|
279
|
-
So auth
|
|
279
|
+
So auth has everything it needs to stop using the fallback mirror and start using the persistent users-backed one.
|
|
280
280
|
|
|
281
|
-
That is the true point of this chapter. The app is
|
|
281
|
+
That is the true point of this chapter. The app is not just authenticated. It has a real users layer.
|
|
282
282
|
|
|
283
283
|
### `users-core` also owns the profile-sync lifecycle registry
|
|
284
284
|
|
|
@@ -361,7 +361,7 @@ This chapter is where the app stopped treating signed-in people as only Supabase
|
|
|
361
361
|
|
|
362
362
|
That is why this chapter feels bigger than a normal page install. It changes both the browser experience and the server-side meaning of "a signed-in user."
|
|
363
363
|
|
|
364
|
-
At the end of this chapter, the app
|
|
364
|
+
At the end of this chapter, the app has:
|
|
365
365
|
|
|
366
366
|
- real JSKIT-side `users` and `user_settings` tables
|
|
367
367
|
- a real authenticated `/account` surface
|
|
@@ -71,14 +71,15 @@ In the current scaffold, those scripts are intentionally thin:
|
|
|
71
71
|
|
|
72
72
|
That is a deliberate design choice.
|
|
73
73
|
|
|
74
|
-
The app keeps the handy `npm run` names, but the real maintenance policy
|
|
74
|
+
The app keeps the handy `npm run` names, but the real maintenance policy lives in the installed CLI package instead of copied shell scripts inside the app. That means if JSKIT later changes how package updates, local linking, or baseline verification should work, apps can pick up the new behavior by updating `@jskit-ai/jskit-cli` instead of hand-editing frozen scaffold files.
|
|
75
75
|
|
|
76
76
|
This gives you a clean ownership split:
|
|
77
77
|
|
|
78
78
|
- app-owned scripts still describe how *this app* runs, builds, and tests
|
|
79
|
+
- `npm run devlinks` re-applies local checkout links after `npm install` when you are testing an app against this monorepo
|
|
79
80
|
- JSKIT-owned wrapper scripts delegate framework maintenance to `jskit app ...`
|
|
80
81
|
|
|
81
|
-
That split is worth keeping in mind through the rest of the guide. When you see `npm run verify`,
|
|
82
|
+
That split is worth keeping in mind through the rest of the guide. When you see `npm run verify`, read it as "run the app's JSKIT baseline verification policy, then any app-specific extra verification hook".
|
|
82
83
|
|
|
83
84
|
The starter scaffold also includes `.github/workflows/verify.yml`. That workflow is intentionally conservative: it runs `npm run verify` and does not assume that every app can stand up full browser, auth, seed-data, and database verification inside hosted CI.
|
|
84
85
|
|
|
@@ -332,8 +333,8 @@ The placement sections are often the most useful part of `show --details`.
|
|
|
332
333
|
|
|
333
334
|
For `@jskit-ai/workspaces-web`, the detailed output shows placement contributions such as:
|
|
334
335
|
|
|
335
|
-
- the workspace selector in `shell
|
|
336
|
-
- the pending invites cue in `shell
|
|
336
|
+
- the workspace selector in `shell.identity`
|
|
337
|
+
- the pending invites cue in `shell.status`
|
|
337
338
|
- the workspace tools widget on the `admin` surface
|
|
338
339
|
- the `Members` and workspace settings menu entries
|
|
339
340
|
|
|
@@ -341,9 +342,10 @@ That lets you answer a very concrete question before installing anything:
|
|
|
341
342
|
|
|
342
343
|
- *what will change in the shell if I add this package?*
|
|
343
344
|
|
|
344
|
-
It also shows placement
|
|
345
|
+
It also shows semantic placement topology, such as:
|
|
345
346
|
|
|
346
|
-
- `admin-settings
|
|
347
|
+
- `page.section-nav` with owner `admin-settings`
|
|
348
|
+
- `admin.tools-menu`
|
|
347
349
|
|
|
348
350
|
which helps you understand where later app-owned pages or settings links can attach.
|
|
349
351
|
|
|
@@ -504,7 +506,13 @@ npx jskit add package shell-web
|
|
|
504
506
|
npm install
|
|
505
507
|
```
|
|
506
508
|
|
|
507
|
-
`jskit add` changes the app. `npm install` downloads the dependencies that the changed app
|
|
509
|
+
`jskit add` changes the app. `npm install` downloads the dependencies that the changed app requires.
|
|
510
|
+
|
|
511
|
+
If the app is being tested against a local JSKIT checkout with linked packages, run the local-link wrapper again after every `npm install`:
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
npm run devlinks
|
|
515
|
+
```
|
|
508
516
|
|
|
509
517
|
### `add bundle`
|
|
510
518
|
|
|
@@ -699,7 +707,7 @@ That is a different job from:
|
|
|
699
707
|
|
|
700
708
|
Those commands can all pass while JSKIT-managed state is still inconsistent. `doctor` is the command that checks that JSKIT's own view of the app still makes sense.
|
|
701
709
|
|
|
702
|
-
That is exactly why the starter scaffold
|
|
710
|
+
That is exactly why the starter scaffold routes `npm run verify` through `jskit app verify`.
|
|
703
711
|
|
|
704
712
|
It belongs there because JSKIT apps are not only source trees. They also have:
|
|
705
713
|
|
|
@@ -731,7 +739,7 @@ Good times to run it manually include:
|
|
|
731
739
|
|
|
732
740
|
One important nuance: `doctor` is checking for broken JSKIT ownership and visibility, not trying to stop you from editing app-owned files. For example, a managed file that still exists but whose contents changed is normally fine. The problem is when JSKIT expects a managed file to exist and it is gone, or when the installed package state no longer resolves cleanly.
|
|
733
741
|
|
|
734
|
-
There is one intentional exception
|
|
742
|
+
There is one intentional exception for user-facing UI work.
|
|
735
743
|
|
|
736
744
|
If the current git working tree has changed UI files under the app's normal UI paths, `doctor` expects a matching `.jskit/verification/ui.json` receipt. The intended way to create that receipt is:
|
|
737
745
|
|
|
@@ -961,7 +969,7 @@ Good fits include:
|
|
|
961
969
|
- a custom integration package that talks to one external API
|
|
962
970
|
- app-specific auth or policy behavior
|
|
963
971
|
- a local runtime package that owns both client and server behavior for one feature area
|
|
964
|
-
- a package that starts small
|
|
972
|
+
- a package that starts small but may later grow providers, shared helpers, and routes
|
|
965
973
|
|
|
966
974
|
Use a generator when the problem is already understood well enough that JSKIT can scaffold the feature shape for you.
|
|
967
975
|
|