@jskit-ai/agent-docs 0.1.148 → 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 (232) hide show
  1. package/guide/agent/app-setup/existing-application-migration.md +8 -6
  2. package/guide/agent/app-setup/initial-scaffolding.md +26 -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/PATTERN.md +5 -0
  12. package/patterns/minimal-foundation/example/AGENTS.md +8 -8
  13. package/patterns/minimal-foundation/example/package.json +4 -5
  14. package/patterns/minimal-foundation/example/vite.config.mjs +0 -1
  15. package/patterns/shell-foundation/PATTERN.md +5 -0
  16. package/patterns/shell-foundation/example/AGENTS.md +8 -8
  17. package/patterns/shell-foundation/example/package.json +5 -6
  18. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  19. package/patterns/shell-foundation/example/vite.config.mjs +0 -1
  20. package/reference/autogen/PATTERN_INDEX.md +61 -61
  21. package/reference/autogen/tooling/testUtils.md +1 -1
  22. package/skills/jskit/SKILL.md +8 -5
  23. package/skills/jskit/references/app-operations.md +12 -11
  24. package/skills/jskit/references/crud-operations.md +10 -6
  25. package/skills/jskit/references/existing-application-migration.md +9 -12
  26. package/skills/jskit/references/material-3.md +2 -0
  27. package/skills/jskit/references/pattern-index.md +61 -61
  28. package/skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md +105 -0
  29. package/skills/jskit/references/patterns/app/minimal-foundation/example/.nvmrc +1 -0
  30. package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +17 -0
  31. package/skills/jskit/references/patterns/app/minimal-foundation/example/Procfile +2 -0
  32. package/skills/jskit/references/patterns/app/minimal-foundation/example/app.json +14 -0
  33. package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/develop.js +71 -0
  34. package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/server.js +8 -0
  35. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/public.js +40 -0
  36. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/server.js +1 -0
  37. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/surfaceAccessPolicies.js +3 -0
  38. package/skills/jskit/references/patterns/app/minimal-foundation/example/eslint.config.mjs +19 -0
  39. package/skills/jskit/references/patterns/app/minimal-foundation/example/favicon.svg +7 -0
  40. package/skills/jskit/references/patterns/app/minimal-foundation/example/gitignore +9 -0
  41. package/skills/jskit/references/patterns/app/minimal-foundation/example/index.html +13 -0
  42. package/skills/jskit/references/patterns/app/minimal-foundation/example/jsconfig.json +8 -0
  43. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +62 -0
  44. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/package.json +42 -0
  45. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/src/shared/index.js +10 -0
  46. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  47. package/skills/jskit/references/patterns/app/minimal-foundation/example/playwright.config.mjs +31 -0
  48. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/runtimeEnv.js +45 -0
  49. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/surfaceRuntime.js +10 -0
  50. package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +195 -0
  51. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/App.vue +13 -0
  52. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/main.js +85 -0
  53. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/pages/home/index.vue +48 -0
  54. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/pages/home.vue +13 -0
  55. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/views/NotFound.vue +13 -0
  56. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/client/smoke.vitest.js +7 -0
  57. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  58. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/server/smoke.test.js +16 -0
  59. package/skills/jskit/references/patterns/app/minimal-foundation/example/vite.config.mjs +80 -0
  60. package/skills/jskit/references/patterns/app/shell-foundation/PATTERN.md +111 -0
  61. package/skills/jskit/references/patterns/app/shell-foundation/example/.nvmrc +1 -0
  62. package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +17 -0
  63. package/skills/jskit/references/patterns/app/shell-foundation/example/Procfile +2 -0
  64. package/skills/jskit/references/patterns/app/shell-foundation/example/app.json +14 -0
  65. package/skills/jskit/references/patterns/app/shell-foundation/example/bin/develop.js +71 -0
  66. package/skills/jskit/references/patterns/app/shell-foundation/example/bin/server.js +8 -0
  67. package/skills/jskit/references/patterns/app/shell-foundation/example/config/public.js +40 -0
  68. package/skills/jskit/references/patterns/app/shell-foundation/example/config/server.js +1 -0
  69. package/skills/jskit/references/patterns/app/shell-foundation/example/config/surfaceAccessPolicies.js +3 -0
  70. package/skills/jskit/references/patterns/app/shell-foundation/example/eslint.config.mjs +19 -0
  71. package/skills/jskit/references/patterns/app/shell-foundation/example/favicon.svg +7 -0
  72. package/skills/jskit/references/patterns/app/shell-foundation/example/gitignore +9 -0
  73. package/skills/jskit/references/patterns/app/shell-foundation/example/index.html +13 -0
  74. package/skills/jskit/references/patterns/app/shell-foundation/example/jsconfig.json +8 -0
  75. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +64 -0
  76. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +56 -0
  77. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/index.js +9 -0
  78. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +18 -0
  79. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/shared/index.js +10 -0
  80. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  81. package/skills/jskit/references/patterns/app/shell-foundation/example/playwright.config.mjs +31 -0
  82. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/runtimeEnv.js +45 -0
  83. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/surfaceRuntime.js +10 -0
  84. package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +195 -0
  85. package/skills/jskit/references/patterns/app/shell-foundation/example/src/App.vue +11 -0
  86. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/ShellLayout.vue +12 -0
  87. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/MenuLinkItem.vue +30 -0
  88. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  89. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/TabLinkItem.vue +42 -0
  90. package/skills/jskit/references/patterns/app/shell-foundation/example/src/error.js +19 -0
  91. package/skills/jskit/references/patterns/app/shell-foundation/example/src/main.js +85 -0
  92. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/index.vue +116 -0
  93. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings/general/index.vue +40 -0
  94. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings/index.vue +7 -0
  95. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings.vue +109 -0
  96. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home.vue +20 -0
  97. package/skills/jskit/references/patterns/app/shell-foundation/example/src/placement.js +56 -0
  98. package/skills/jskit/references/patterns/app/shell-foundation/example/src/placementTopology.js +149 -0
  99. package/skills/jskit/references/patterns/app/shell-foundation/example/src/views/NotFound.vue +13 -0
  100. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/client/smoke.vitest.js +7 -0
  101. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  102. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  103. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/server/smoke.test.js +16 -0
  104. package/skills/jskit/references/patterns/app/shell-foundation/example/vite.config.mjs +80 -0
  105. package/skills/jskit/references/patterns/assistant/assistant-surface/PATTERN.md +77 -0
  106. package/skills/jskit/references/patterns/assistant/assistant-surface/example/config/public.js +19 -0
  107. package/skills/jskit/references/patterns/assistant/assistant-surface/example/config/server.js +9 -0
  108. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/pages/admin/assistant/index.vue +7 -0
  109. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/pages/admin/settings/assistant/index.vue +7 -0
  110. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/placement.js +38 -0
  111. package/skills/jskit/references/patterns/auth/auth-surface/PATTERN.md +90 -0
  112. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/login.vue +17 -0
  113. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/reset-password.vue +17 -0
  114. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/signout.vue +17 -0
  115. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/authGuardRuntime.js +7 -0
  116. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/authHttpClient.js +1 -0
  117. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/useSignOut.js +1 -0
  118. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/LoginView.vue +7 -0
  119. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/ResetPasswordView.vue +7 -0
  120. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/SignOutView.vue +7 -0
  121. package/skills/jskit/references/patterns/auth/auth-surface/example/tools/preview-identity +5 -0
  122. package/skills/jskit/references/patterns/auth/supabase-auth/PATTERN.md +67 -0
  123. package/skills/jskit/references/patterns/auth/supabase-auth/example/.env.example +4 -0
  124. package/skills/jskit/references/patterns/auth/supabase-auth/example/config/server.js +11 -0
  125. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +7 -0
  126. package/skills/jskit/references/patterns/console/console-surface/PATTERN.md +58 -0
  127. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/index.vue +62 -0
  128. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/settings/index.vue +17 -0
  129. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/settings.vue +95 -0
  130. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console.vue +20 -0
  131. package/skills/jskit/references/patterns/crud/crud-screen-set/PATTERN.md +88 -0
  132. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookEditPage.vue +54 -0
  133. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookFormFields.vue +52 -0
  134. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookListPage.vue +54 -0
  135. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookNewPage.vue +45 -0
  136. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookViewPage.vue +50 -0
  137. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/formFields.js +31 -0
  138. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/listExtensions.js +9 -0
  139. package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +160 -0
  140. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/migrations/20260815000000_books.cjs +22 -0
  141. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +41 -0
  142. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/server/BooksFeature.js +13 -0
  143. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/shared/bookResource.js +83 -0
  144. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/shared/index.js +1 -0
  145. package/skills/jskit/references/patterns/crud/resource-contract/PATTERN.md +102 -0
  146. package/skills/jskit/references/patterns/crud/resource-contract/example/bookResource.js +87 -0
  147. package/skills/jskit/references/patterns/database/mysql-application/PATTERN.md +80 -0
  148. package/skills/jskit/references/patterns/database/mysql-application/example/.env.example +5 -0
  149. package/skills/jskit/references/patterns/database/mysql-application/example/.github/workflows/verify.yml +39 -0
  150. package/skills/jskit/references/patterns/database/mysql-application/example/knexfile.js +11 -0
  151. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +13 -0
  152. package/skills/jskit/references/patterns/database/mysql-application/example/scripts/prepare-database.js +3 -0
  153. package/skills/jskit/references/patterns/database/postgres-application/PATTERN.md +80 -0
  154. package/skills/jskit/references/patterns/database/postgres-application/example/.env.example +5 -0
  155. package/skills/jskit/references/patterns/database/postgres-application/example/.github/workflows/verify.yml +38 -0
  156. package/skills/jskit/references/patterns/database/postgres-application/example/knexfile.js +11 -0
  157. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +13 -0
  158. package/skills/jskit/references/patterns/database/postgres-application/example/scripts/prepare-database.js +3 -0
  159. package/skills/jskit/references/patterns/mobile/android-application/PATTERN.md +71 -0
  160. package/skills/jskit/references/patterns/mobile/android-application/example/capacitor.config.json +10 -0
  161. package/skills/jskit/references/patterns/realtime/realtime-application/PATTERN.md +69 -0
  162. package/skills/jskit/references/patterns/realtime/realtime-application/example/.env.example +1 -0
  163. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +8 -0
  164. package/skills/jskit/references/patterns/realtime/realtime-application/example/src/placement.js +17 -0
  165. package/skills/jskit/references/patterns/server/feature-package/PATTERN.md +108 -0
  166. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +48 -0
  167. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +33 -0
  168. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/actions.js +26 -0
  169. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/inputSchemas.js +19 -0
  170. package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineProvider.js +31 -0
  171. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupProvider.js +36 -0
  172. package/skills/jskit/references/patterns/server/feature-package/example/variations/customKnexRepository.js +34 -0
  173. package/skills/jskit/references/patterns/server/feature-package/example/variations/orchestratorService.js +23 -0
  174. package/skills/jskit/references/patterns/shell/application-shell/PATTERN.md +66 -0
  175. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/App.vue +13 -0
  176. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/pages/home/index.vue +48 -0
  177. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/pages/home.vue +13 -0
  178. package/skills/jskit/references/patterns/shell/application-shell/example/src/App.vue +11 -0
  179. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/ShellLayout.vue +13 -0
  180. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/MenuLinkItem.vue +30 -0
  181. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  182. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/TabLinkItem.vue +42 -0
  183. package/skills/jskit/references/patterns/shell/application-shell/example/src/error.js +19 -0
  184. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/index.vue +106 -0
  185. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings/general/index.vue +40 -0
  186. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings/index.vue +7 -0
  187. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings.vue +109 -0
  188. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home.vue +20 -0
  189. package/skills/jskit/references/patterns/shell/application-shell/example/src/placement.js +56 -0
  190. package/skills/jskit/references/patterns/shell/application-shell/example/src/placementTopology.js +149 -0
  191. package/skills/jskit/references/patterns/shell/application-shell/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  192. package/skills/jskit/references/patterns/ui/page-and-placement/PATTERN.md +76 -0
  193. package/skills/jskit/references/patterns/ui/page-and-placement/example/packages/main/src/client/providers/MainClientProvider.js +14 -0
  194. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/components/SyncStatusElement.vue +16 -0
  195. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/activity.vue +8 -0
  196. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/index.vue +7 -0
  197. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/overview.vue +8 -0
  198. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports.vue +33 -0
  199. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/placement.js +52 -0
  200. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/placementTopology.js +29 -0
  201. package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +61 -0
  202. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsNotificationsSection.vue +81 -0
  203. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsPreferencesSection.vue +151 -0
  204. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsProfileSection.vue +120 -0
  205. package/skills/jskit/references/patterns/users/account-settings/example/src/pages/account/index.vue +17 -0
  206. package/skills/jskit/references/patterns/users/user-administration-server/PATTERN.md +64 -0
  207. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +42 -0
  208. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/server/UsersFeature.js +13 -0
  209. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/index.js +1 -0
  210. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/userResource.js +69 -0
  211. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +43 -0
  212. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/UsersWorkspaceFeature.js +22 -0
  213. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/index.js +1 -0
  214. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/userResource.js +56 -0
  215. package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +60 -0
  216. package/skills/jskit/references/patterns/workspaces/workspace-server/example/config/roles.js +27 -0
  217. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteEmail.js +23 -0
  218. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/PATTERN.md +63 -0
  219. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/packages/main/src/client/components/AccountPendingInvitesCue.vue +106 -0
  220. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/packages/main/src/client/components/AccountSettingsInvitesSection.vue +7 -0
  221. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/components/WorkspaceNotFoundCard.vue +53 -0
  222. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/composables/useWorkspaceNotFoundState.js +41 -0
  223. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/members/index.vue +7 -0
  224. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/workspace/settings/index.vue +23 -0
  225. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/workspace/settings.vue +95 -0
  226. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/invite/[token].vue +7 -0
  227. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/admin/index.vue +85 -0
  228. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/admin/root.vue +20 -0
  229. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/app/index.vue +46 -0
  230. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/app/root.vue +20 -0
  231. package/skills/jskit/references/ui-operations.md +5 -3
  232. package/templates/app/AGENTS.md +8 -8
@@ -0,0 +1,69 @@
1
+ import { defineCrudResource } from "@jskit-ai/resource-crud-core/shared/crudResource";
2
+
3
+ const resource = defineCrudResource({
4
+ namespace: "users",
5
+ tableName: "users",
6
+ crudOperations: ["list", "view"],
7
+ schema: {
8
+ name: {
9
+ type: "string",
10
+ required: true,
11
+ minLength: 1,
12
+ maxLength: 160,
13
+ actualField: "display_name",
14
+ search: true,
15
+ operations: {
16
+ output: { required: false }
17
+ }
18
+ },
19
+ email: {
20
+ type: "string",
21
+ required: true,
22
+ search: true,
23
+ operations: {
24
+ output: { required: false }
25
+ }
26
+ },
27
+ username: {
28
+ type: "string",
29
+ required: true,
30
+ search: true,
31
+ operations: {
32
+ output: { required: false }
33
+ }
34
+ },
35
+ createdAt: {
36
+ type: "dateTime",
37
+ required: true,
38
+ storage: { writeSerializer: "datetime-utc" },
39
+ operations: {
40
+ output: { required: true }
41
+ }
42
+ },
43
+ updatedAt: {
44
+ type: "dateTime",
45
+ required: true,
46
+ storage: { writeSerializer: "datetime-utc" },
47
+ operations: {
48
+ output: { required: true }
49
+ }
50
+ }
51
+ },
52
+ searchSchema: {
53
+ id: {
54
+ type: "id",
55
+ actualField: "id"
56
+ },
57
+ q: {
58
+ type: "string",
59
+ oneOf: ["name", "email", "username"],
60
+ filterOperator: "like",
61
+ splitBy: " ",
62
+ matchAll: true
63
+ }
64
+ },
65
+ defaultSort: ["name", "email"],
66
+ autofilter: "public"
67
+ });
68
+
69
+ export { resource };
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@app/users-workspace",
3
+ "version": "0.0.0",
4
+ "description": "App-local workspace-scoped read-only user administration feature.",
5
+ "private": true,
6
+ "type": "module",
7
+ "exports": {
8
+ "./server/UsersWorkspaceFeature": "./src/server/UsersWorkspaceFeature.js",
9
+ "./shared": "./src/shared/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@jskit-ai/crud-core": "0.1.189",
13
+ "@jskit-ai/resource-crud-core": "0.1.120",
14
+ "@jskit-ai/workspaces-core": "0.1.156"
15
+ },
16
+ "jskit": {
17
+ "kind": "runtime",
18
+ "capabilities": {
19
+ "provides": [
20
+ "app.users-workspace"
21
+ ],
22
+ "requires": [
23
+ "runtime.http",
24
+ "runtime.json-rest-api",
25
+ "runtime.actions",
26
+ "runtime.database"
27
+ ]
28
+ },
29
+ "runtime": {
30
+ "server": {
31
+ "providers": [
32
+ {
33
+ "entrypoint": "src/server/UsersWorkspaceFeature.js",
34
+ "export": "UsersWorkspaceFeature"
35
+ }
36
+ ]
37
+ },
38
+ "client": {
39
+ "providers": []
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,22 @@
1
+ import { defineCrudJsonApiFeature } from "@jskit-ai/crud-core/server/defineCrudJsonApiFeature";
2
+ import { buildWorkspaceInputFromRouteParams } from "@jskit-ai/workspaces-core/server/support/workspaceRouteInput";
3
+ import { workspaceSlugParamsValidator } from "@jskit-ai/workspaces-core/server/validators/routeParamsValidator";
4
+ import { resource } from "../shared/userResource.js";
5
+
6
+ const UsersWorkspaceFeature = defineCrudJsonApiFeature({
7
+ resource,
8
+ id: "app.users-workspace",
9
+ capability: "app.users-workspace",
10
+ surface: "admin",
11
+ ownershipFilter: "workspace",
12
+ relativePath: "/users",
13
+ scope: {
14
+ routeBase: "/w/:workspaceSlug",
15
+ actionInputValidator: workspaceSlugParamsValidator,
16
+ routeParamsValidator: workspaceSlugParamsValidator,
17
+ inputKeys: ["workspaceSlug"],
18
+ input: (request) => buildWorkspaceInputFromRouteParams(request.input.params)
19
+ }
20
+ });
21
+
22
+ export { UsersWorkspaceFeature };
@@ -0,0 +1,56 @@
1
+ import { defineCrudResource } from "@jskit-ai/resource-crud-core/shared/crudResource";
2
+
3
+ const resource = defineCrudResource({
4
+ namespace: "users",
5
+ tableName: "users",
6
+ crudOperations: ["list", "view"],
7
+ schema: {
8
+ name: {
9
+ type: "string",
10
+ required: true,
11
+ minLength: 1,
12
+ maxLength: 160,
13
+ actualField: "display_name",
14
+ search: true,
15
+ operations: { output: { required: false } }
16
+ },
17
+ email: {
18
+ type: "string",
19
+ required: true,
20
+ search: true,
21
+ operations: { output: { required: false } }
22
+ },
23
+ username: {
24
+ type: "string",
25
+ required: true,
26
+ search: true,
27
+ operations: { output: { required: false } }
28
+ },
29
+ createdAt: {
30
+ type: "dateTime",
31
+ required: true,
32
+ storage: { writeSerializer: "datetime-utc" },
33
+ operations: { output: { required: true } }
34
+ },
35
+ updatedAt: {
36
+ type: "dateTime",
37
+ required: true,
38
+ storage: { writeSerializer: "datetime-utc" },
39
+ operations: { output: { required: true } }
40
+ }
41
+ },
42
+ searchSchema: {
43
+ id: { type: "id", actualField: "id" },
44
+ q: {
45
+ type: "string",
46
+ oneOf: ["name", "email", "username"],
47
+ filterOperator: "like",
48
+ splitBy: " ",
49
+ matchAll: true
50
+ }
51
+ },
52
+ defaultSort: ["name", "email"],
53
+ autofilter: "public"
54
+ });
55
+
56
+ export { resource };
@@ -0,0 +1,60 @@
1
+ ---
2
+ id: workspaces/workspace-server
3
+ title: Workspace tenancy server composition
4
+ summary: Configure roles, workspace access policy, invitations, and app-owned invitation email rendering around JSKIT workspace runtime APIs.
5
+ keywords: access, invite, membership, multitenancy, policy, role, tenancy, workspace
6
+ requires: @jskit-ai/workspaces-core, @jskit-ai/users-core
7
+ ---
8
+
9
+ # Workspace tenancy server composition
10
+
11
+ ## Use when
12
+
13
+ Use this pattern when records, routes, or navigation belong to a selected
14
+ workspace and membership or role affects access.
15
+
16
+ ## Do not use when
17
+
18
+ Do not use workspace tenancy for a genuinely single-owner product or as a
19
+ substitute for a simpler domain ownership column.
20
+
21
+ ## Product decisions
22
+
23
+ Choose workspace creation policy, roles, invitation policy, expiry, email copy,
24
+ member permissions, personal-workspace behavior, and surface access rules.
25
+
26
+ ## Framework APIs
27
+
28
+ Use workspace routes, resources, scope helpers, tenancy profiles, and settings
29
+ contracts exported by `@jskit-ai/workspaces-core`.
30
+
31
+ ## Invariants
32
+
33
+ - Workspace membership and role are checked before scoped application actions.
34
+ - Role ids are stable product vocabulary shared by server and client config.
35
+ - Invitation tokens remain secret; emails receive only the intended link.
36
+ - Workspace scope reaches repository queries, not just route parsing.
37
+ - Package-owned migrations run directly from the installed package graph.
38
+
39
+ ## Example files
40
+
41
+ `example/config/roles.js` is a concrete role catalogue.
42
+ `example/packages/main/src/server/email/workspaceInviteEmail.js` demonstrates an
43
+ app-owned invitation renderer. Compose both through normal application config.
44
+
45
+ ## Variation points
46
+
47
+ Change roles, invitation policy and copy, defaults, access policies, surface
48
+ ids, and product-specific workspace settings.
49
+
50
+ ## Verification
51
+
52
+ Test create/list/select, member and non-member access, each role boundary,
53
+ invitation expiry/redemption, cross-workspace isolation, and email output.
54
+
55
+ ## Avoid
56
+
57
+ - synthetic membership workarounds
58
+ - authorizing from client navigation state
59
+ - embedding invitation templates or secrets in package metadata
60
+ - source-appending install commands
@@ -0,0 +1,27 @@
1
+ export const roleCatalog = {
2
+ workspace: {
3
+ defaultInviteRole: "member"
4
+ },
5
+ roles: {
6
+ owner: {
7
+ assignable: false,
8
+ permissions: ["*"]
9
+ },
10
+ admin: {
11
+ assignable: true,
12
+ inherits: "member",
13
+ permissions: [
14
+ "workspace.roles.view",
15
+ "workspace.settings.update",
16
+ "workspace.members.view",
17
+ "workspace.members.invite",
18
+ "workspace.members.manage",
19
+ "workspace.invites.revoke"
20
+ ]
21
+ },
22
+ member: {
23
+ assignable: true,
24
+ permissions: ["workspace.settings.view"]
25
+ }
26
+ }
27
+ };
@@ -0,0 +1,23 @@
1
+ function renderWorkspaceInviteEmail({
2
+ inviteUrl = "",
3
+ workspace = {},
4
+ inviter = null,
5
+ roleSid = "member",
6
+ expiresAt = ""
7
+ } = {}) {
8
+ const workspaceName = String(workspace?.name || workspace?.slug || "the workspace").trim() || "the workspace";
9
+ const inviterName = String(inviter?.displayName || inviter?.email || "").trim();
10
+ const roleName = String(roleSid || "member").trim() || "member";
11
+ const intro = inviterName
12
+ ? `${inviterName} invited you to join ${workspaceName} as ${roleName}.`
13
+ : `You have been invited to join ${workspaceName} as ${roleName}.`;
14
+ const expiryText = expiresAt ? `This invitation expires at ${expiresAt}.` : "";
15
+
16
+ return {
17
+ subject: `You're invited to ${workspaceName}`,
18
+ text: [intro, expiryText, "Open this link to accept the invitation:", inviteUrl].filter(Boolean).join("\n\n"),
19
+ html: null
20
+ };
21
+ }
22
+
23
+ export { renderWorkspaceInviteEmail };
@@ -0,0 +1,63 @@
1
+ ---
2
+ id: workspaces/workspace-surfaces
3
+ title: Workspace application and administration surfaces
4
+ summary: Compose workspace selection, invitation, member administration, settings, and responsive navigation using JSKIT workspace web APIs.
5
+ keywords: admin, invite, member, navigation, settings, surface, switcher, workspace
6
+ requires: @jskit-ai/workspaces-core, @jskit-ai/workspaces-web, @jskit-ai/shell-web
7
+ ---
8
+
9
+ # Workspace application and administration surfaces
10
+
11
+ ## Use when
12
+
13
+ Use this pattern when the product has workspace-scoped app and administration
14
+ surfaces, invitations, member management, or workspace switching.
15
+
16
+ ## Do not use when
17
+
18
+ Do not use this pattern for a single-owner application, or copy its whole
19
+ surface tree when only one workspace widget is needed.
20
+
21
+ ## Product decisions
22
+
23
+ Choose public invitation routes, application/admin surface ids, workspace
24
+ selector behavior, member-management permissions, settings sections, and the
25
+ empty or not-found experience.
26
+
27
+ ## Framework APIs
28
+
29
+ Use the workspace client provider, components, and composables exported by
30
+ `@jskit-ai/workspaces-web` together with JSKIT shell placements and routes.
31
+
32
+ ## Invariants
33
+
34
+ - Route workspace slug, selected workspace, and server scope stay synchronized.
35
+ - Invitation acceptance is public only where the server contract permits it.
36
+ - Administrative UI visibility never substitutes for server authorization.
37
+ - Query and route state hydrate immediately on warm-cache navigation.
38
+ - Loading uses skeletons; mutation failures use toasts without layout movement.
39
+ - Navigation is composed through semantic placements and registered tokens.
40
+
41
+ ## Example files
42
+
43
+ `example/` contains workspace app/admin roots, starter pages, invitation route,
44
+ member and settings routes, not-found state, app-owned invitation widgets, and
45
+ the components that an application's client provider registers.
46
+
47
+ ## Variation points
48
+
49
+ Change surfaces, routes, section owners, labels, icons, placement order,
50
+ workspace-not-found copy, member operations, and invitation presentation.
51
+
52
+ ## Verification
53
+
54
+ Exercise direct workspace URLs, selection and switching, invitations, members,
55
+ settings, not-found state, browser back/forward, forbidden access, and all
56
+ responsive navigation variants.
57
+
58
+ ## Avoid
59
+
60
+ - defaulting silently to another workspace after an invalid route
61
+ - unscoped queries
62
+ - inline mutation error banners
63
+ - generated placement or source mutation machinery
@@ -0,0 +1,106 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { useRoute } from "vue-router";
4
+ import { mdiEmailAlertOutline } from "@mdi/js";
5
+ import { appendQueryString } from "@jskit-ai/kernel/shared/support";
6
+ import {
7
+ useWebPlacementContext,
8
+ resolveSurfaceDefinitionFromPlacementContext,
9
+ resolveSurfacePathFromPlacementContext,
10
+ resolveSurfaceNavigationTargetFromPlacementContext
11
+ } from "@jskit-ai/shell-web/client/placement";
12
+
13
+ const { context: placementContext } = useWebPlacementContext();
14
+ const route = useRoute();
15
+
16
+ function normalizePendingInvitesCount(value) {
17
+ const numeric = Number(value);
18
+ if (!Number.isInteger(numeric) || numeric < 1) {
19
+ return 0;
20
+ }
21
+ return numeric;
22
+ }
23
+
24
+ function resolveReturnTo() {
25
+ const fullPath = String(route?.fullPath || "").trim();
26
+ if (fullPath.startsWith("/") && !fullPath.startsWith("//")) {
27
+ return fullPath;
28
+ }
29
+ const path = String(route?.path || "").trim();
30
+ if (path.startsWith("/") && !path.startsWith("//")) {
31
+ return path;
32
+ }
33
+ return "/";
34
+ }
35
+
36
+ function resolveReturnToHref() {
37
+ if (typeof window === "object" && window?.location?.href) {
38
+ return String(window.location.href || "").trim() || resolveReturnTo();
39
+ }
40
+ return resolveReturnTo();
41
+ }
42
+
43
+ const authenticated = computed(() => placementContext.value?.auth?.authenticated === true);
44
+ const placementPendingInvitesCount = computed(() =>
45
+ normalizePendingInvitesCount(placementContext.value?.pendingInvitesCount)
46
+ );
47
+ const pendingInvitesCount = computed(() => placementPendingInvitesCount.value);
48
+ const placementWorkspaceInvitesEnabled = computed(() => placementContext.value?.workspaceInvitesEnabled === true);
49
+ const workspaceInvitesEnabled = computed(() => placementWorkspaceInvitesEnabled.value);
50
+
51
+ const isVisible = computed(() => {
52
+ return (
53
+ authenticated.value &&
54
+ workspaceInvitesEnabled.value &&
55
+ pendingInvitesCount.value > 0
56
+ );
57
+ });
58
+
59
+ const resolvedTo = computed(() => {
60
+ const hasAccountSurface = Boolean(resolveSurfaceDefinitionFromPlacementContext(placementContext.value, "account"));
61
+ const accountSettingsPath = hasAccountSurface
62
+ ? resolveSurfacePathFromPlacementContext(placementContext.value, "account", "/")
63
+ : "/account";
64
+ const accountSettingsNavigation = resolveSurfaceNavigationTargetFromPlacementContext(placementContext.value, {
65
+ path: accountSettingsPath,
66
+ surfaceId: "account"
67
+ });
68
+
69
+ const query = new URLSearchParams({
70
+ section: "invites",
71
+ returnTo: accountSettingsNavigation.sameOrigin ? resolveReturnTo() : resolveReturnToHref()
72
+ });
73
+ return appendQueryString(accountSettingsPath, query.toString());
74
+ });
75
+
76
+ const resolvedNavigationTarget = computed(() =>
77
+ resolveSurfaceNavigationTargetFromPlacementContext(placementContext.value, {
78
+ path: resolvedTo.value,
79
+ surfaceId: "account"
80
+ })
81
+ );
82
+ </script>
83
+
84
+ <template>
85
+ <v-badge
86
+ v-if="isVisible"
87
+ color="error"
88
+ :content="pendingInvitesCount"
89
+ :model-value="pendingInvitesCount > 0"
90
+ bordered
91
+ offset-x="6"
92
+ offset-y="8"
93
+ >
94
+ <v-btn
95
+ :to="resolvedNavigationTarget.sameOrigin ? resolvedNavigationTarget.href : undefined"
96
+ :href="resolvedNavigationTarget.sameOrigin ? undefined : resolvedNavigationTarget.href"
97
+ variant="tonal"
98
+ color="warning"
99
+ :prepend-icon="mdiEmailAlertOutline"
100
+ size="small"
101
+ class="text-none"
102
+ >
103
+ Invites
104
+ </v-btn>
105
+ </v-badge>
106
+ </template>
@@ -0,0 +1,7 @@
1
+ <script setup>
2
+ import WorkspacesWebAccountSettingsInvitesSection from "@jskit-ai/workspaces-web/client/components/AccountSettingsInvitesSection";
3
+ </script>
4
+
5
+ <template>
6
+ <WorkspacesWebAccountSettingsInvitesSection />
7
+ </template>
@@ -0,0 +1,53 @@
1
+ <script setup>
2
+ import { mdiAlertCircleOutline } from "@mdi/js";
3
+ import { computed } from "vue";
4
+
5
+ const props = defineProps({
6
+ surfaceLabel: {
7
+ type: String,
8
+ default: "Workspace"
9
+ },
10
+ message: {
11
+ type: String,
12
+ default: "Workspace is currently unavailable."
13
+ }
14
+ });
15
+
16
+ const normalizedSurfaceLabel = computed(() => String(props.surfaceLabel || "").trim() || "Workspace");
17
+ const normalizedMessage = computed(() => String(props.message || "").trim() || "Workspace is currently unavailable.");
18
+ </script>
19
+
20
+ <template>
21
+ <v-sheet rounded="lg" border class="workspace-unavailable-panel">
22
+ <div class="workspace-unavailable-panel__header">
23
+ <v-icon :icon="mdiAlertCircleOutline" color="error" />
24
+ <div>
25
+ <h1 class="workspace-unavailable-panel__title">Unavailable</h1>
26
+ <p class="text-body-2 text-medium-emphasis mb-0">{{ normalizedSurfaceLabel }} surface.</p>
27
+ </div>
28
+ </div>
29
+ <p class="text-body-2 text-medium-emphasis mb-0">{{ normalizedMessage }}</p>
30
+ </v-sheet>
31
+ </template>
32
+
33
+ <style scoped>
34
+ .workspace-unavailable-panel {
35
+ display: grid;
36
+ gap: 1rem;
37
+ padding: 1rem;
38
+ }
39
+
40
+ .workspace-unavailable-panel__header {
41
+ align-items: flex-start;
42
+ display: flex;
43
+ gap: 0.75rem;
44
+ }
45
+
46
+ .workspace-unavailable-panel__title {
47
+ font-size: clamp(1.35rem, 2vw, 1.85rem);
48
+ font-weight: 650;
49
+ letter-spacing: -0.02em;
50
+ line-height: 1.15;
51
+ margin: 0 0 0.25rem;
52
+ }
53
+ </style>
@@ -0,0 +1,41 @@
1
+ import { computed } from "vue";
2
+ import { useRoute } from "vue-router";
3
+ import { normalizeLowerText, normalizeObject } from "@jskit-ai/kernel/shared/support/normalize";
4
+ import { useWebPlacementContext } from "@jskit-ai/shell-web/client/placement";
5
+
6
+ const STATUS_MESSAGES = {
7
+ not_found: "The requested workspace was not found.",
8
+ forbidden: "You do not have access to this workspace.",
9
+ unauthenticated: "You need to sign in to access this workspace.",
10
+ error: "Workspace data could not be loaded right now."
11
+ };
12
+ const DEFAULT_WORKSPACE_UNAVAILABLE_MESSAGE = "Workspace is currently unavailable.";
13
+ const RESOLVED_WORKSPACE_STATUS = "resolved";
14
+
15
+ function useWorkspaceNotFoundState() {
16
+ const route = useRoute();
17
+ const { context: placementContext } = useWebPlacementContext();
18
+
19
+ const routeWorkspaceSlug = computed(() => normalizeLowerText(route?.params?.workspaceSlug));
20
+
21
+ const workspaceBootstrapStatus = computed(() => {
22
+ const statuses = normalizeObject(placementContext.value?.workspaceBootstrapStatuses);
23
+ return normalizeLowerText(statuses[routeWorkspaceSlug.value]);
24
+ });
25
+
26
+ const workspaceUnavailable = computed(
27
+ () => Boolean(workspaceBootstrapStatus.value) && workspaceBootstrapStatus.value !== RESOLVED_WORKSPACE_STATUS
28
+ );
29
+ const workspaceUnavailableMessage = computed(
30
+ () => STATUS_MESSAGES[workspaceBootstrapStatus.value] || DEFAULT_WORKSPACE_UNAVAILABLE_MESSAGE
31
+ );
32
+
33
+ return Object.freeze({
34
+ routeWorkspaceSlug,
35
+ workspaceBootstrapStatus,
36
+ workspaceUnavailable,
37
+ workspaceUnavailableMessage
38
+ });
39
+ }
40
+
41
+ export { useWorkspaceNotFoundState };
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <WorkspaceMembersClientElement />
3
+ </template>
4
+
5
+ <script setup>
6
+ import WorkspaceMembersClientElement from "@jskit-ai/workspaces-web/client/components/WorkspaceMembersClientElement";
7
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <section class="workspace-settings-landing">
3
+ <v-sheet rounded="lg" border class="workspace-settings-landing__panel">
4
+ <h2 class="workspace-settings-landing__title">No settings sections yet</h2>
5
+ <p class="text-body-2 text-medium-emphasis mb-0">
6
+ This app has no workspace-level settings configured.
7
+ </p>
8
+ </v-sheet>
9
+ </section>
10
+ </template>
11
+
12
+ <style scoped>
13
+ .workspace-settings-landing__panel {
14
+ padding: 1rem;
15
+ }
16
+
17
+ .workspace-settings-landing__title {
18
+ font-size: 1rem;
19
+ font-weight: 650;
20
+ line-height: 1.2;
21
+ margin: 0 0 0.25rem;
22
+ }
23
+ </style>