@jskit-ai/agent-docs 0.1.149 → 0.1.150

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 (227) hide show
  1. package/guide/agent/app-setup/existing-application-migration.md +8 -6
  2. package/guide/agent/app-setup/initial-scaffolding.md +9 -7
  3. package/guide/agent/app-setup/quickstart.md +9 -6
  4. package/guide/agent/framework/application-operations.md +91 -0
  5. package/guide/agent/framework/crud-operations.md +83 -0
  6. package/guide/agent/framework/material-3.md +112 -0
  7. package/guide/agent/framework/ui-operations.md +78 -0
  8. package/guide/agent/index.md +13 -3
  9. package/package.json +1 -1
  10. package/patterns/feature-package/example/booking-engine/package.json +1 -1
  11. package/patterns/minimal-foundation/example/AGENTS.md +8 -8
  12. package/patterns/minimal-foundation/example/package.json +4 -5
  13. package/patterns/shell-foundation/example/AGENTS.md +8 -8
  14. package/patterns/shell-foundation/example/package.json +5 -6
  15. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  16. package/reference/autogen/PATTERN_INDEX.md +61 -61
  17. package/skills/jskit/SKILL.md +8 -5
  18. package/skills/jskit/references/app-operations.md +12 -11
  19. package/skills/jskit/references/crud-operations.md +10 -6
  20. package/skills/jskit/references/existing-application-migration.md +9 -12
  21. package/skills/jskit/references/material-3.md +2 -0
  22. package/skills/jskit/references/pattern-index.md +61 -61
  23. package/skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md +105 -0
  24. package/skills/jskit/references/patterns/app/minimal-foundation/example/.nvmrc +1 -0
  25. package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +17 -0
  26. package/skills/jskit/references/patterns/app/minimal-foundation/example/Procfile +2 -0
  27. package/skills/jskit/references/patterns/app/minimal-foundation/example/app.json +14 -0
  28. package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/develop.js +71 -0
  29. package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/server.js +8 -0
  30. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/public.js +40 -0
  31. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/server.js +1 -0
  32. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/surfaceAccessPolicies.js +3 -0
  33. package/skills/jskit/references/patterns/app/minimal-foundation/example/eslint.config.mjs +19 -0
  34. package/skills/jskit/references/patterns/app/minimal-foundation/example/favicon.svg +7 -0
  35. package/skills/jskit/references/patterns/app/minimal-foundation/example/gitignore +9 -0
  36. package/skills/jskit/references/patterns/app/minimal-foundation/example/index.html +13 -0
  37. package/skills/jskit/references/patterns/app/minimal-foundation/example/jsconfig.json +8 -0
  38. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +62 -0
  39. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/package.json +42 -0
  40. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/src/shared/index.js +10 -0
  41. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  42. package/skills/jskit/references/patterns/app/minimal-foundation/example/playwright.config.mjs +31 -0
  43. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/runtimeEnv.js +45 -0
  44. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/surfaceRuntime.js +10 -0
  45. package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +195 -0
  46. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/App.vue +13 -0
  47. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/main.js +85 -0
  48. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/pages/home/index.vue +48 -0
  49. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/pages/home.vue +13 -0
  50. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/views/NotFound.vue +13 -0
  51. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/client/smoke.vitest.js +7 -0
  52. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  53. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/server/smoke.test.js +16 -0
  54. package/skills/jskit/references/patterns/app/minimal-foundation/example/vite.config.mjs +80 -0
  55. package/skills/jskit/references/patterns/app/shell-foundation/PATTERN.md +111 -0
  56. package/skills/jskit/references/patterns/app/shell-foundation/example/.nvmrc +1 -0
  57. package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +17 -0
  58. package/skills/jskit/references/patterns/app/shell-foundation/example/Procfile +2 -0
  59. package/skills/jskit/references/patterns/app/shell-foundation/example/app.json +14 -0
  60. package/skills/jskit/references/patterns/app/shell-foundation/example/bin/develop.js +71 -0
  61. package/skills/jskit/references/patterns/app/shell-foundation/example/bin/server.js +8 -0
  62. package/skills/jskit/references/patterns/app/shell-foundation/example/config/public.js +40 -0
  63. package/skills/jskit/references/patterns/app/shell-foundation/example/config/server.js +1 -0
  64. package/skills/jskit/references/patterns/app/shell-foundation/example/config/surfaceAccessPolicies.js +3 -0
  65. package/skills/jskit/references/patterns/app/shell-foundation/example/eslint.config.mjs +19 -0
  66. package/skills/jskit/references/patterns/app/shell-foundation/example/favicon.svg +7 -0
  67. package/skills/jskit/references/patterns/app/shell-foundation/example/gitignore +9 -0
  68. package/skills/jskit/references/patterns/app/shell-foundation/example/index.html +13 -0
  69. package/skills/jskit/references/patterns/app/shell-foundation/example/jsconfig.json +8 -0
  70. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +64 -0
  71. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +56 -0
  72. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/index.js +9 -0
  73. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +18 -0
  74. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/shared/index.js +10 -0
  75. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  76. package/skills/jskit/references/patterns/app/shell-foundation/example/playwright.config.mjs +31 -0
  77. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/runtimeEnv.js +45 -0
  78. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/surfaceRuntime.js +10 -0
  79. package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +195 -0
  80. package/skills/jskit/references/patterns/app/shell-foundation/example/src/App.vue +11 -0
  81. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/ShellLayout.vue +12 -0
  82. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/MenuLinkItem.vue +30 -0
  83. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  84. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/TabLinkItem.vue +42 -0
  85. package/skills/jskit/references/patterns/app/shell-foundation/example/src/error.js +19 -0
  86. package/skills/jskit/references/patterns/app/shell-foundation/example/src/main.js +85 -0
  87. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/index.vue +116 -0
  88. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings/general/index.vue +40 -0
  89. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings/index.vue +7 -0
  90. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings.vue +109 -0
  91. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home.vue +20 -0
  92. package/skills/jskit/references/patterns/app/shell-foundation/example/src/placement.js +56 -0
  93. package/skills/jskit/references/patterns/app/shell-foundation/example/src/placementTopology.js +149 -0
  94. package/skills/jskit/references/patterns/app/shell-foundation/example/src/views/NotFound.vue +13 -0
  95. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/client/smoke.vitest.js +7 -0
  96. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  97. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  98. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/server/smoke.test.js +16 -0
  99. package/skills/jskit/references/patterns/app/shell-foundation/example/vite.config.mjs +80 -0
  100. package/skills/jskit/references/patterns/assistant/assistant-surface/PATTERN.md +77 -0
  101. package/skills/jskit/references/patterns/assistant/assistant-surface/example/config/public.js +19 -0
  102. package/skills/jskit/references/patterns/assistant/assistant-surface/example/config/server.js +9 -0
  103. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/pages/admin/assistant/index.vue +7 -0
  104. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/pages/admin/settings/assistant/index.vue +7 -0
  105. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/placement.js +38 -0
  106. package/skills/jskit/references/patterns/auth/auth-surface/PATTERN.md +90 -0
  107. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/login.vue +17 -0
  108. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/reset-password.vue +17 -0
  109. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/signout.vue +17 -0
  110. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/authGuardRuntime.js +7 -0
  111. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/authHttpClient.js +1 -0
  112. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/useSignOut.js +1 -0
  113. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/LoginView.vue +7 -0
  114. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/ResetPasswordView.vue +7 -0
  115. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/SignOutView.vue +7 -0
  116. package/skills/jskit/references/patterns/auth/auth-surface/example/tools/preview-identity +5 -0
  117. package/skills/jskit/references/patterns/auth/supabase-auth/PATTERN.md +67 -0
  118. package/skills/jskit/references/patterns/auth/supabase-auth/example/.env.example +4 -0
  119. package/skills/jskit/references/patterns/auth/supabase-auth/example/config/server.js +11 -0
  120. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +7 -0
  121. package/skills/jskit/references/patterns/console/console-surface/PATTERN.md +58 -0
  122. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/index.vue +62 -0
  123. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/settings/index.vue +17 -0
  124. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/settings.vue +95 -0
  125. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console.vue +20 -0
  126. package/skills/jskit/references/patterns/crud/crud-screen-set/PATTERN.md +88 -0
  127. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookEditPage.vue +54 -0
  128. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookFormFields.vue +52 -0
  129. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookListPage.vue +54 -0
  130. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookNewPage.vue +45 -0
  131. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookViewPage.vue +50 -0
  132. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/formFields.js +31 -0
  133. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/listExtensions.js +9 -0
  134. package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +160 -0
  135. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/migrations/20260815000000_books.cjs +22 -0
  136. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +41 -0
  137. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/server/BooksFeature.js +13 -0
  138. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/shared/bookResource.js +83 -0
  139. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/shared/index.js +1 -0
  140. package/skills/jskit/references/patterns/crud/resource-contract/PATTERN.md +102 -0
  141. package/skills/jskit/references/patterns/crud/resource-contract/example/bookResource.js +87 -0
  142. package/skills/jskit/references/patterns/database/mysql-application/PATTERN.md +80 -0
  143. package/skills/jskit/references/patterns/database/mysql-application/example/.env.example +5 -0
  144. package/skills/jskit/references/patterns/database/mysql-application/example/.github/workflows/verify.yml +39 -0
  145. package/skills/jskit/references/patterns/database/mysql-application/example/knexfile.js +11 -0
  146. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +13 -0
  147. package/skills/jskit/references/patterns/database/mysql-application/example/scripts/prepare-database.js +3 -0
  148. package/skills/jskit/references/patterns/database/postgres-application/PATTERN.md +80 -0
  149. package/skills/jskit/references/patterns/database/postgres-application/example/.env.example +5 -0
  150. package/skills/jskit/references/patterns/database/postgres-application/example/.github/workflows/verify.yml +38 -0
  151. package/skills/jskit/references/patterns/database/postgres-application/example/knexfile.js +11 -0
  152. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +13 -0
  153. package/skills/jskit/references/patterns/database/postgres-application/example/scripts/prepare-database.js +3 -0
  154. package/skills/jskit/references/patterns/mobile/android-application/PATTERN.md +71 -0
  155. package/skills/jskit/references/patterns/mobile/android-application/example/capacitor.config.json +10 -0
  156. package/skills/jskit/references/patterns/realtime/realtime-application/PATTERN.md +69 -0
  157. package/skills/jskit/references/patterns/realtime/realtime-application/example/.env.example +1 -0
  158. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +8 -0
  159. package/skills/jskit/references/patterns/realtime/realtime-application/example/src/placement.js +17 -0
  160. package/skills/jskit/references/patterns/server/feature-package/PATTERN.md +108 -0
  161. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +48 -0
  162. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +33 -0
  163. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/actions.js +26 -0
  164. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/inputSchemas.js +19 -0
  165. package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineProvider.js +31 -0
  166. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupProvider.js +36 -0
  167. package/skills/jskit/references/patterns/server/feature-package/example/variations/customKnexRepository.js +34 -0
  168. package/skills/jskit/references/patterns/server/feature-package/example/variations/orchestratorService.js +23 -0
  169. package/skills/jskit/references/patterns/shell/application-shell/PATTERN.md +66 -0
  170. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/App.vue +13 -0
  171. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/pages/home/index.vue +48 -0
  172. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/pages/home.vue +13 -0
  173. package/skills/jskit/references/patterns/shell/application-shell/example/src/App.vue +11 -0
  174. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/ShellLayout.vue +13 -0
  175. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/MenuLinkItem.vue +30 -0
  176. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  177. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/TabLinkItem.vue +42 -0
  178. package/skills/jskit/references/patterns/shell/application-shell/example/src/error.js +19 -0
  179. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/index.vue +106 -0
  180. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings/general/index.vue +40 -0
  181. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings/index.vue +7 -0
  182. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings.vue +109 -0
  183. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home.vue +20 -0
  184. package/skills/jskit/references/patterns/shell/application-shell/example/src/placement.js +56 -0
  185. package/skills/jskit/references/patterns/shell/application-shell/example/src/placementTopology.js +149 -0
  186. package/skills/jskit/references/patterns/shell/application-shell/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  187. package/skills/jskit/references/patterns/ui/page-and-placement/PATTERN.md +76 -0
  188. package/skills/jskit/references/patterns/ui/page-and-placement/example/packages/main/src/client/providers/MainClientProvider.js +14 -0
  189. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/components/SyncStatusElement.vue +16 -0
  190. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/activity.vue +8 -0
  191. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/index.vue +7 -0
  192. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/overview.vue +8 -0
  193. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports.vue +33 -0
  194. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/placement.js +52 -0
  195. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/placementTopology.js +29 -0
  196. package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +61 -0
  197. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsNotificationsSection.vue +81 -0
  198. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsPreferencesSection.vue +151 -0
  199. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsProfileSection.vue +120 -0
  200. package/skills/jskit/references/patterns/users/account-settings/example/src/pages/account/index.vue +17 -0
  201. package/skills/jskit/references/patterns/users/user-administration-server/PATTERN.md +64 -0
  202. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +42 -0
  203. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/server/UsersFeature.js +13 -0
  204. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/index.js +1 -0
  205. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/userResource.js +69 -0
  206. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +43 -0
  207. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/UsersWorkspaceFeature.js +22 -0
  208. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/index.js +1 -0
  209. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/userResource.js +56 -0
  210. package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +60 -0
  211. package/skills/jskit/references/patterns/workspaces/workspace-server/example/config/roles.js +27 -0
  212. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteEmail.js +23 -0
  213. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/PATTERN.md +63 -0
  214. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/packages/main/src/client/components/AccountPendingInvitesCue.vue +106 -0
  215. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/packages/main/src/client/components/AccountSettingsInvitesSection.vue +7 -0
  216. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/components/WorkspaceNotFoundCard.vue +53 -0
  217. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/composables/useWorkspaceNotFoundState.js +41 -0
  218. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/members/index.vue +7 -0
  219. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/workspace/settings/index.vue +23 -0
  220. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/workspace/settings.vue +95 -0
  221. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/invite/[token].vue +7 -0
  222. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/admin/index.vue +85 -0
  223. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/admin/root.vue +20 -0
  224. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/app/index.vue +46 -0
  225. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/app/root.vue +20 -0
  226. package/skills/jskit/references/ui-operations.md +5 -3
  227. package/templates/app/AGENTS.md +8 -8
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "reading-room",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "Minimal JSKIT base app (Fastify + Vue)",
7
+ "engines": {
8
+ "node": "26.x"
9
+ },
10
+ "workspaces": [
11
+ "packages/*"
12
+ ],
13
+ "scripts": {
14
+ "server": "node ./bin/server.js",
15
+ "server:all": "node ./bin/server.js",
16
+ "server:home": "SERVER_SURFACE=home node ./bin/server.js",
17
+ "start": "node ./bin/server.js",
18
+ "develop": "node ./bin/develop.js",
19
+ "dev": "vite",
20
+ "dev:all": "vite",
21
+ "dev:home": "VITE_SURFACE=home vite",
22
+ "build": "vite build",
23
+ "build:all": "vite build",
24
+ "build:home": "VITE_SURFACE=home vite build",
25
+ "preview": "vite preview",
26
+ "lint": "eslint .",
27
+ "test": "node --test",
28
+ "test:client": "vitest run tests/client",
29
+ "test:e2e": "playwright test tests/e2e",
30
+ "jskit:update": "npx --yes @jskit-ai/jskit-catalog@latest update",
31
+ "jskit:check": "jskit check",
32
+ "verify": "npm run jskit:check && npm run lint && npm run test && npm run test:client && npm run build"
33
+ },
34
+ "dependencies": {
35
+ "@local/main": "0.1.0",
36
+ "@fastify/static": "^10.1.3",
37
+ "@jskit-ai/kernel": "0.1.178",
38
+ "@tanstack/vue-query": "^5.101.0",
39
+ "fastify": "^5.8.5",
40
+ "json-rest-schema": "^1.0.17",
41
+ "pinia": "^3.0.4",
42
+ "vue": "^3.5.38",
43
+ "vue-router": "^5.1.0",
44
+ "vuetify": "^4.1.2",
45
+ "@jskit-ai/http-runtime": "0.1.176"
46
+ },
47
+ "devDependencies": {
48
+ "@jskit-ai/config-eslint": "0.1.175",
49
+ "@jskit-ai/jskit-catalog": "0.1.203",
50
+ "@playwright/test": "1.61.1",
51
+ "@vitejs/plugin-vue": "^6.0.7",
52
+ "eslint": "^10.8.0",
53
+ "vite": "^8.2.1",
54
+ "vite-plugin-vuetify": "^2.1.3",
55
+ "vitest": "^4.1.9"
56
+ },
57
+ "allowScripts": {
58
+ "fsevents@2.3.2": true,
59
+ "fsevents@2.3.3": true,
60
+ "vue-demi@0.14.10": true
61
+ }
62
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@local/main",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "exports": {
7
+ "./shared": "./src/shared/index.js"
8
+ },
9
+ "description": "App-local runtime composition and lightweight glue.",
10
+ "jskit": {
11
+ "kind": "runtime",
12
+ "capabilities": {
13
+ "provides": [],
14
+ "requires": []
15
+ },
16
+ "metadata": {
17
+ "jskit": {
18
+ "ownershipGuidance": {
19
+ "title": "App-local main lane",
20
+ "summary": "Keep @local/main focused on app composition and lightweight glue. Substantial server features should become dedicated packages instead of growing inside packages/main.",
21
+ "responsibilities": [
22
+ "packages/main server code: bootstraps app-local configuration and lightweight wiring only",
23
+ "substantial server features: author a dedicated app-local package from the relevant framework pattern",
24
+ "packages/main: do not add service/controller/route/repository feature trees here"
25
+ ],
26
+ "examples": [
27
+ "packages/booking-engine owns booking operations",
28
+ "packages/availability-engine owns availability orchestration"
29
+ ]
30
+ }
31
+ },
32
+ "server": {
33
+ "routes": []
34
+ },
35
+ "ui": {
36
+ "routes": [],
37
+ "elements": [],
38
+ "overrides": []
39
+ }
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shared entrypoint for code used by both client and server.
3
+ *
4
+ * Keep this for genuinely app-local shared glue only.
5
+ *
6
+ * Example:
7
+ * export * from "./schemas/index.js";
8
+ * export * from "./constants/index.js";
9
+ */
10
+ export {};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * App-local shared transport validators/resources live here.
3
+ * Dedicated feature packages should keep their own schemas with the feature.
4
+ *
5
+ * Example:
6
+ * import { createSchema } from "json-rest-schema";
7
+ *
8
+ * export const helloQuerySchema = createSchema({
9
+ * name: { type: "string", minLength: 1, maxLength: 80 }
10
+ * });
11
+ *
12
+ * export const helloResponseSchema = {
13
+ * type: "object",
14
+ * additionalProperties: false,
15
+ * required: ["ok", "message"],
16
+ * properties: {
17
+ * ok: { type: "boolean" },
18
+ * message: { type: "string", minLength: 1 }
19
+ * }
20
+ * };
21
+ */
22
+ export {};
@@ -0,0 +1,31 @@
1
+ import { defineConfig } from "@playwright/test";
2
+
3
+ const managedBaseUrl = String(process.env.PLAYWRIGHT_BASE_URL || "")
4
+ .trim()
5
+ .replace(/\/+$/u, "");
6
+ const baseURL = managedBaseUrl || "http://127.0.0.1:4173";
7
+ const storageState = String(process.env.VIBE64_PLAYWRIGHT_STORAGE_STATE || "").trim();
8
+
9
+ export default defineConfig({
10
+ testDir: "./tests/e2e",
11
+ timeout: 60_000,
12
+ expect: {
13
+ timeout: 10_000
14
+ },
15
+ use: {
16
+ baseURL,
17
+ headless: true,
18
+ ...(storageState ? { storageState } : {})
19
+ },
20
+ ...(managedBaseUrl ? {} : {
21
+ webServer: {
22
+ command: "npm run build && node ./bin/server.js",
23
+ env: {
24
+ PORT: "4173"
25
+ },
26
+ url: `${baseURL}/api/health`,
27
+ reuseExistingServer: true,
28
+ timeout: 180_000
29
+ }
30
+ })
31
+ });
@@ -0,0 +1,45 @@
1
+ import { createRequire } from "node:module";
2
+ import { surfaceRuntime } from "./surfaceRuntime.js";
3
+
4
+ const require = createRequire(import.meta.url);
5
+
6
+ function toPort(value, fallback = 3000) {
7
+ const parsed = Number.parseInt(String(value || "").trim(), 10);
8
+ if (Number.isInteger(parsed) && parsed > 0) {
9
+ return parsed;
10
+ }
11
+ return fallback;
12
+ }
13
+
14
+ let envLoaded = false;
15
+
16
+ function ensureRuntimeEnvLoaded() {
17
+ if (envLoaded) {
18
+ return;
19
+ }
20
+ try {
21
+ const dotenvModule = require("dotenv");
22
+ const loadDotEnv = dotenvModule?.config;
23
+ if (typeof loadDotEnv === "function") {
24
+ loadDotEnv();
25
+ }
26
+ } catch {
27
+ // dotenv is optional in base-shell; bundles can add it when needed.
28
+ }
29
+ envLoaded = true;
30
+ }
31
+
32
+ function resolveRuntimeEnv() {
33
+ ensureRuntimeEnvLoaded();
34
+ const serverSurface = surfaceRuntime.normalizeSurfaceMode(
35
+ process.env.JSKIT_SERVER_SURFACE || process.env.SERVER_SURFACE
36
+ );
37
+ return {
38
+ ...process.env,
39
+ SERVER_SURFACE: serverSurface,
40
+ PORT: toPort(process.env.PORT, 3000),
41
+ HOST: String(process.env.HOST || "").trim() || "0.0.0.0"
42
+ };
43
+ }
44
+
45
+ export { resolveRuntimeEnv };
@@ -0,0 +1,10 @@
1
+ import { createSurfaceRuntime } from "@jskit-ai/kernel/shared/surface/runtime";
2
+ import { config } from "../../config/public.js";
3
+
4
+ const surfaceRuntime = createSurfaceRuntime({
5
+ allMode: config.surfaceModeAll,
6
+ surfaces: config.surfaceDefinitions,
7
+ defaultSurfaceId: config.surfaceDefaultId
8
+ });
9
+
10
+ export { surfaceRuntime };
@@ -0,0 +1,195 @@
1
+ import Fastify from "fastify";
2
+ import fastifyStatic from "@fastify/static";
3
+ import { resolveRuntimeEnv } from "./server/lib/runtimeEnv.js";
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import path from "node:path";
6
+ import {
7
+ createInstalledRuntime,
8
+ registerSurfaceRequestConstraint,
9
+ resolveRuntimeProfileFromSurface
10
+ } from "@jskit-ai/kernel/server/platform";
11
+ import { loadAppConfigFromAppRoot } from "@jskit-ai/kernel/server/support";
12
+ import { matchesPathPrefix, normalizePathname } from "@jskit-ai/kernel/shared/surface/paths";
13
+ import { surfaceRuntime } from "./server/lib/surfaceRuntime.js";
14
+
15
+ const SPA_INDEX_FILE = "index.html";
16
+ const API_BASE_PATH = "/api";
17
+ const STATIC_GLOBAL_UI_PATHS = Object.freeze([
18
+ "/assets",
19
+ "/favicon.svg",
20
+ "/favicon.ico",
21
+ "/robots.txt",
22
+ "/manifest.webmanifest"
23
+ ]);
24
+
25
+ function toRequestPathname(urlValue) {
26
+ const rawUrl = String(urlValue || "").trim() || "/";
27
+ try {
28
+ return normalizePathname(new URL(rawUrl, "http://localhost").pathname || "/");
29
+ } catch {
30
+ return normalizePathname(rawUrl.split("?")[0] || "/");
31
+ }
32
+ }
33
+
34
+ function isApiPath(pathname) {
35
+ return matchesPathPrefix(pathname, API_BASE_PATH);
36
+ }
37
+
38
+ function hasFileExtension(pathname) {
39
+ return path.extname(normalizePathname(pathname)) !== "";
40
+ }
41
+
42
+ function resolveGlobalUiPaths(runtimeGlobalUiPaths = []) {
43
+ const paths = new Set(Array.isArray(runtimeGlobalUiPaths) ? runtimeGlobalUiPaths : []);
44
+ for (const staticPath of STATIC_GLOBAL_UI_PATHS) {
45
+ paths.add(staticPath);
46
+ }
47
+ return [...paths];
48
+ }
49
+
50
+ function resolveStaticFilePath(pathname) {
51
+ const normalizedPathname = normalizePathname(pathname);
52
+
53
+ const relativePath = normalizedPathname.replace(/^\/+/, "");
54
+ if (!relativePath || relativePath.endsWith("/")) {
55
+ return "";
56
+ }
57
+
58
+ const normalizedRelativePath = path.posix.normalize(relativePath);
59
+ if (
60
+ !normalizedRelativePath ||
61
+ normalizedRelativePath === "." ||
62
+ normalizedRelativePath === ".." ||
63
+ normalizedRelativePath.startsWith("../") ||
64
+ normalizedRelativePath.includes("/../")
65
+ ) {
66
+ return "";
67
+ }
68
+
69
+ return normalizedRelativePath;
70
+ }
71
+
72
+ function canServeStaticFile(distRoot, relativePath) {
73
+ if (!distRoot || !relativePath) {
74
+ return false;
75
+ }
76
+
77
+ const normalizedDistRoot = path.resolve(distRoot);
78
+ const resolvedPath = path.resolve(normalizedDistRoot, relativePath);
79
+ if (!(resolvedPath === normalizedDistRoot || resolvedPath.startsWith(`${normalizedDistRoot}${path.sep}`))) {
80
+ return false;
81
+ }
82
+
83
+ return existsSync(resolvedPath);
84
+ }
85
+
86
+ async function createServer({ runtimeEnv = resolveRuntimeEnv() } = {}) {
87
+ const app = Fastify({
88
+ logger: true,
89
+ ajv: {
90
+ customOptions: {
91
+ allowUnionTypes: true
92
+ }
93
+ }
94
+ });
95
+
96
+ app.get("/api/health", async () => {
97
+ return {
98
+ ok: true,
99
+ app: "reading-room"
100
+ };
101
+ });
102
+ const appRoot = path.resolve(process.cwd());
103
+ const distRoot = path.resolve(appRoot, "dist");
104
+ const hasWebBuild = existsSync(path.resolve(distRoot, SPA_INDEX_FILE));
105
+ const spaDocument = hasWebBuild ? readFileSync(path.resolve(distRoot, SPA_INDEX_FILE), "utf8") : "";
106
+ const runtime = await createInstalledRuntime({
107
+ appRoot,
108
+ profile: resolveRuntimeProfileFromSurface({
109
+ surfaceRuntime,
110
+ serverSurface: runtimeEnv.SERVER_SURFACE
111
+ }),
112
+ config: await loadAppConfigFromAppRoot({ appRoot }),
113
+ env: runtimeEnv,
114
+ logger: app.log,
115
+ fastify: app
116
+ });
117
+
118
+ registerSurfaceRequestConstraint({
119
+ fastify: app,
120
+ surfaceRuntime,
121
+ serverSurface: runtimeEnv.SERVER_SURFACE,
122
+ globalUiPaths: resolveGlobalUiPaths(runtime?.globalUiPaths || [])
123
+ });
124
+
125
+ if (hasWebBuild) {
126
+ await app.register(fastifyStatic, {
127
+ root: distRoot,
128
+ index: false,
129
+ serve: false
130
+ });
131
+ } else {
132
+ app.log.warn("Frontend build not found (dist/index.html). Page routes will return 404 until `npm run build`.");
133
+ }
134
+
135
+ app.setNotFoundHandler(async (request, reply) => {
136
+ const pathname = toRequestPathname(request?.url);
137
+ const method = String(request?.method || "GET")
138
+ .trim()
139
+ .toUpperCase();
140
+ if (isApiPath(pathname) || (method !== "GET" && method !== "HEAD")) {
141
+ return reply.code(404).send({
142
+ message: `Route ${method}:${pathname} not found`,
143
+ error: "Not Found",
144
+ statusCode: 404
145
+ });
146
+ }
147
+ if (hasFileExtension(pathname)) {
148
+ const staticFilePath = resolveStaticFilePath(pathname);
149
+ if (hasWebBuild && staticFilePath && canServeStaticFile(distRoot, staticFilePath)) {
150
+ return reply.sendFile(staticFilePath);
151
+ }
152
+ return reply.code(404).send({
153
+ message: `Route ${method}:${pathname} not found`,
154
+ error: "Not Found",
155
+ statusCode: 404
156
+ });
157
+ }
158
+ if (!hasWebBuild) {
159
+ return reply.code(404).send({
160
+ error: "Frontend build is not available. Run `npm run build`."
161
+ });
162
+ }
163
+ return reply.type("text/html; charset=utf-8").send(spaDocument);
164
+ });
165
+
166
+ app.log.info(
167
+ {
168
+ surface: surfaceRuntime.normalizeSurfaceMode(runtimeEnv.SERVER_SURFACE),
169
+ providerPackages: runtime.providerPackageOrder,
170
+ packageOrder: runtime.packageOrder,
171
+ capabilities: runtime.diagnostics.capabilityIds
172
+ },
173
+ "Started JSKIT installed runtime."
174
+ );
175
+
176
+ return app;
177
+ }
178
+
179
+ async function startServer(options = {}) {
180
+ const runtimeEnv = resolveRuntimeEnv();
181
+ const configuredPort = options?.port === undefined ? runtimeEnv.PORT : Number(options.port);
182
+ const port = Number.isInteger(configuredPort) && configuredPort >= 0 ? configuredPort : runtimeEnv.PORT;
183
+ const host = String(options?.host || "").trim() || runtimeEnv.HOST;
184
+ const app = await createServer({
185
+ runtimeEnv: {
186
+ ...runtimeEnv,
187
+ HOST: host,
188
+ PORT: port
189
+ }
190
+ });
191
+ await app.listen({ port, host });
192
+ return app;
193
+ }
194
+
195
+ export { createServer, startServer };
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <v-app>
3
+ <v-main>
4
+ <v-container class="py-10 py-md-14">
5
+ <v-row justify="center">
6
+ <v-col cols="12" sm="11" md="10" lg="8" xl="7">
7
+ <RouterView />
8
+ </v-col>
9
+ </v-row>
10
+ </v-container>
11
+ </v-main>
12
+ </v-app>
13
+ </template>
@@ -0,0 +1,85 @@
1
+ import { createApp } from "vue";
2
+ import { createPinia } from "pinia";
3
+ import { QueryClient, VueQueryPlugin } from "@tanstack/vue-query";
4
+ import { createRouter, createWebHistory } from "vue-router/auto";
5
+ import { routes } from "vue-router/auto-routes";
6
+ import "vuetify/styles";
7
+ import { createVuetify } from "vuetify";
8
+ import { aliases as mdiAliases, mdi } from "vuetify/iconsets/mdi-svg";
9
+ import App from "./App.vue";
10
+ import NotFoundView from "./views/NotFound.vue";
11
+ import { bootInstalledClientModules } from "virtual:jskit-client-bootstrap";
12
+ import { createSurfaceRuntime } from "@jskit-ai/kernel/shared/surface/runtime";
13
+ import {
14
+ shouldRetryTransientQueryFailure,
15
+ transientQueryRetryDelay
16
+ } from "@jskit-ai/kernel/shared/support";
17
+ import {
18
+ bootstrapClientShellApp,
19
+ createShellRouter
20
+ } from "@jskit-ai/kernel/client";
21
+ import { config } from "../config/public.js";
22
+
23
+ const surfaceRuntime = createSurfaceRuntime({
24
+ allMode: config.surfaceModeAll,
25
+ surfaces: config.surfaceDefinitions,
26
+ defaultSurfaceId: config.surfaceDefaultId
27
+ });
28
+
29
+ const surfaceMode = surfaceRuntime.normalizeSurfaceMode(import.meta.env.VITE_SURFACE);
30
+ const { router, fallbackRoute } = createShellRouter({
31
+ createRouter,
32
+ history: createWebHistory(),
33
+ routes,
34
+ surfaceRuntime,
35
+ surfaceMode,
36
+ notFoundComponent: NotFoundView,
37
+ guard: {
38
+ surfaceDefinitions: config.surfaceDefinitions,
39
+ defaultSurfaceId: config.surfaceDefaultId,
40
+ webRootAllowed: config.webRootAllowed
41
+ }
42
+ });
43
+
44
+ const vuetify = createVuetify({
45
+ theme: {
46
+ defaultTheme: "light"
47
+ },
48
+ icons: {
49
+ defaultSet: "mdi",
50
+ aliases: mdiAliases,
51
+ sets: { mdi }
52
+ }
53
+ });
54
+ const pinia = createPinia();
55
+ const queryClient = new QueryClient({
56
+ defaultOptions: {
57
+ queries: {
58
+ refetchOnWindowFocus: false,
59
+ refetchOnReconnect: true,
60
+ retry: shouldRetryTransientQueryFailure,
61
+ retryDelay: transientQueryRetryDelay
62
+ }
63
+ }
64
+ });
65
+
66
+ void bootstrapClientShellApp({
67
+ createApp,
68
+ rootComponent: App,
69
+ appConfig: config,
70
+ appPlugins: [
71
+ pinia,
72
+ [VueQueryPlugin, { queryClient }],
73
+ vuetify
74
+ ],
75
+ pinia,
76
+ queryClient,
77
+ router,
78
+ bootClientModules: bootInstalledClientModules,
79
+ surfaceRuntime,
80
+ surfaceMode,
81
+ env: import.meta.env,
82
+ fallbackRoute
83
+ }).catch((error) => {
84
+ console.error("Failed to bootstrap client app.", error);
85
+ });
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <section class="home-start-screen d-flex flex-column ga-4">
3
+ <header>
4
+ <p class="text-overline text-medium-emphasis mb-1">Home</p>
5
+ <h1 class="home-start-screen__title">Home base</h1>
6
+ <p class="text-body-2 text-medium-emphasis mb-0">
7
+ The app runtime is online and ready for the first real workflow.
8
+ </p>
9
+ </header>
10
+
11
+ <v-sheet rounded="lg" border class="home-start-screen__panel">
12
+ <h2 class="text-h6 mb-2">No activity yet</h2>
13
+ <p class="text-body-2 text-medium-emphasis mb-0">
14
+ Recent work, saved records, and next actions will appear here once this app has data.
15
+ </p>
16
+ </v-sheet>
17
+ </section>
18
+ </template>
19
+
20
+ <style scoped>
21
+ .home-start-screen {
22
+ --home-start-title-size: 2rem;
23
+ --home-start-panel-padding: 1rem;
24
+ }
25
+
26
+ .home-start-screen {
27
+ margin-inline: auto;
28
+ max-width: 48rem;
29
+ }
30
+
31
+ .home-start-screen__title {
32
+ font-size: var(--home-start-title-size);
33
+ font-weight: 700;
34
+ letter-spacing: 0;
35
+ line-height: 1.08;
36
+ margin: 0 0 0.45rem;
37
+ }
38
+
39
+ .home-start-screen__panel {
40
+ padding: var(--home-start-panel-padding);
41
+ }
42
+
43
+ @media (max-width: 640px) {
44
+ .home-start-screen {
45
+ --home-start-title-size: 1.5rem;
46
+ }
47
+ }
48
+ </style>
@@ -0,0 +1,13 @@
1
+ <route lang="json">
2
+ {
3
+ "meta": {
4
+ "jskit": {
5
+ "surface": "home"
6
+ }
7
+ }
8
+ }
9
+ </route>
10
+
11
+ <template>
12
+ <RouterView />
13
+ </template>
@@ -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,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: "Home base" })).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
+ });