@jskit-ai/agent-docs 0.1.131 → 0.1.133

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/existing-application-migration.md +273 -0
  9. package/guide/agent/app-setup/initial-scaffolding.md +50 -784
  10. package/guide/agent/app-setup/multi-homing.md +39 -712
  11. package/guide/agent/app-setup/quickstart.md +43 -179
  12. package/guide/agent/app-setup/users.md +34 -353
  13. package/guide/agent/index.md +17 -23
  14. package/package.json +2 -2
  15. package/patterns/INDEX.md +7 -7
  16. package/patterns/child-cruds.md +3 -3
  17. package/patterns/client-requests.md +6 -6
  18. package/patterns/crud-authoring.md +94 -0
  19. package/patterns/crud-links.md +1 -1
  20. package/patterns/feature-package/PATTERN.md +108 -0
  21. package/patterns/feature-package/example/booking-engine/package.json +48 -0
  22. package/patterns/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +33 -0
  23. package/patterns/feature-package/example/booking-engine/src/server/actions.js +26 -0
  24. package/patterns/feature-package/example/booking-engine/src/server/inputSchemas.js +19 -0
  25. package/patterns/feature-package/example/variations/AvailabilityEngineProvider.js +31 -0
  26. package/patterns/feature-package/example/variations/InvoiceRollupProvider.js +36 -0
  27. package/patterns/feature-package/example/variations/customKnexRepository.js +34 -0
  28. package/patterns/feature-package/example/variations/orchestratorService.js +23 -0
  29. package/patterns/filters.md +8 -8
  30. package/patterns/live-actions.md +5 -18
  31. package/patterns/minimal-foundation/PATTERN.md +98 -0
  32. package/patterns/minimal-foundation/example/.nvmrc +1 -0
  33. package/patterns/minimal-foundation/example/AGENTS.md +17 -0
  34. package/patterns/minimal-foundation/example/Procfile +2 -0
  35. package/patterns/minimal-foundation/example/app.json +14 -0
  36. package/patterns/minimal-foundation/example/bin/develop.js +71 -0
  37. package/patterns/minimal-foundation/example/bin/server.js +8 -0
  38. package/patterns/minimal-foundation/example/config/public.js +40 -0
  39. package/patterns/minimal-foundation/example/config/server.js +1 -0
  40. package/patterns/minimal-foundation/example/config/surfaceAccessPolicies.js +3 -0
  41. package/patterns/minimal-foundation/example/eslint.config.mjs +19 -0
  42. package/patterns/minimal-foundation/example/favicon.svg +7 -0
  43. package/patterns/minimal-foundation/example/gitignore +9 -0
  44. package/patterns/minimal-foundation/example/index.html +13 -0
  45. package/patterns/minimal-foundation/example/jsconfig.json +8 -0
  46. package/patterns/minimal-foundation/example/package.json +57 -0
  47. package/patterns/minimal-foundation/example/packages/main/package.json +42 -0
  48. package/patterns/minimal-foundation/example/packages/main/src/shared/index.js +10 -0
  49. package/patterns/minimal-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  50. package/patterns/minimal-foundation/example/playwright.config.mjs +31 -0
  51. package/patterns/minimal-foundation/example/server/lib/runtimeEnv.js +45 -0
  52. package/patterns/minimal-foundation/example/server/lib/surfaceRuntime.js +10 -0
  53. package/patterns/minimal-foundation/example/server.js +195 -0
  54. package/patterns/minimal-foundation/example/src/App.vue +13 -0
  55. package/patterns/minimal-foundation/example/src/main.js +85 -0
  56. package/patterns/minimal-foundation/example/src/pages/home/index.vue +48 -0
  57. package/patterns/minimal-foundation/example/src/pages/home.vue +13 -0
  58. package/patterns/minimal-foundation/example/src/views/NotFound.vue +13 -0
  59. package/patterns/minimal-foundation/example/tests/client/smoke.vitest.js +7 -0
  60. package/patterns/minimal-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  61. package/patterns/minimal-foundation/example/tests/server/smoke.test.js +16 -0
  62. package/patterns/minimal-foundation/example/vite.config.mjs +81 -0
  63. package/patterns/page-scaffolding.md +20 -17
  64. package/patterns/placements.md +17 -15
  65. package/patterns/row-policies.md +4 -5
  66. package/patterns/server-search.md +3 -3
  67. package/patterns/shell-foundation/PATTERN.md +104 -0
  68. package/patterns/shell-foundation/example/.nvmrc +1 -0
  69. package/patterns/shell-foundation/example/AGENTS.md +17 -0
  70. package/patterns/shell-foundation/example/Procfile +2 -0
  71. package/patterns/shell-foundation/example/app.json +14 -0
  72. package/patterns/shell-foundation/example/bin/develop.js +71 -0
  73. package/patterns/shell-foundation/example/bin/server.js +8 -0
  74. package/patterns/shell-foundation/example/config/public.js +40 -0
  75. package/patterns/shell-foundation/example/config/server.js +1 -0
  76. package/patterns/shell-foundation/example/config/surfaceAccessPolicies.js +3 -0
  77. package/patterns/shell-foundation/example/eslint.config.mjs +19 -0
  78. package/patterns/shell-foundation/example/favicon.svg +7 -0
  79. package/patterns/shell-foundation/example/gitignore +9 -0
  80. package/patterns/shell-foundation/example/index.html +13 -0
  81. package/patterns/shell-foundation/example/jsconfig.json +8 -0
  82. package/patterns/shell-foundation/example/package.json +59 -0
  83. package/patterns/shell-foundation/example/packages/main/package.json +56 -0
  84. package/patterns/shell-foundation/example/packages/main/src/client/index.js +9 -0
  85. package/patterns/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +18 -0
  86. package/patterns/shell-foundation/example/packages/main/src/shared/index.js +10 -0
  87. package/patterns/shell-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  88. package/patterns/shell-foundation/example/playwright.config.mjs +31 -0
  89. package/patterns/shell-foundation/example/server/lib/runtimeEnv.js +45 -0
  90. package/patterns/shell-foundation/example/server/lib/surfaceRuntime.js +10 -0
  91. package/patterns/shell-foundation/example/server.js +195 -0
  92. package/patterns/shell-foundation/example/src/App.vue +11 -0
  93. package/patterns/shell-foundation/example/src/components/ShellLayout.vue +12 -0
  94. package/patterns/shell-foundation/example/src/components/menus/MenuLinkItem.vue +30 -0
  95. package/patterns/shell-foundation/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  96. package/patterns/shell-foundation/example/src/components/menus/TabLinkItem.vue +42 -0
  97. package/patterns/shell-foundation/example/src/error.js +19 -0
  98. package/patterns/shell-foundation/example/src/main.js +85 -0
  99. package/patterns/shell-foundation/example/src/pages/home/index.vue +116 -0
  100. package/patterns/shell-foundation/example/src/pages/home/settings/general/index.vue +40 -0
  101. package/patterns/shell-foundation/example/src/pages/home/settings/index.vue +7 -0
  102. package/patterns/shell-foundation/example/src/pages/home/settings.vue +109 -0
  103. package/patterns/shell-foundation/example/src/pages/home.vue +20 -0
  104. package/patterns/shell-foundation/example/src/placement.js +56 -0
  105. package/patterns/shell-foundation/example/src/placementTopology.js +149 -0
  106. package/patterns/shell-foundation/example/src/views/NotFound.vue +13 -0
  107. package/patterns/shell-foundation/example/tests/client/smoke.vitest.js +7 -0
  108. package/patterns/shell-foundation/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  109. package/patterns/shell-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  110. package/patterns/shell-foundation/example/tests/server/smoke.test.js +16 -0
  111. package/patterns/shell-foundation/example/vite.config.mjs +81 -0
  112. package/patterns/ui-contract.md +56 -0
  113. package/patterns/ui-testing.md +10 -12
  114. package/reference/autogen/KERNEL_MAP.md +29 -107
  115. package/reference/autogen/PATTERN_INDEX.md +230 -0
  116. package/reference/autogen/README.md +4 -8
  117. package/reference/autogen/packages/agent-docs.md +259 -0
  118. package/reference/autogen/packages/assistant-core.md +3 -3
  119. package/reference/autogen/packages/assistant-runtime.md +32 -17
  120. package/reference/autogen/packages/auth-core.md +31 -33
  121. package/reference/autogen/packages/auth-provider-local-core.md +4 -12
  122. package/reference/autogen/packages/auth-provider-local-db-core.md +4 -4
  123. package/reference/autogen/packages/auth-provider-supabase-core.md +14 -18
  124. package/reference/autogen/packages/auth-web.md +42 -22
  125. package/reference/autogen/packages/console-core.md +8 -25
  126. package/reference/autogen/packages/console-web.md +5 -5
  127. package/reference/autogen/packages/crud-core.md +61 -17
  128. package/reference/autogen/packages/database-runtime-mysql.md +12 -2
  129. package/reference/autogen/packages/database-runtime-postgres.md +12 -2
  130. package/reference/autogen/packages/database-runtime.md +26 -25
  131. package/reference/autogen/packages/google-rewarded-core.md +19 -104
  132. package/reference/autogen/packages/http-runtime.md +4 -8
  133. package/reference/autogen/packages/http-web.md +32 -0
  134. package/reference/autogen/packages/json-rest-api-core.md +4 -6
  135. package/reference/autogen/packages/kernel.md +109 -390
  136. package/reference/autogen/packages/mobile-capacitor.md +2 -13
  137. package/reference/autogen/packages/realtime.md +29 -26
  138. package/reference/autogen/packages/resource-crud-core.md +6 -0
  139. package/reference/autogen/packages/shell-web.md +69 -54
  140. package/reference/autogen/packages/storage-runtime.md +3 -3
  141. package/reference/autogen/packages/uploads-image-web.md +0 -1
  142. package/reference/autogen/packages/uploads-runtime.md +3 -3
  143. package/reference/autogen/packages/users-core.md +45 -90
  144. package/reference/autogen/packages/users-web.md +5 -7
  145. package/reference/autogen/packages/workspaces-core.md +53 -74
  146. package/reference/autogen/packages/workspaces-web.md +15 -16
  147. package/reference/autogen/tooling/jskit-catalog.md +34 -0
  148. package/reference/autogen/tooling/testUtils.md +4 -4
  149. package/skills/jskit/SKILL.md +38 -31
  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 +1 -1
  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
@@ -0,0 +1,109 @@
1
+ <script setup>
2
+ import ShellOutlet from "@jskit-ai/shell-web/client/components/ShellOutlet";
3
+ import { RouterView } from "vue-router";
4
+ </script>
5
+
6
+ <template>
7
+ <section class="settings-shell d-flex flex-column ga-4">
8
+ <header>
9
+ <p class="text-overline text-medium-emphasis mb-1">Settings</p>
10
+ <h1 class="settings-shell__title">Home settings</h1>
11
+ <p class="text-body-2 text-medium-emphasis mb-0">Configure shell behavior for this surface.</p>
12
+ </header>
13
+
14
+ <v-sheet rounded="lg" border class="settings-shell__panel">
15
+ <div class="settings-shell__body">
16
+ <nav class="settings-shell__nav" aria-label="Home settings sections">
17
+ <v-list nav density="compact" rounded="lg">
18
+ <ShellOutlet target="home-settings:primary-menu" />
19
+ </v-list>
20
+ </nav>
21
+
22
+ <main class="settings-shell__content">
23
+ <RouterView />
24
+ </main>
25
+ </div>
26
+ </v-sheet>
27
+ </section>
28
+ </template>
29
+
30
+ <style scoped>
31
+ .settings-shell {
32
+ --settings-title-size: 1.85rem;
33
+ --settings-panel-padding: 1rem;
34
+ }
35
+
36
+ .settings-shell__title {
37
+ font-size: var(--settings-title-size);
38
+ font-weight: 650;
39
+ letter-spacing: 0;
40
+ line-height: 1.15;
41
+ margin: 0 0 0.35rem;
42
+ }
43
+
44
+ .settings-shell__panel {
45
+ overflow: hidden;
46
+ }
47
+
48
+ .settings-shell__body {
49
+ display: grid;
50
+ gap: 1rem;
51
+ grid-template-columns: minmax(12rem, 16rem) minmax(0, 1fr);
52
+ padding: var(--settings-panel-padding);
53
+ }
54
+
55
+ .settings-shell__content {
56
+ border-left: 1px solid rgba(var(--v-theme-on-surface), 0.18);
57
+ min-width: 0;
58
+ padding-left: 1rem;
59
+ }
60
+
61
+ .settings-shell__nav :deep(.v-list) {
62
+ padding: 0.35rem;
63
+ }
64
+
65
+ .settings-shell__nav :deep(.v-list-item) {
66
+ min-height: 48px;
67
+ padding-inline: 0.6rem 0.7rem;
68
+ }
69
+
70
+ .settings-shell__nav :deep(.v-list-item__prepend) {
71
+ margin-inline-end: 0;
72
+ }
73
+
74
+ .settings-shell__nav :deep(.v-list-item__spacer) {
75
+ min-width: 0.5rem;
76
+ width: 0.5rem;
77
+ }
78
+
79
+ .settings-shell__nav :deep(.v-list-item-title) {
80
+ line-height: 1.2;
81
+ }
82
+
83
+ @media (max-width: 960px) {
84
+ .settings-shell {
85
+ --settings-title-size: 1.35rem;
86
+ }
87
+
88
+ .settings-shell__body {
89
+ grid-template-columns: 1fr;
90
+ }
91
+
92
+ .settings-shell__nav :deep(.v-list) {
93
+ display: flex;
94
+ gap: 0.25rem;
95
+ overflow-x: auto;
96
+ scrollbar-width: thin;
97
+ }
98
+
99
+ .settings-shell__nav :deep(.v-list-item) {
100
+ flex: 0 0 auto;
101
+ min-height: 48px;
102
+ }
103
+
104
+ .settings-shell__content {
105
+ border-left: 0;
106
+ padding-left: 0;
107
+ }
108
+ }
109
+ </style>
@@ -0,0 +1,20 @@
1
+ <route lang="json">
2
+ {
3
+ "meta": {
4
+ "jskit": {
5
+ "surface": "home"
6
+ }
7
+ }
8
+ }
9
+ </route>
10
+
11
+ <script setup>
12
+ import ShellLayout from "@/components/ShellLayout.vue";
13
+ import { RouterView } from "vue-router";
14
+ </script>
15
+
16
+ <template>
17
+ <ShellLayout title="" subtitle="">
18
+ <RouterView />
19
+ </ShellLayout>
20
+ </template>
@@ -0,0 +1,56 @@
1
+ import { createPlacementRegistry } from "@jskit-ai/shell-web/client/placement";
2
+
3
+ const registry = createPlacementRegistry();
4
+ const { addPlacement } = registry;
5
+
6
+ export { addPlacement };
7
+
8
+ // Keep the default export near the top so module installers can append addPlacement(...)
9
+ // blocks at the bottom of this file without changing the export section.
10
+ export default function getPlacements() {
11
+ return registry.build();
12
+ }
13
+
14
+ addPlacement({
15
+ id: "shell-web.home.menu.home",
16
+ target: "shell.primary-nav",
17
+ kind: "link",
18
+ surfaces: ["home"],
19
+ order: 50,
20
+ props: {
21
+ label: "Home",
22
+ surface: "home",
23
+ scopedSuffix: "/",
24
+ unscopedSuffix: "/",
25
+ exact: true
26
+ }
27
+ });
28
+
29
+ addPlacement({
30
+ id: "shell-web.home.menu.settings",
31
+ target: "shell.primary-nav",
32
+ kind: "link",
33
+ surfaces: ["home"],
34
+ order: 100,
35
+ props: {
36
+ label: "Settings",
37
+ surface: "home",
38
+ scopedSuffix: "/settings",
39
+ unscopedSuffix: "/settings"
40
+ }
41
+ });
42
+
43
+ addPlacement({
44
+ id: "shell-web.home.settings.general",
45
+ target: "page.section-nav",
46
+ owner: "home-settings",
47
+ kind: "link",
48
+ surfaces: ["home"],
49
+ order: 100,
50
+ props: {
51
+ label: "General",
52
+ surface: "home",
53
+ scopedSuffix: "/settings/general",
54
+ unscopedSuffix: "/settings/general"
55
+ }
56
+ });
@@ -0,0 +1,149 @@
1
+ const placements = [];
2
+
3
+ function addPlacementTopology(value = {}) {
4
+ placements.push(value);
5
+ }
6
+
7
+ export { addPlacementTopology };
8
+ export default { placements };
9
+
10
+ const menuLinkRenderers = Object.freeze({
11
+ link: "local.main.ui.surface-aware-menu-link-item"
12
+ });
13
+
14
+ const bottomNavLinkRenderers = Object.freeze({
15
+ link: "local.main.ui.tab-link-item"
16
+ });
17
+
18
+ addPlacementTopology({
19
+ id: "shell.primary-nav",
20
+ description: "Primary top-level navigation for the current surface.",
21
+ surfaces: ["*"],
22
+ default: true,
23
+ variants: {
24
+ compact: {
25
+ outlet: "shell-layout:primary-bottom-nav",
26
+ renderers: bottomNavLinkRenderers
27
+ },
28
+ medium: {
29
+ outlet: "shell-layout:primary-menu",
30
+ renderers: menuLinkRenderers
31
+ },
32
+ expanded: {
33
+ outlet: "shell-layout:primary-menu",
34
+ renderers: menuLinkRenderers
35
+ }
36
+ }
37
+ });
38
+
39
+ addPlacementTopology({
40
+ id: "shell.secondary-nav",
41
+ description: "Secondary navigation for the current surface.",
42
+ surfaces: ["*"],
43
+ variants: {
44
+ compact: {
45
+ outlet: "shell-layout:secondary-menu",
46
+ renderers: menuLinkRenderers
47
+ },
48
+ medium: {
49
+ outlet: "shell-layout:secondary-menu",
50
+ renderers: menuLinkRenderers
51
+ },
52
+ expanded: {
53
+ outlet: "shell-layout:secondary-menu",
54
+ renderers: menuLinkRenderers
55
+ }
56
+ }
57
+ });
58
+
59
+ addPlacementTopology({
60
+ id: "shell.identity",
61
+ description: "Current surface identity and switcher controls.",
62
+ surfaces: ["*"],
63
+ variants: {
64
+ compact: {
65
+ outlet: "shell-layout:top-left"
66
+ },
67
+ medium: {
68
+ outlet: "shell-layout:top-left"
69
+ },
70
+ expanded: {
71
+ outlet: "shell-layout:top-left"
72
+ }
73
+ }
74
+ });
75
+
76
+ addPlacementTopology({
77
+ id: "shell.status",
78
+ description: "Surface status, connection, and utility indicators.",
79
+ surfaces: ["*"],
80
+ variants: {
81
+ compact: {
82
+ outlet: "shell-layout:top-right"
83
+ },
84
+ medium: {
85
+ outlet: "shell-layout:top-right"
86
+ },
87
+ expanded: {
88
+ outlet: "shell-layout:top-right"
89
+ }
90
+ }
91
+ });
92
+
93
+ addPlacementTopology({
94
+ id: "shell.global-actions",
95
+ description: "Global surface actions that should stay outside primary navigation.",
96
+ surfaces: ["*"],
97
+ variants: {
98
+ compact: {
99
+ outlet: "shell-layout:top-right",
100
+ renderers: menuLinkRenderers
101
+ },
102
+ medium: {
103
+ outlet: "shell-layout:top-right",
104
+ renderers: menuLinkRenderers
105
+ },
106
+ expanded: {
107
+ outlet: "shell-layout:top-right",
108
+ renderers: menuLinkRenderers
109
+ }
110
+ }
111
+ });
112
+
113
+ addPlacementTopology({
114
+ id: "page.supporting-content",
115
+ description: "Supporting page content that opens as a bottom sheet on compact layouts and a side panel on wider layouts.",
116
+ surfaces: ["*"],
117
+ variants: {
118
+ compact: {
119
+ outlet: "shell-layout:supporting-bottom-sheet"
120
+ },
121
+ medium: {
122
+ outlet: "shell-layout:supporting-side-panel"
123
+ },
124
+ expanded: {
125
+ outlet: "shell-layout:supporting-side-panel"
126
+ }
127
+ }
128
+ });
129
+
130
+ addPlacementTopology({
131
+ id: "page.section-nav",
132
+ owner: "home-settings",
133
+ description: "Navigation between child pages in the home settings section.",
134
+ surfaces: ["home"],
135
+ variants: {
136
+ compact: {
137
+ outlet: "home-settings:primary-menu",
138
+ renderers: menuLinkRenderers
139
+ },
140
+ medium: {
141
+ outlet: "home-settings:primary-menu",
142
+ renderers: menuLinkRenderers
143
+ },
144
+ expanded: {
145
+ outlet: "home-settings:primary-menu",
146
+ renderers: menuLinkRenderers
147
+ }
148
+ }
149
+ });
@@ -0,0 +1,13 @@
1
+ <script setup>
2
+ const title = "Not Found";
3
+ const message = "The page you requested does not exist.";
4
+ </script>
5
+
6
+ <template>
7
+ <v-container class="fill-height d-flex align-center justify-center">
8
+ <v-card class="pa-6 text-center" max-width="560" rounded="lg">
9
+ <v-card-title class="text-h4">{{ title }}</v-card-title>
10
+ <v-card-text class="text-medium-emphasis">{{ message }}</v-card-text>
11
+ </v-card>
12
+ </v-container>
13
+ </template>
@@ -0,0 +1,7 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ describe("reading-room client smoke", () => {
4
+ it("runs vitest in reading-room", () => {
5
+ expect(true).toBe(true);
6
+ });
7
+ });
@@ -0,0 +1,10 @@
1
+ import { expect, test } from "@playwright/test";
2
+ import { DEFAULT_VIEWPORTS, runAdaptiveShellSmokeCase } from "@jskit-ai/shell-web/test/adaptiveShellSmoke";
3
+
4
+ test.describe("adaptive shell smoke", () => {
5
+ for (const viewport of DEFAULT_VIEWPORTS) {
6
+ test(`${viewport.name} layout has reachable navigation and no horizontal overflow`, async ({ page }) => {
7
+ await runAdaptiveShellSmokeCase({ page, expect, viewport });
8
+ });
9
+ }
10
+ });
@@ -0,0 +1,23 @@
1
+ import { expect, test } from "@playwright/test";
2
+
3
+ const VIEWPORTS = Object.freeze([
4
+ Object.freeze({ name: "compact", width: 390, height: 844 }),
5
+ Object.freeze({ name: "medium", width: 768, height: 1024 }),
6
+ Object.freeze({ name: "expanded", width: 1280, height: 900 })
7
+ ]);
8
+
9
+ test.describe("application responsive smoke", () => {
10
+ for (const viewport of VIEWPORTS) {
11
+ test(`${viewport.name} home route renders without horizontal overflow`, async ({ page }) => {
12
+ await page.setViewportSize(viewport);
13
+ await page.goto("/home");
14
+ await expect(page.getByRole("heading", { name: "Ready" })).toBeVisible();
15
+
16
+ const dimensions = await page.evaluate(() => ({
17
+ clientWidth: document.documentElement.clientWidth,
18
+ scrollWidth: document.documentElement.scrollWidth
19
+ }));
20
+ expect(dimensions.scrollWidth).toBeLessThanOrEqual(dimensions.clientWidth + 1);
21
+ });
22
+ }
23
+ });
@@ -0,0 +1,16 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { createServer } from "../../server.js";
4
+
5
+ test("GET /api/health returns built-in health response", async () => {
6
+ const app = await createServer();
7
+ const response = await app.inject({
8
+ method: "GET",
9
+ url: "/api/health"
10
+ });
11
+
12
+ assert.equal(response.statusCode, 200);
13
+ assert.equal(response.json().ok, true);
14
+
15
+ await app.close();
16
+ });
@@ -0,0 +1,81 @@
1
+ import { fileURLToPath, URL } from "node:url";
2
+ import { defineConfig } from "vite";
3
+ import vue from "@vitejs/plugin-vue";
4
+ import vuetify from "vite-plugin-vuetify";
5
+ import VueRouter from "vue-router/vite";
6
+ import { createJskitClientBootstrapPlugin } from "@jskit-ai/kernel/client/vite";
7
+
8
+ const configuredDevPort = Number.parseInt(String(process.env.VITE_DEV_PORT || "").trim(), 10);
9
+ const devPort = Number.isInteger(configuredDevPort) && configuredDevPort > 0 ? configuredDevPort : 5173;
10
+ const apiProxyTarget = String(process.env.VITE_API_PROXY_TARGET || "").trim() || "http://localhost:3000";
11
+ const clientEntry = (() => {
12
+ const normalized = String(process.env.VITE_CLIENT_ENTRY || "").trim();
13
+ if (!normalized) {
14
+ return "/src/main.js";
15
+ }
16
+ if (normalized.startsWith("/")) {
17
+ return normalized;
18
+ }
19
+ if (normalized.startsWith("src/")) {
20
+ return `/${normalized}`;
21
+ }
22
+ return `/src/${normalized}`;
23
+ })();
24
+
25
+ export default defineConfig({
26
+ resolve: {
27
+ preserveSymlinks: true,
28
+ alias: {
29
+ "@": fileURLToPath(new URL("./src", import.meta.url))
30
+ }
31
+ },
32
+ plugins: [
33
+ createJskitClientBootstrapPlugin({
34
+ proxyTarget: apiProxyTarget
35
+ }),
36
+ VueRouter({
37
+ routesFolder: "src/pages",
38
+ // Generated on the first Vite dev/build scan and intentionally gitignored.
39
+ dts: "src/typed-router.d.ts",
40
+ nestedChildren: false
41
+ }),
42
+ vue(),
43
+ vuetify({
44
+ autoImport: true
45
+ }),
46
+ {
47
+ name: "jskit-client-entry",
48
+ transformIndexHtml(source) {
49
+ return String(source || "")
50
+ .replace(/\/src\/%VITE_CLIENT_ENTRY%/g, clientEntry)
51
+ .replace(/\/src\/main\.js/g, clientEntry);
52
+ }
53
+ }
54
+ ],
55
+ test: {
56
+ include: ["tests/client/**/*.vitest.js"]
57
+ },
58
+ optimizeDeps: {
59
+ entries: [
60
+ "index.html",
61
+ "src/**/*.{js,ts,vue}"
62
+ ]
63
+ },
64
+ server: {
65
+ port: devPort,
66
+ warmup: {
67
+ clientFiles: [
68
+ "src/main.{js,ts}",
69
+ "src/router/**/*.{js,ts}",
70
+ "src/pages/**/*.{js,ts,vue}",
71
+ "src/components/**/*.{js,ts,vue}"
72
+ ]
73
+ },
74
+ proxy: {
75
+ "/api": {
76
+ target: apiProxyTarget,
77
+ changeOrigin: true
78
+ }
79
+ }
80
+ }
81
+ });
@@ -0,0 +1,56 @@
1
+ # JSKIT UI contract
2
+
3
+ Use this contract when creating or reviewing JSKIT shell, page, CRUD, settings,
4
+ and action UI.
5
+
6
+ ## Product-quality defaults
7
+
8
+ - Live pages contain product language, not framework instructions or placeholder
9
+ copy.
10
+ - Layouts adapt at compact, medium, and expanded widths without horizontal
11
+ overflow.
12
+ - Compact interactive targets are at least 48 CSS pixels.
13
+ - Navigation uses semantic placements and explicit navigation roles.
14
+ - Pages do not stack decorative cards inside structural cards.
15
+ - Shared screens own repeated chrome; app pages own product fields and domain
16
+ sections.
17
+
18
+ ## Loading and feedback
19
+
20
+ - Initial and structural loading uses shape-matching skeletons.
21
+ - Never use circular progress, indeterminate spinners, or loading icons.
22
+ - Pending buttons keep their position and use stable disabled labels.
23
+ - Resource-load failures stay in the affected region with retry.
24
+ - Command and mutation failures use the shared toast/snackbar feedback path;
25
+ they do not insert banners that push page content down.
26
+ - Cached query/resource data and route state may already exist at component
27
+ creation. Prefer computed truth; when writable state is necessary, hydrate it
28
+ synchronously or with an immediate watcher.
29
+
30
+ ## Shared CRUD screens
31
+
32
+ Use `CrudListScreen`, `CrudViewScreen`, and `CrudAddEditScreen` with their
33
+ matching composables. Use the public filter, bulk-action, row-action, synthetic
34
+ row, and detail-slot seams before replacing shared chrome.
35
+
36
+ Filters derive query parameters through the shared screen runtime. Server-side
37
+ filters use `createCrudListFilterContract()` so route/action validation, JSON
38
+ REST search schema, and repository normalization remain one contract.
39
+
40
+ ## Shell and placements
41
+
42
+ Keep placement identities semantic and surface-aware. `primary`, `secondary`,
43
+ `utility`, `detail`, `workflow`, and `none` describe product navigation intent.
44
+ `page.supporting-content` is a semantic secondary region: compact layouts expose
45
+ it as a closed sheet and wider layouts as a closed side panel.
46
+
47
+ ## Verification
48
+
49
+ - test skeleton, empty, loaded, local error, retry, and mutation feedback states
50
+ - navigate away and back with warm query cache, including browser back/forward
51
+ - exercise compact, medium, and expanded viewports
52
+ - verify accessible names, keyboard operation, target size, and no overflow
53
+ - assert that no spinner or layout-shifting transient error banner appears
54
+
55
+ Framework source contracts and package tests enforce the reusable parts of this
56
+ policy. Application browser tests prove product-specific behavior.
@@ -10,11 +10,13 @@ Use when:
10
10
  Rules:
11
11
 
12
12
  - Any chunk that adds or changes user-facing UI must include a Playwright flow that exercises the changed behavior before the chunk is done.
13
- - Generator or package template UI changes must be checked at compact phone, tablet-ish medium, and expanded desktop widths.
14
- - For generated UI, check horizontal overflow, clipped or invisible text, duplicate navigation, and broken route placement at every standard viewport. On compact screens, also check generated-screen tap targets under 48 px; medium and expanded layouts may use their documented denser controls.
13
+ - Pattern and framework UI changes must be checked at compact phone, tablet-ish medium, and expanded desktop widths.
14
+ - Check horizontal overflow, clipped or invisible text, duplicate navigation, and broken route placement at every standard viewport. On compact screens, also check screen tap targets under 48 px; medium and expanded layouts may use their documented denser controls.
15
15
  - Apps with `shell-web` installed should start from `tests/e2e/adaptive-shell.spec.ts` and extend it with feature-specific assertions.
16
16
  - The package helper reads the shell's rendered `data-layout` contract, waits for drawer transitions without fixed sleeps, verifies compact Escape/outside dismissal, checks content-aware drawer fit, and measures rail icon centring against the configured width. Do not replace it with viewport-name assumptions or immediate animation-time geometry reads.
17
- - Generated `playwright.config.mjs` delegates to `@jskit-ai/jskit-cli/test/playwright`. Do not copy base-URL, web-server, or storage-state logic into app tests.
17
+ - Start from the application-foundation Playwright configuration and keep it
18
+ app-owned. Do not duplicate base-URL, web-server, or storage-state logic in
19
+ individual tests.
18
20
  - Use relative paths such as `page.goto("/home")`. The shared config owns the browser base URL.
19
21
  - A managed runner supplies `PLAYWRIGHT_BASE_URL`. When it is set, JSKIT does not start another app server.
20
22
  - Vibe64 supplies an authenticated context through `VIBE64_PLAYWRIGHT_STORAGE_STATE`. Treat that file as a temporary secret: do not commit it, print it, or retain it after the run.
@@ -22,15 +24,14 @@ Rules:
22
24
 
23
25
  ## Preserve baseline tests
24
26
 
25
- Generated baseline tests are app-owned and customizable. Adapt infrastructure
27
+ Foundation-pattern baseline tests are app-owned and customizable. Adapt infrastructure
26
28
  tests in place when routes or behavior change so the baseline coverage remains
27
29
  truthful.
28
30
 
29
31
  When the starter product route is replaced, update the scaffold smoke test to
30
32
  visit and assert the new canonical route. Do not delete baseline browser
31
33
  coverage such as `tests/e2e/base-shell.spec.ts` or
32
- `tests/e2e/adaptive-shell.spec.ts`. JSKIT Doctor must continue to flag a
33
- managed test that is missing.
34
+ `tests/e2e/adaptive-shell.spec.ts`.
34
35
 
35
36
  ## Direct local authentication
36
37
 
@@ -78,7 +79,7 @@ VIBE64_PLAYWRIGHT_STORAGE_STATE=/secure/temp/playwright-state.json \
78
79
  playwright test tests/e2e/contacts.spec.ts
79
80
  ```
80
81
 
81
- The generated config applies that state to Playwright contexts and omits its local `webServer`. Tests then navigate with relative paths and begin with the runner-provided identity already authenticated.
82
+ The app-owned config applies that state to Playwright contexts and omits its local `webServer`. Tests then navigate with relative paths and begin with the runner-provided identity already authenticated.
82
83
 
83
84
  Do not call `loginAsExistingUser()` against a managed preview. It is deliberately localhost-only. An ordinary request to `/api/dev-auth/login-as` without the private exchange header must return `403`.
84
85
 
@@ -90,11 +91,8 @@ Run the focused Playwright command directly:
90
91
  npx playwright test tests/e2e/contacts.spec.ts -g filters
91
92
  ```
92
93
 
93
- For local pre-merge review, follow the focused run with:
94
-
95
- ```bash
96
- npx jskit doctor --against origin/main
97
- ```
94
+ For local pre-merge review, follow the focused run with the application's
95
+ ordinary lint, package, build, and test scripts.
98
96
 
99
97
  Do not mark the chunk done if:
100
98