@jskit-ai/agent-docs 0.1.47 → 0.1.48

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.
@@ -2,43 +2,31 @@
2
2
 
3
3
  # A more interesting shell
4
4
 
5
- In the first chapter, the app was intentionally plain. That was useful because it let us see the smallest possible JSKIT scaffold without too many moving parts. In this chapter, we install `shell-web`, which is the package that turns that bare starting point into a real shell: a layout, navigation outlets, a first settings area, and a proper app-level error host.
5
+ In the first chapter, the app started with `shell-web` already installed. That is the normal JSKIT starting point: a real layout, navigation outlets, a first settings area, and a proper app-level error host.
6
6
 
7
7
  This still is not authentication, not database work, and not multi-surface routing. The app remains small. But it starts to look and behave like something you could actually grow.
8
8
 
9
- ## Installing `shell-web`
9
+ ## Running the shell
10
10
 
11
11
  From inside `exampleapp`, run:
12
12
 
13
- ```bash
14
- npx jskit add package shell-web
15
- npm install
16
- ```
17
-
18
- `jskit add` rewrites part of the scaffold and records the installed runtime package in `.jskit/lock.json`. The following `npm install` is what actually downloads the new package and its supporting dependencies.
19
-
20
- To see the result, run:
21
-
22
13
  ```bash
23
14
  npm run dev
24
15
  npm run server
25
16
  ```
26
17
 
27
- This time you really want both processes running. The new home page fetches `/api/health`, so the browser-facing dev server on port `5173` expects the backend on port `3000` to be alive as well.
18
+ You want both processes running. The starter home page fetches `/api/health`, so the browser-facing dev server on port `5173` expects the backend on port `3000` to be alive as well.
28
19
 
29
- **Important: Install It Early**
20
+ **Minimal: Adding `shell-web` To A Bare Scaffold**
30
21
 
31
- `shell-web` is not just adding new files. It also **claims and replaces part of the original scaffold** so the app can switch from the plain starter layout to the real shell layout.
22
+ The normal `create-app` template already has `shell-web`. If you deliberately created the bare scaffold with `--minimal` or `--template minimal-shell`, install the shell before you personalize the files it claims:
32
23
 
33
- That replacement is intentionally strict: `shell-web` only takes over scaffold files if they are still **exactly** the same as the files that `create-app` originally wrote. If you have already edited those starter files, `shell-web` refuses to claim them instead of overwriting your work.
34
-
35
- That is why the intended flow is:
36
-
37
- 1. scaffold the app
38
- 2. install `shell-web`
39
- 3. start personalizing the shell
24
+ ```bash
25
+ npx jskit add package shell-web
26
+ npm install
27
+ ```
40
28
 
41
- If you build directly on top of the plain scaffold first and only try to add `shell-web` later, the install may fail because those app-owned files no longer match the untouched scaffold baseline.
29
+ That install is intentionally strict: `shell-web` only takes over scaffold files if they are still **exactly** the same as the files that `create-app --minimal` originally wrote. If you have already edited those starter files, `shell-web` refuses to claim them instead of overwriting your work.
42
30
 
43
31
  Open `http://localhost:5173/` in the browser. The app lands in the `home` surface inside a real shell with an app bar, a navigation drawer, and a settings route at `/home/settings`.
44
32
 
@@ -285,7 +273,7 @@ So the shell story in this chapter is:
285
273
 
286
274
  That is the first real example of JSKIT behaving like an extension system rather than just a scaffold generator.
287
275
 
288
- ## What `shell-web` changes in the app
276
+ ## What `shell-web` owns in the app
289
277
 
290
278
  The most interesting files look roughly like this:
291
279
 
@@ -315,11 +303,11 @@ src/
315
303
  index.vue
316
304
  ```
317
305
 
318
- This chapter is the first time the scaffold starts to feel layered instead of flat.
306
+ This chapter is where the default scaffold starts to feel layered instead of flat.
319
307
 
320
308
  ### `package.json` and `.jskit/lock.json`
321
309
 
322
- The first file worth reopening is still `package.json`. After `shell-web`, the most important new dependency entries are:
310
+ The first file worth reopening is still `package.json`. Because the default app includes `shell-web`, the important shell dependency entries are already present:
323
311
 
324
312
  ```json
325
313
  {
@@ -334,15 +322,15 @@ The important part is not just that `@jskit-ai/shell-web` appears. The package b
334
322
 
335
323
  It is also worth noticing what does **not** happen here. The `placed-element` and `page` commands from this chapter mutate app-owned files, but they do not add a permanent runtime dependency to `package.json`. They are tooling actions, not runtime package installs.
336
324
 
337
- The lock file becomes more interesting too. In the first chapter, `.jskit/lock.json` only knew about `@local/main`. Now it also records `@jskit-ai/shell-web` and the exact files and text mutations that package introduced.
325
+ The lock file records this too. In a default app, `.jskit/lock.json` already records `@local/main`, `@jskit-ai/shell-web`, and the exact files and text mutations that the shell package owns.
338
326
 
339
- That is worth noticing because this is the first chapter where JSKIT applies a runtime package that owns concrete changes in your app tree.
327
+ That is worth noticing because the default scaffold is not just copied files. It starts with a JSKIT-managed runtime package that owns concrete changes in your app tree.
340
328
 
341
329
  ### The `home` surface gets a real wrapper
342
330
 
343
331
  The surface itself did not change. `home` is still the same surface defined in `config/public.js`. What changed is the page tree inside it.
344
332
 
345
- Before `shell-web`, `src/pages/home.vue` was only a tiny route owner with a `RouterView`. After installing `shell-web`, it becomes:
333
+ In the shell-web scaffold, `src/pages/home.vue` is more than a tiny route owner with a `RouterView`. It wraps the surface in the app-owned shell layout:
346
334
 
347
335
  ```vue
348
336
  <route lang="json">
@@ -369,9 +357,9 @@ import { RouterView } from "vue-router";
369
357
 
370
358
  That one change explains a lot. The `home` surface is a shell-wrapped surface. Every child page under `src/pages/home/` renders inside that app-owned `ShellLayout`.
371
359
 
372
- ### `src/placement.js` becomes the placement registry
360
+ ### `src/placement.js` is the placement registry
373
361
 
374
- After installing `shell-web`, the app gets a placement registry file:
362
+ The app has a placement registry file:
375
363
 
376
364
  ```js
377
365
  import { createPlacementRegistry } from "@jskit-ai/shell-web/client/placement";
@@ -388,7 +376,7 @@ export default function getPlacements() {
388
376
 
389
377
  That file is the app-owned seam for placements. `shell-web` owns the runtime that can render placements, but the app owns the registry source that lists what should appear in those targets.
390
378
 
391
- After the `shell-web` install plus the `placed-element` and `page` commands from this chapter, the bottom of the file contains real placement entries:
379
+ After the scaffold's shell entries plus the `placed-element` and `page` commands from this chapter, the bottom of the file contains real placement entries:
392
380
 
393
381
  ```js
394
382
  addPlacement({
@@ -498,7 +486,7 @@ So the shell itself remains stable. What changes is the registry that feeds it.
498
486
 
499
487
  The placement registry only points at tokens. Those tokens still need to resolve to real Vue components somewhere. That happens in the app-local client provider in `packages/main/src/client/providers/MainClientProvider.js`.
500
488
 
501
- After the `shell-web` install and the `Alerts Widget` generator command, that file contains registrations like these:
489
+ After the scaffold's shell registrations and the `Alerts Widget` generator command, that file contains registrations like these:
502
490
 
503
491
  ```js
504
492
  import AlertsWidgetElement from "/src/components/AlertsWidgetElement.vue";
@@ -570,9 +558,9 @@ The default error policy is intent-based. Runtime code reports what kind of erro
570
558
 
571
559
  `src/pages/home/index.vue` uses Vue Query to fetch `/api/health` and display the result in the UI.
572
560
 
573
- That is why this chapter is the point where running both `npm run dev` and `npm run server` matters. The page expects the backend to be alive.
561
+ That is why this chapter keeps running both `npm run dev` and `npm run server`. The page expects the backend to be alive.
574
562
 
575
- This matters because it is the first tiny example of the frontend and backend participating in the same shell. The request itself is simple, but the behavior is more realistic than the empty starter card from the previous chapter.
563
+ This matters because it is a tiny example of the frontend and backend participating in the same shell. The request itself is simple, but it proves the shell can surface runtime status instead of only rendering static chrome.
576
564
 
577
565
  ### The first client stores appear
578
566
 
@@ -676,6 +664,6 @@ The app is still structurally simple. `shell-web` just makes that simple app beh
676
664
 
677
665
  ## Summary
678
666
 
679
- After this chapter, the app is still small, but it has a shell shape. `shell-web` adds an app-owned shell layout, a placement registry, a shell error host, menu-link tokens in the local client provider, real drawer navigation, and the first nested settings section under `home`.
667
+ After this chapter, the app is still small, but you have inspected the shell shape it starts with. `shell-web` provides an app-owned shell layout, a placement registry, a shell error host, menu-link tokens in the local client provider, real drawer navigation, and the first nested settings section under `home`.
680
668
 
681
669
  More importantly, this chapter is where placements stop being theory. The shell already uses them for `Home`, `Settings`, and the starter `General` settings page. Then you inspect the available targets, place real UI into the outer shell, and add more child settings pages that automatically land in the nested settings menu. That is the first real example of JSKIT working as an extension system rather than just a scaffold generator.
@@ -12,9 +12,6 @@ To get back to the same starting point as the end of the previous chapter, run:
12
12
  npx @jskit-ai/create-app exampleapp --tenancy-mode none
13
13
  cd exampleapp
14
14
  npm install
15
-
16
- npx jskit add package shell-web
17
- npm install
18
15
  ```
19
16
 
20
17
  If you are already continuing from the previous chapter, you are already in the right place and can skip that setup.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Initial scaffolding
4
4
 
5
- In this first chapter, we are going to create the smallest useful JSKIT app, install its dependencies, run it locally, and read the scaffold it gives us. The goal of this chapter is to explain how to get started with JSKIT and to understand what the generator produced, which files matter, and why the project already has concepts like _surfaces_, a local runtime package, and a server even before we add any real features.
5
+ In this first chapter, we are going to create the smallest useful JSKIT app, install its dependencies, run it locally, and read the scaffold it gives us. The default scaffold already includes `shell-web`, so the app starts with a real shell, placements, settings routes, and the app-level error host. The goal of this chapter is to explain how to get started with JSKIT and to understand what the generator produced, which files matter, and why the project already has concepts like _surfaces_, a local runtime package, and a server even before we add any real features.
6
6
 
7
7
  Start in a working directory and run:
8
8
 
@@ -12,7 +12,7 @@ cd exampleapp
12
12
  npm install
13
13
  ```
14
14
 
15
- The first command creates a new folder called `exampleapp` and fills it with JSKIT's base shell template. The `exampleapp` name is used in a few template replacements, such as the package name and the browser title. The `--tenancy-mode none` flag tells JSKIT to start with the smallest routing model. In this mode, the app is not workspace-aware (more of this later in the guide, when multihoming is introduced). That keeps the first scaffold easier to read because there is no workspace slug handling yet.
15
+ The first command creates a new folder called `exampleapp` and fills it with JSKIT's default shell-web app template. The `exampleapp` name is used in a few template replacements, such as the package name and the browser title. The `--tenancy-mode none` flag tells JSKIT to start with the smallest routing model. In this mode, the app is not workspace-aware (more of this later in the guide, when multihoming is introduced). That keeps the first scaffold easier to read because there is no workspace slug handling yet.
16
16
 
17
17
  If you are working with an AI agent and want the agent to drive the initial JSKIT setup conversation, use the dedicated seed path:
18
18
 
@@ -30,7 +30,15 @@ npm install
30
30
 
31
31
  After that promotion, the overwritten app `AGENTS.md` stays deliberately small. Use it with the distributed JSKIT agent docs when planning or implementing app changes. The durable app memory lives in `.jskit/APP_BLUEPRINT.md` and should describe product and architecture decisions, not become an implementation task list.
32
32
 
33
- After creating the real app scaffolding (the base shell, not the seed wrapper), you will need to run `npm install` to install dependencies.
33
+ After creating the real app scaffolding (the default shell-web app, not the seed wrapper), you will need to run `npm install` to install dependencies.
34
+
35
+ If you deliberately need the older bare scaffold, use `--minimal` or `--template minimal-shell`. That is useful for descriptor tests or unusual package-development flows, but it is not the normal starting point for a JSKIT app:
36
+
37
+ ```bash
38
+ npx @jskit-ai/create-app exampleapp --minimal --tenancy-mode none
39
+ ```
40
+
41
+ Minimal apps can still install the standard shell later with `npx jskit add package shell-web`, as long as the starter files it claims have not been edited first.
34
42
 
35
43
  If you already know you want a small non-workspace baseline right after the scaffold, this is the shortest reproducible path:
36
44
 
@@ -47,8 +55,6 @@ npx @jskit-ai/create-app exampleapp --tenancy-mode none
47
55
  cd exampleapp
48
56
  npm install
49
57
 
50
- npx jskit add package shell-web
51
-
52
58
  npx jskit add package auth-provider-supabase-core \
53
59
  --auth-supabase-url "$SUPABASE_URL" \
54
60
  --auth-supabase-publishable-key "$SUPABASE_KEY" \
@@ -108,21 +114,19 @@ and press Tab, JSKIT will complete that subcommand argument to `package`.
108
114
 
109
115
  The `jskit` command is central in the use of JSKIT. The autocompletion will help speeding things up.
110
116
 
111
- To see the app in the browser, the quickest path is:
117
+ To see the app in the browser with the starter health check working, run the frontend and backend in two terminals:
112
118
 
113
119
  ```bash
114
120
  npm run dev
115
121
  ```
116
122
 
117
- Then open `http://localhost:5173/` in the browser. The starter screen is intentionally plain. That is a good thing. It proves the shell is wired correctly before we start adding packages.
118
-
119
- For the very first page, `npm run dev` is enough because the scaffold does not make any real API calls yet. For normal JSKIT development, though, you will usually keep a second terminal open and run the backend as well:
120
-
121
123
  ```bash
122
124
  npm run server
123
125
  ```
124
126
 
125
- That starts the Fastify server on port `3000`. As soon as you begin adding backend features, the frontend dev server will expect that backend to be there, because the Vite configuration proxies `/api` requests to the local server. A good habit is to treat `npm run dev` as the browser-facing process and `npm run server` as the app runtime behind it.
127
+ Then open `http://localhost:5173/` in the browser. The starter screen is intentionally small. That is a good thing. It proves the shell is wired correctly before we start adding packages.
128
+
129
+ `npm run server` starts the Fastify server on port `3000`. The default home page already uses the Vite proxy to request `/api/health`, so keep the backend running when you want the starter status to be fully green. A good habit is to treat `npm run dev` as the browser-facing process and `npm run server` as the app runtime behind it.
126
130
 
127
131
  If you want a fast sanity check that the backend is alive, open `http://localhost:3000/api/health` or request it from the terminal:
128
132
 
@@ -383,7 +387,7 @@ surfaceRuntime.listEnabledSurfaceIds(); // ["home"]
383
387
  surfaceRuntime.resolveSurfaceFromPathname("/home"); // "home"
384
388
  ```
385
389
 
386
- `surfaceMode` is not another surface definition. It is the current viewing mode for the app. In a plain starter app, `VITE_SURFACE` is usually unset, so `surfaceMode` becomes `"all"`, meaning "do not restrict the router to one specific surface". Later, when you run surface-specific profiles, the same runtime can narrow the active routes to just one surface. In the scaffold scripts, `npm run dev:home` is simply setting `VITE_SURFACE=home`, while `npm run dev` and `npm run dev:all` leave the client in unrestricted `"all"` mode.
390
+ `surfaceMode` is not another surface definition. It is the current viewing mode for the app. In a starter app, `VITE_SURFACE` is usually unset, so `surfaceMode` becomes `"all"`, meaning "do not restrict the router to one specific surface". Later, when you run surface-specific profiles, the same runtime can narrow the active routes to just one surface. In the scaffold scripts, `npm run dev:home` is simply setting `VITE_SURFACE=home`, while `npm run dev` and `npm run dev:all` leave the client in unrestricted `"all"` mode.
387
391
 
388
392
  `createShellRouter(...)` uses that `surfaceRuntime` object to assemble the actual router. Concretely, it does this:
389
393
 
@@ -403,7 +407,7 @@ In the starter app, with only `home`, this is almost boring. It mostly means:
403
407
 
404
408
  `createPinia()` is the standard shared-state layer for the client app. JSKIT installs it from day 0 so later packages can expose Vue-facing stores without each app having to bolt Pinia on afterward.
405
409
 
406
- In the plain starter scaffold there are still no package-defined client stores to use yet. Pinia is already there so later packages can add them without changing the app bootstrap. In the next chapters, `shell-web` adds shell stores such as `useShellLayoutStore()`, and `auth-web` later adds `useAuthStore()`.
410
+ The default scaffold already has the `shell-web` client stores available, such as `useShellLayoutStore()` and the shell error presentation store behind `ShellErrorHost`. Pinia is also there from day 0 so later packages, such as `auth-web`, can add their own stores without changing the app bootstrap.
407
411
 
408
412
  `createVuetify(...)` is the ordinary UI plugin setup. There is nothing especially JSKIT-specific there; it configures theme settings and icon aliases before the router is mounted. Vuetify components are auto-imported by `vite-plugin-vuetify`, so the scaffold does not register the full Vuetify component namespace in the client bundle.
409
413
 
@@ -521,7 +525,7 @@ export {
521
525
  };
522
526
  ```
523
527
 
524
- The important idea is that this provider is not rendering UI directly. It is registering token-addressable client components into the application container. In the base scaffold, that list starts empty. Later package installs and generators can extend this file by adding imports and `registerMainClientComponent(...)` calls for app-owned client components. In other words, this file is the app's local registration seam.
528
+ The important idea is that this provider is not rendering UI directly. It is registering token-addressable client components into the application container. In the default scaffold, the list starts with shell link components that the placement runtime can use for menus and tabs. Later package installs and generators can extend this file by adding imports and `registerMainClientComponent(...)` calls for more app-owned client components. In other words, this file is the app's local registration seam.
525
529
 
526
530
  ```js
527
531
  import MenuLinkItem from "/src/components/menus/MenuLinkItem.vue";
@@ -574,7 +578,7 @@ So the order is:
574
578
  2. the generated route record gets a normal `meta` object
575
579
  3. JSKIT reads that `meta` during routing
576
580
 
577
- `src/App.vue` is deliberately small. It is only the outer Vuetify app shell and a `RouterView`. That is another pattern you should get used to in JSKIT: the base scaffold stays thin, and most behavior is pushed toward packages, page files, and runtime providers.
581
+ `src/App.vue` is deliberately small. It is the outer Vuetify app shell, the top-level `RouterView`, and `ShellErrorHost`. That is another pattern you should get used to in JSKIT: the app root stays thin, and most behavior is pushed toward packages, page files, and runtime providers.
578
582
 
579
583
  **Container: App Methods**
580
584
 
@@ -686,7 +690,7 @@ async function createServer() {
686
690
 
687
691
  The health route is built in, but the more important idea is that the server is already prepared to validate HTTP input with Fastify's normal JSON Schema path, load the JSKIT provider runtime from the app itself, and constrain requests by surface.
688
692
 
689
- You will also notice `config/server.js`. In the base shell it is intentionally almost empty. It is there to reserve a clear place for server-side configuration as backend features are added, without pretending the starter app already has server behavior it does not yet need.
693
+ You will also notice `config/server.js`. In the base app it is intentionally almost empty. It is there to reserve a clear place for server-side configuration as backend features are added, without pretending the starter app already has feature-specific server configuration.
690
694
 
691
695
  The small `server/lib/` directory exists to keep that server boot code tidy. `runtimeEnv.js` reads environment variables such as port and host. `surfaceRuntime.js` builds the same surface runtime that the client uses, so the server and browser agree on what surfaces exist. In the scaffold scripts, `npm run server:home` is simply setting `SERVER_SURFACE=home`, while `npm run server` and `npm run server:all` leave the server unrestricted.
692
696
 
@@ -760,7 +764,7 @@ The `.jskit/lock.json` file is also important. Treat it like JSKIT's own lock an
760
764
 
761
765
  This file is narrower than `package.json`. `package.json` lists every npm dependency the app needs, including plain libraries such as Vue, Fastify, and Vuetify. `.jskit/lock.json` only tracks JSKIT package-install state: which JSKIT runtime packages were installed into the app and which files, text mutations, and dependency entries JSKIT is managing on their behalf.
762
766
 
763
- On a brand-new app, the lock file is telling you that only the local app package is installed so far:
767
+ On a brand-new default app, the lock file is telling you that the app-local package and the standard shell package are installed from the start:
764
768
 
765
769
  ```json
766
770
  {
@@ -774,35 +778,47 @@ On a brand-new app, the lock file is telling you that only the local app package
774
778
  "packagePath": "packages/main",
775
779
  "descriptorPath": "packages/main/package.descriptor.mjs"
776
780
  },
781
+ "managed": { "...": "..." }
782
+ },
783
+ "@jskit-ai/shell-web": {
784
+ "packageId": "@jskit-ai/shell-web",
785
+ "source": {
786
+ "type": "catalog"
787
+ },
777
788
  "managed": {
778
789
  "packageJson": {
779
790
  "dependencies": {
780
- "@local/main": {
781
- "value": "file:packages/main"
791
+ "@jskit-ai/shell-web": {
792
+ "value": "0.x"
793
+ },
794
+ "@mdi/js": {
795
+ "value": "^7.4.47"
782
796
  }
783
797
  }
784
- }
798
+ },
799
+ "files": { "...": "..." },
800
+ "text": { "...": "..." }
785
801
  }
786
802
  }
787
803
  }
788
804
  }
789
805
  ```
790
806
 
791
- That is a useful anchor point. Before you add anything else, JSKIT already knows about exactly one runtime package: the one that belongs to your app.
807
+ That is a useful anchor point. Before you add anything else, JSKIT already knows about the runtime package that belongs to your app and the shell runtime package that owns the default shell files, placement config, and error host wiring.
792
808
 
793
- That is why you saw `@jskit-ai/kernel` and `@jskit-ai/http-runtime` earlier in `package.json`, but you do not see them here. They are npm dependencies of the scaffold, but they are not separate JSKIT-installed app packages in this initial state.
809
+ That is why you saw `@jskit-ai/kernel` and `@jskit-ai/http-runtime` earlier in `package.json`, but you do not see them as separate installed packages here. They are npm dependencies of the scaffold, while `.jskit/lock.json` records JSKIT package install state and managed app mutations.
794
810
 
795
811
  ### Other files and options
796
812
 
797
813
  The remaining files are easier to understand once you know the core pieces above. `vite.config.mjs` configures the frontend build and the `/api` proxy used during development. `index.html` is the HTML shell Vite uses to mount Vue. `tests/` contains basic smoke tests so the app has a verification path from day one. The `scripts/` directory is intentionally small because JSKIT maintenance helpers such as `verify`, `jskit:update`, `devlinks`, and `release` are package-owned CLI commands rather than copied app scripts.
798
814
 
799
- The `create-app` command also accepts a few other flags that are useful without changing the basic meaning of this chapter's setup. `--title <text>` lets you replace the browser title and other template text with a friendlier app name. `--target <path>` lets you choose a different output directory instead of the default `./exampleapp`. `--tenancy-mode <mode>` can seed `none`, `personal`, or `workspaces`; for this chapter we intentionally use `none` so the first scaffold stays small and non-workspace. `--force` allows writing into a non-empty target directory when you know that is what you want. `--dry-run` prints the planned file writes without touching the filesystem, which is useful when you want to inspect what the generator would do. `-h` or `--help` prints the command help.
815
+ The `create-app` command also accepts a few other flags that are useful without changing the basic meaning of this chapter's setup. `--title <text>` lets you replace the browser title and other template text with a friendlier app name. `--target <path>` lets you choose a different output directory instead of the default `./exampleapp`. `--tenancy-mode <mode>` can seed `none`, `personal`, or `workspaces`; for this chapter we intentionally use `none` so the first scaffold stays small and non-workspace. `--minimal` selects the bare `minimal-shell` template instead of the default shell-web app template. `--force` allows writing into a non-empty target directory when you know that is what you want. `--dry-run` prints the planned file writes without touching the filesystem, which is useful when you want to inspect what the generator would do. `-h` or `--help` prints the command help.
800
816
 
801
- **Next step: Install shell-web before editing the scaffold**
817
+ **Template: Use The Default Shell Unless You Need Minimal**
802
818
 
803
- If the next thing you plan to do is install `shell-web`, do that **before** you start personalizing the starter shell files.
819
+ The default app already includes `shell-web`. Start there for normal JSKIT apps because it gives you placement-aware navigation, settings routes, and shell-level error presentation immediately.
804
820
 
805
- `shell-web` upgrades the plain scaffold by claiming a few app-owned files such as `src/App.vue`, `src/pages/home.vue`, and `src/pages/home/index.vue`. It only does that when those files still match the untouched base scaffold exactly. If you edit them first, `shell-web` will refuse to overwrite your changes.
821
+ Use `--minimal` only when you deliberately need the bare scaffold. If you later add `shell-web` to a minimal app, do it before editing files such as `src/App.vue`, `src/pages/home.vue`, and `src/pages/home/index.vue`, because the package only claims files that still match the untouched minimal baseline exactly.
806
822
 
807
823
  ## Summary
808
824
 
@@ -510,7 +510,7 @@ The other returned values are there for more advanced cases.
510
510
  - `placementContext` matters when a page needs to read the current shell/bootstrap context directly, for example available workspaces or current permissions already in the shell state.
511
511
  - `mergePlacementContext` is for pages that need to push refreshed workspace data back into the shell runtime after a fetch or save.
512
512
 
513
- That second case is real, but it is more advanced. It is what packaged elements such as the workspace settings client use when they need the shell's current workspace badge, selector state, or permissions to refresh after a change.
513
+ That second case is real, but it is more advanced. It is available for app-owned workspace pages that intentionally need to push refreshed workspace state back into shell-visible context after a save.
514
514
 
515
515
  For normal custom page code, you usually do **not** start there. Start with `workspaceSlugFromRoute`.
516
516
 
@@ -589,7 +589,8 @@ That one block explains a lot of the workspace shell behavior.
589
589
  - `shell.identity` carries the workspace selector
590
590
  - `shell.status` can show a pending-invites cue
591
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`
592
+ - the admin surface gets a workspace tools menu with `Settings` and `Members`
593
+ - the workspace settings shell exposes its own nested menu host for app-owned settings child pages
593
594
 
594
595
  If you want to add your own app-owned page into that top cog menu, first ask JSKIT which semantic placements exist:
595
596
 
@@ -50,8 +50,6 @@ npx @jskit-ai/create-app testapp --tenancy-mode personal
50
50
  cd testapp
51
51
  npm install
52
52
 
53
- npx jskit add package shell-web
54
-
55
53
  npx jskit add package auth-provider-supabase-core \
56
54
  --auth-supabase-url "$SUPABASE_URL" \
57
55
  --auth-supabase-publishable-key "$SUPABASE_KEY" \
@@ -28,7 +28,7 @@ The easiest way to understand `jskit` is to separate it from the other tools in
28
28
 
29
29
  That separation is crucial.
30
30
 
31
- When you run a command such as `npx jskit add package shell-web`, JSKIT updates app-owned files and records what it changed. It does **not** replace npm, Vite, or Knex.
31
+ When you run a command such as `npx jskit add package auth-provider-supabase-core`, JSKIT updates app-owned files and records what it changed. It does **not** replace npm, Vite, or Knex.
32
32
 
33
33
  The most important record of that managed state lives here:
34
34
 
@@ -476,7 +476,7 @@ This is not required, but it is genuinely useful once you start using commands s
476
476
  The install command comes in two main forms:
477
477
 
478
478
  ```bash
479
- npx jskit add package shell-web
479
+ npx jskit add package auth-provider-supabase-core
480
480
  npx jskit add bundle auth-base
481
481
  ```
482
482
 
@@ -487,22 +487,22 @@ Those two examples look similar, but they do different things.
487
487
  Use this when you know the exact runtime package you want:
488
488
 
489
489
  ```bash
490
- npx jskit add package shell-web
490
+ npx jskit add package users-web
491
491
  ```
492
492
 
493
- This is the command the next chapter uses.
493
+ This is the shape of the package install commands used throughout the rest of the guide.
494
494
 
495
495
  Important defaults:
496
496
 
497
- - short ids such as `shell-web` resolve to `@jskit-ai/shell-web` when available
497
+ - short ids such as `users-web` resolve to `@jskit-ai/users-web` when available
498
498
  - JSKIT records the install in `.jskit/lock.json`
499
499
  - JSKIT rewrites app-owned managed files as needed
500
500
  - npm install does **not** run unless you ask for it with `--run-npm-install`
501
501
 
502
- That last point is why the normal guide flow is still:
502
+ That last point is why the normal guide flow after adding a runtime package is still:
503
503
 
504
504
  ```bash
505
- npx jskit add package shell-web
505
+ npx jskit add package users-web
506
506
  npm install
507
507
  ```
508
508
 
@@ -1079,4 +1079,4 @@ And then keep one more distinction in your head:
1079
1079
 
1080
1080
  That is the mental model the rest of the guide assumes.
1081
1081
 
1082
- The next chapter goes back to the normal hands-on flow and uses that model immediately by installing `shell-web`.
1082
+ The next chapter goes back to the normal hands-on flow and uses that model while inspecting the shell that default apps already include.
@@ -4,7 +4,7 @@
4
4
 
5
5
  This guide is the main hands-on path through JSKIT.
6
6
 
7
- It starts with a fast reproducible Quickstart, then steps back to the smaller scaffold-first chapters that explain how the app is assembled piece by piece. After that, it introduces the database-backed users layer, expands into console and workspace-aware app structure, and adds a small `App extras` section for optional runtime packages such as the Android Capacitor shell, realtime, and assistant. Finally, the guide breaks out generator-specific workflows into their own section.
7
+ It starts with a fast reproducible Quickstart, then steps back to the scaffold-first chapters that explain the default shell and runtime shape. After that, it introduces the database-backed users layer, expands into console and workspace-aware app structure, and adds a small `App extras` section for optional runtime packages such as the Android Capacitor shell, realtime, and assistant. Finally, the guide breaks out generator-specific workflows into their own section.
8
8
 
9
9
  ## Table of Contents
10
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/agent-docs",
3
- "version": "0.1.47",
3
+ "version": "0.1.48",
4
4
  "description": "Distributed JSKIT agent references, prompts, guides, and generated reference maps.",
5
5
  "type": "module",
6
6
  "files": [
@@ -657,6 +657,19 @@ Exports
657
657
  Local functions
658
658
  - `normalizeClientAppConfig(source = {})`
659
659
 
660
+ ### `client/asyncModuleRecovery.js`
661
+ Exports
662
+ - `createAsyncModuleRecoveryState({ label = "App module", message = "", retry = null } = {})`
663
+ - `dismissAsyncModuleRecovery(state)`
664
+ - `dynamicImportErrorMessage(error = null, { label = "App module", stale = isDynamicImportError(error) } = {})`
665
+ - `guardedReloadApp({ browserWindow = typeof window !== "undefined" ? window : null, fetchFn = typeof fetch === "function" ? fetch : null, state = null, label = "App", message = "The app cannot reload because the app server is not reachable. Restart the server, then click Retry or Reload." } = {})`
666
+ - `installAsyncModuleRecoveryHandlers({ router = null, state, label = "App module", onNotify = null, windowObject = typeof window !== "undefined" ? window : null } = {})`
667
+ - `isDynamicImportError(error = null)`
668
+ - `notifyAsyncModuleLoadError(state, error = null, { label = "App module", message = "", retry = null, stale = isDynamicImportError(error) } = {})`
669
+ Local functions
670
+ - `isRecord(value)`
671
+ - `errorText(error = null)`
672
+
660
673
  ### `client/componentInteraction.js`
661
674
  Exports
662
675
  - `createComponentInteractionEmitter(emit)`
@@ -673,6 +686,13 @@ Exports
673
686
  - `getClientAppConfig`
674
687
  - `resolveMobileConfig`
675
688
  - `resolveClientAssetMode`
689
+ - `createAsyncModuleRecoveryState`
690
+ - `dismissAsyncModuleRecovery`
691
+ - `dynamicImportErrorMessage`
692
+ - `guardedReloadApp`
693
+ - `installAsyncModuleRecoveryHandlers`
694
+ - `isDynamicImportError`
695
+ - `notifyAsyncModuleLoadError`
676
696
  - `normalizeIncomingAppUrl`
677
697
  - `registerMobileLaunchRouting`
678
698
  - `resolveClientBootstrapDebugEnabled`
@@ -308,21 +308,26 @@ Local functions
308
308
  - `isValidSurfaceIdToken(value = "")`
309
309
  - `toInteger(value, fallback = 1000)`
310
310
 
311
+ ### `src/client/providers/appModuleLoadFailure.js`
312
+ Exports
313
+ - `isMissingDynamicModule(error, moduleSpecifier)`
314
+ - `notifyDynamicImportFailure(asyncModuleRecoveryRuntime, error, { label = "App module" } = {})`
315
+
311
316
  ### `src/client/providers/ShellWebClientProvider.js`
312
317
  Exports
313
318
  - `ShellWebClientProvider`
314
319
  - `resolveAppPlacementTopologyExport(exported, logger)`
315
320
  Local functions
316
- - `isMissingDynamicModule(error, moduleSpecifier)`
317
- - `loadAppPlacementDefinitions(logger)`
318
- - `loadAppPlacementTopology(logger)`
321
+ - `loadAppPlacementDefinitions(logger, asyncModuleRecoveryRuntime = null)`
322
+ - `loadAppPlacementTopology(logger, asyncModuleRecoveryRuntime = null)`
319
323
  - `createErrorConfigToolkit(errorRuntime)`
320
- - `loadAppErrorConfig(logger, errorRuntime)`
324
+ - `loadAppErrorConfig(logger, errorRuntime, asyncModuleRecoveryRuntime = null)`
321
325
  - `applyAppErrorConfig(errorRuntime, errorConfig = {})`
322
326
  - `isPullRefreshQuery(query = null)`
323
327
  - `createShellRefreshRuntime({ app, logger = null } = {})`
324
328
  - `installVueErrorBridge(vueApp, errorRuntime, logger)`
325
329
  - `installRouterErrorBridge(app, errorRuntime, logger)`
330
+ - `createShellAsyncModuleRecoveryRuntime({ app, logger = null } = {})`
326
331
 
327
332
  ### `src/client/runtime/bootstrapRuntime.js`
328
333
  Exports
@@ -142,6 +142,26 @@ Exports
142
142
  Exports
143
143
  - None
144
144
 
145
+ ### `templates/base-shell/src/components/menus/MenuLinkItem.vue`
146
+ Exports
147
+ - None
148
+
149
+ ### `templates/base-shell/src/components/menus/SurfaceAwareMenuLinkItem.vue`
150
+ Exports
151
+ - None
152
+
153
+ ### `templates/base-shell/src/components/menus/TabLinkItem.vue`
154
+ Exports
155
+ - None
156
+
157
+ ### `templates/base-shell/src/components/ShellLayout.vue`
158
+ Exports
159
+ - `default`
160
+
161
+ ### `templates/base-shell/src/error.js`
162
+ Exports
163
+ - None
164
+
145
165
  ### `templates/base-shell/src/main.js`
146
166
  Exports
147
167
  - None
@@ -154,6 +174,28 @@ Exports
154
174
  Exports
155
175
  - None
156
176
 
177
+ ### `templates/base-shell/src/pages/home/settings.vue`
178
+ Exports
179
+ - None
180
+
181
+ ### `templates/base-shell/src/pages/home/settings/general/index.vue`
182
+ Exports
183
+ - None
184
+
185
+ ### `templates/base-shell/src/pages/home/settings/index.vue`
186
+ Exports
187
+ - None
188
+
189
+ ### `templates/base-shell/src/placement.js`
190
+ Exports
191
+ - `addPlacement`
192
+ - `getPlacements()`
193
+
194
+ ### `templates/base-shell/src/placementTopology.js`
195
+ Exports
196
+ - `addPlacementTopology(value = {})`
197
+ - `default`
198
+
157
199
  ### `templates/base-shell/src/views/NotFound.vue`
158
200
  Exports
159
201
  - None
@@ -169,6 +211,114 @@ Exports
169
211
  - `toPositiveInt(value, fallback)`
170
212
  - `loadViteDevProxyEntries({ appRootUrl = import.meta.url, fallbackTarget = "" } = {})`
171
213
 
214
+ ### `templates/minimal-shell/bin/server.js`
215
+ Exports
216
+ - None
217
+
218
+ ### `templates/minimal-shell/config/public.js`
219
+ Exports
220
+ - `config`
221
+
222
+ ### `templates/minimal-shell/config/server.js`
223
+ Exports
224
+ - `config`
225
+
226
+ ### `templates/minimal-shell/config/surfaceAccessPolicies.js`
227
+ Exports
228
+ - `surfaceAccessPolicies`
229
+
230
+ ### `templates/minimal-shell/eslint.config.mjs`
231
+ Exports
232
+ - None
233
+
234
+ ### `templates/minimal-shell/packages/main/package.descriptor.mjs`
235
+ Exports
236
+ - None
237
+
238
+ ### `templates/minimal-shell/packages/main/src/client/index.js`
239
+ Exports
240
+ - `MainClientProvider`
241
+ - `registerMainClientComponent`
242
+
243
+ ### `templates/minimal-shell/packages/main/src/client/providers/MainClientProvider.js`
244
+ Exports
245
+ - `MainClientProvider`
246
+ - `registerMainClientComponent(token, resolveComponent)`
247
+
248
+ ### `templates/minimal-shell/packages/main/src/server/index.js`
249
+ Exports
250
+ - `MainServiceProvider`
251
+
252
+ ### `templates/minimal-shell/packages/main/src/server/loadAppConfig.js`
253
+ Exports
254
+ - `loadAppConfig({ moduleUrl = import.meta.url } = {})`
255
+
256
+ ### `templates/minimal-shell/packages/main/src/server/MainServiceProvider.js`
257
+ Exports
258
+ - `MainServiceProvider`
259
+
260
+ ### `templates/minimal-shell/packages/main/src/shared/index.js`
261
+ Exports
262
+ - None
263
+
264
+ ### `templates/minimal-shell/packages/main/src/shared/schemas/index.js`
265
+ Exports
266
+ - None
267
+
268
+ ### `templates/minimal-shell/server.js`
269
+ Exports
270
+ - `createServer()`
271
+ - `startServer(options = {})`
272
+ Local functions
273
+ - `toRequestPathname(urlValue)`
274
+ - `isApiPath(pathname)`
275
+ - `hasFileExtension(pathname)`
276
+ - `resolveGlobalUiPaths(runtimeGlobalUiPaths = [])`
277
+ - `resolveStaticFilePath(pathname)`
278
+ - `canServeStaticFile(distRoot, relativePath)`
279
+
280
+ ### `templates/minimal-shell/server/lib/runtimeEnv.js`
281
+ Exports
282
+ - `resolveRuntimeEnv()`
283
+ Local functions
284
+ - `toPort(value, fallback = 3000)`
285
+ - `ensureRuntimeEnvLoaded()`
286
+
287
+ ### `templates/minimal-shell/server/lib/surfaceRuntime.js`
288
+ Exports
289
+ - `surfaceRuntime`
290
+
291
+ ### `templates/minimal-shell/src/App.vue`
292
+ Exports
293
+ - None
294
+
295
+ ### `templates/minimal-shell/src/main.js`
296
+ Exports
297
+ - None
298
+
299
+ ### `templates/minimal-shell/src/pages/home.vue`
300
+ Exports
301
+ - None
302
+
303
+ ### `templates/minimal-shell/src/pages/home/index.vue`
304
+ Exports
305
+ - None
306
+
307
+ ### `templates/minimal-shell/src/views/NotFound.vue`
308
+ Exports
309
+ - None
310
+
311
+ ### `templates/minimal-shell/vite.config.mjs`
312
+ Exports
313
+ - None
314
+ Local functions
315
+ - `clientEntry(()`
316
+
317
+ ### `templates/minimal-shell/vite.shared.mjs`
318
+ Exports
319
+ - `toPositiveInt(value, fallback)`
320
+ - `loadViteDevProxyEntries({ appRootUrl = import.meta.url, fallbackTarget = "" } = {})`
321
+
172
322
  ### bin
173
323
 
174
324
  ### `bin/jskit-create-app.js`