@askrjs/cli 0.0.2

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 (460) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +140 -0
  3. package/dist/add-DqhqRzBQ.js +555 -0
  4. package/dist/add-DqhqRzBQ.js.map +1 -0
  5. package/dist/add.js +3 -0
  6. package/dist/cli.js +91 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/create.js +923 -0
  9. package/dist/create.js.map +1 -0
  10. package/dist/is-direct-execution-Cdlr-ZUl.js +20 -0
  11. package/dist/is-direct-execution-Cdlr-ZUl.js.map +1 -0
  12. package/dist/openapi.js +127 -0
  13. package/dist/openapi.js.map +1 -0
  14. package/dist/skills/askr-accessibility/SKILL.md +68 -0
  15. package/dist/skills/askr-accessibility/agents/openai.yaml +4 -0
  16. package/dist/skills/askr-agent-execution/SKILL.md +85 -0
  17. package/dist/skills/askr-agent-execution/agents/openai.yaml +4 -0
  18. package/dist/skills/askr-agent-workflows/SKILL.md +57 -0
  19. package/dist/skills/askr-agent-workflows/agents/openai.yaml +4 -0
  20. package/dist/skills/askr-api-integration/SKILL.md +79 -0
  21. package/dist/skills/askr-api-integration/agents/openai.yaml +4 -0
  22. package/dist/skills/askr-app-builder/SKILL.md +99 -0
  23. package/dist/skills/askr-app-builder/agents/openai.yaml +4 -0
  24. package/dist/skills/askr-auth-access/SKILL.md +74 -0
  25. package/dist/skills/askr-auth-access/agents/openai.yaml +4 -0
  26. package/dist/skills/askr-cli-vite/SKILL.md +76 -0
  27. package/dist/skills/askr-cli-vite/agents/openai.yaml +4 -0
  28. package/dist/skills/askr-dashboard-charts/SKILL.md +82 -0
  29. package/dist/skills/askr-dashboard-charts/agents/openai.yaml +4 -0
  30. package/dist/skills/askr-design-system/SKILL.md +86 -0
  31. package/dist/skills/askr-design-system/agents/openai.yaml +4 -0
  32. package/dist/skills/askr-env-config/SKILL.md +74 -0
  33. package/dist/skills/askr-env-config/agents/openai.yaml +4 -0
  34. package/dist/skills/askr-error-loading-empty/SKILL.md +89 -0
  35. package/dist/skills/askr-error-loading-empty/agents/openai.yaml +4 -0
  36. package/dist/skills/askr-file-upload-artifacts/SKILL.md +77 -0
  37. package/dist/skills/askr-file-upload-artifacts/agents/openai.yaml +4 -0
  38. package/dist/skills/askr-forms-tables-crud/SKILL.md +98 -0
  39. package/dist/skills/askr-forms-tables-crud/agents/openai.yaml +4 -0
  40. package/dist/skills/askr-mental-model/SKILL.md +109 -0
  41. package/dist/skills/askr-mental-model/agents/openai.yaml +4 -0
  42. package/dist/skills/askr-migration-react/SKILL.md +81 -0
  43. package/dist/skills/askr-migration-react/agents/openai.yaml +4 -0
  44. package/dist/skills/askr-observability-debugging/SKILL.md +83 -0
  45. package/dist/skills/askr-observability-debugging/agents/openai.yaml +4 -0
  46. package/dist/skills/askr-project-structure/SKILL.md +79 -0
  47. package/dist/skills/askr-project-structure/agents/openai.yaml +4 -0
  48. package/dist/skills/askr-query-mutation/SKILL.md +115 -0
  49. package/dist/skills/askr-query-mutation/agents/openai.yaml +4 -0
  50. package/dist/skills/askr-realtime-streaming/SKILL.md +76 -0
  51. package/dist/skills/askr-realtime-streaming/agents/openai.yaml +4 -0
  52. package/dist/skills/askr-resources-data/SKILL.md +100 -0
  53. package/dist/skills/askr-resources-data/agents/openai.yaml +4 -0
  54. package/dist/skills/askr-routing-layouts/SKILL.md +107 -0
  55. package/dist/skills/askr-routing-layouts/agents/openai.yaml +4 -0
  56. package/dist/skills/askr-runtime-reactivity/SKILL.md +92 -0
  57. package/dist/skills/askr-runtime-reactivity/agents/openai.yaml +4 -0
  58. package/dist/skills/askr-ssr-ssg/SKILL.md +76 -0
  59. package/dist/skills/askr-ssr-ssg/agents/openai.yaml +4 -0
  60. package/dist/skills/askr-testing-determinism/SKILL.md +75 -0
  61. package/dist/skills/askr-testing-determinism/agents/openai.yaml +4 -0
  62. package/dist/skills/askr-theming/SKILL.md +86 -0
  63. package/dist/skills/askr-theming/agents/openai.yaml +4 -0
  64. package/dist/skills/askr-ui-composition/SKILL.md +92 -0
  65. package/dist/skills/askr-ui-composition/agents/openai.yaml +4 -0
  66. package/dist/skills-Bh0mEhIx.js +682 -0
  67. package/dist/skills-Bh0mEhIx.js.map +1 -0
  68. package/dist/skills.js +3 -0
  69. package/dist/ssg.js +188 -0
  70. package/dist/ssg.js.map +1 -0
  71. package/dist/templates/full-stack/AGENTS.md +12 -0
  72. package/dist/templates/full-stack/README.md +18 -0
  73. package/dist/templates/full-stack/gitignore.template +4 -0
  74. package/dist/templates/full-stack/index.html +14 -0
  75. package/dist/templates/full-stack/package.json +37 -0
  76. package/dist/templates/full-stack/server.ts +13 -0
  77. package/dist/templates/full-stack/src/action-authorizations.ts +10 -0
  78. package/dist/templates/full-stack/src/actions/create-message.ts +10 -0
  79. package/dist/templates/full-stack/src/i18n.ts +8 -0
  80. package/dist/templates/full-stack/src/main.tsx +12 -0
  81. package/dist/templates/full-stack/src/pages/home.tsx +25 -0
  82. package/dist/templates/full-stack/src/pages/layout.tsx +33 -0
  83. package/dist/templates/full-stack/src/pages/not-found.tsx +4 -0
  84. package/dist/templates/full-stack/src/routes.tsx +20 -0
  85. package/dist/templates/full-stack/src/schemas.ts +11 -0
  86. package/dist/templates/full-stack/src/server/action-registry.ts +12 -0
  87. package/dist/templates/full-stack/src/server/actions/create-message.ts +14 -0
  88. package/dist/templates/full-stack/src/server/app.ts +66 -0
  89. package/dist/templates/full-stack/src/server/dependencies.ts +55 -0
  90. package/dist/templates/full-stack/src/server/entry-server.ts +8 -0
  91. package/dist/templates/full-stack/src/telemetry.ts +4 -0
  92. package/dist/templates/full-stack/src/vite-server.d.ts +6 -0
  93. package/dist/templates/full-stack/tests/actions/create-message.test.ts +13 -0
  94. package/dist/templates/full-stack/tsconfig.json +16 -0
  95. package/dist/templates/full-stack/vite.config.ts +11 -0
  96. package/dist/templates/spa/AGENTS.md +60 -0
  97. package/dist/templates/spa/README.md +96 -0
  98. package/dist/templates/spa/gitignore.template +16 -0
  99. package/dist/templates/spa/index.html +13 -0
  100. package/dist/templates/spa/package.json +35 -0
  101. package/dist/templates/spa/src/adapters/operations-client.ts +90 -0
  102. package/dist/templates/spa/src/components/shared/metric-card.tsx +27 -0
  103. package/dist/templates/spa/src/components/shared/status-badge.tsx +24 -0
  104. package/dist/templates/spa/src/features/operations/operations.query.ts +9 -0
  105. package/dist/templates/spa/src/main.tsx +10 -0
  106. package/dist/templates/spa/src/pages/_layout.tsx +9 -0
  107. package/dist/templates/spa/src/pages/_routes.tsx +27 -0
  108. package/dist/templates/spa/src/pages/app/_layout.tsx +94 -0
  109. package/dist/templates/spa/src/pages/app/_routes.tsx +10 -0
  110. package/dist/templates/spa/src/pages/app/admin-home.tsx +152 -0
  111. package/dist/templates/spa/src/pages/app/agent-runs.tsx +93 -0
  112. package/dist/templates/spa/src/pages/app/settings.tsx +91 -0
  113. package/dist/templates/spa/src/pages/auth/_layout.tsx +38 -0
  114. package/dist/templates/spa/src/pages/auth/_routes.tsx +6 -0
  115. package/dist/templates/spa/src/pages/auth/login.tsx +63 -0
  116. package/dist/templates/spa/src/pages/not-found.tsx +22 -0
  117. package/dist/templates/spa/src/pages/public/_layout.tsx +47 -0
  118. package/dist/templates/spa/src/pages/public/_routes.tsx +6 -0
  119. package/dist/templates/spa/src/pages/public/home.tsx +143 -0
  120. package/dist/templates/spa/src/shared/format.ts +12 -0
  121. package/dist/templates/spa/src/shared/navigation.ts +15 -0
  122. package/dist/templates/spa/src/styles/components.css +49 -0
  123. package/dist/templates/spa/src/styles/layout.css +192 -0
  124. package/dist/templates/spa/src/styles/reset.css +44 -0
  125. package/dist/templates/spa/src/styles/theme.css +57 -0
  126. package/dist/templates/spa/src/styles/tokens.css +20 -0
  127. package/dist/templates/spa/src/styles.css +7 -0
  128. package/dist/templates/spa/src/styles.d.ts +1 -0
  129. package/dist/templates/spa/tests/app.test.tsx +37 -0
  130. package/dist/templates/spa/tests/components/shared.test.tsx +12 -0
  131. package/dist/templates/spa/tests/resources.test.ts +22 -0
  132. package/dist/templates/spa/tsconfig.json +20 -0
  133. package/dist/templates/spa/tsconfig.node.json +10 -0
  134. package/dist/templates/spa/vite.config.ts +24 -0
  135. package/dist/templates/spa/vitest.config.ts +17 -0
  136. package/dist/templates/ssg/AGENTS.md +55 -0
  137. package/dist/templates/ssg/README.md +39 -0
  138. package/dist/templates/ssg/gitignore.template +17 -0
  139. package/dist/templates/ssg/index.html +13 -0
  140. package/dist/templates/ssg/package.json +35 -0
  141. package/dist/templates/ssg/src/app.tsx +14 -0
  142. package/dist/templates/ssg/src/components/badge.tsx +3 -0
  143. package/dist/templates/ssg/src/components/counter.tsx +30 -0
  144. package/dist/templates/ssg/src/components/site-shell.tsx +111 -0
  145. package/dist/templates/ssg/src/jsx.d.ts +23 -0
  146. package/dist/templates/ssg/src/main.tsx +8 -0
  147. package/dist/templates/ssg/src/pages/about.tsx +82 -0
  148. package/dist/templates/ssg/src/pages/content.tsx +63 -0
  149. package/dist/templates/ssg/src/pages/example.tsx +97 -0
  150. package/dist/templates/ssg/src/pages/home.tsx +51 -0
  151. package/dist/templates/ssg/src/resources/user.ts +15 -0
  152. package/dist/templates/ssg/src/routes.tsx +15 -0
  153. package/dist/templates/ssg/src/styles.css +89 -0
  154. package/dist/templates/ssg/src/vite-env.d.ts +5 -0
  155. package/dist/templates/ssg/ssg.config.ts +34 -0
  156. package/dist/templates/ssg/tests/app.test.tsx +19 -0
  157. package/dist/templates/ssg/tests/components/counter.test.tsx +18 -0
  158. package/dist/templates/ssg/tests/resources.test.ts +11 -0
  159. package/dist/templates/ssg/tests/ssg-config.test.ts +11 -0
  160. package/dist/templates/ssg/tsconfig.json +20 -0
  161. package/dist/templates/ssg/tsconfig.node.json +10 -0
  162. package/dist/templates/ssg/vite.config.ts +24 -0
  163. package/dist/templates/ssg/vitest.config.ts +17 -0
  164. package/dist/templates/ssr/AGENTS.md +28 -0
  165. package/dist/templates/ssr/README.md +38 -0
  166. package/dist/templates/ssr/gitignore.template +16 -0
  167. package/dist/templates/ssr/index.html +13 -0
  168. package/dist/templates/ssr/package.json +34 -0
  169. package/dist/templates/ssr/server.ts +16 -0
  170. package/dist/templates/ssr/src/app.tsx +21 -0
  171. package/dist/templates/ssr/src/components/counter.tsx +26 -0
  172. package/dist/templates/ssr/src/entry-server.tsx +10 -0
  173. package/dist/templates/ssr/src/main.tsx +11 -0
  174. package/dist/templates/ssr/src/pages/about.tsx +75 -0
  175. package/dist/templates/ssr/src/pages/example.tsx +113 -0
  176. package/dist/templates/ssr/src/pages/home.tsx +56 -0
  177. package/dist/templates/ssr/src/resources/user.ts +15 -0
  178. package/dist/templates/ssr/src/routes.tsx +13 -0
  179. package/dist/templates/ssr/src/styles.css +148 -0
  180. package/dist/templates/ssr/src/vite-server.d.ts +7 -0
  181. package/dist/templates/ssr/tests/app.test.tsx +24 -0
  182. package/dist/templates/ssr/tests/components/counter.test.tsx +13 -0
  183. package/dist/templates/ssr/tests/resources.test.ts +11 -0
  184. package/dist/templates/ssr/tsconfig.json +22 -0
  185. package/dist/templates/ssr/tsconfig.node.json +10 -0
  186. package/dist/templates/ssr/tsconfig.server.json +15 -0
  187. package/dist/templates/ssr/vite.config.ts +25 -0
  188. package/dist/templates/ssr/vitest.config.ts +13 -0
  189. package/dist/templates/startkit/AGENTS.md +77 -0
  190. package/dist/templates/startkit/README.md +192 -0
  191. package/dist/templates/startkit/gitignore.template +16 -0
  192. package/dist/templates/startkit/index.html +13 -0
  193. package/dist/templates/startkit/package.json +35 -0
  194. package/dist/templates/startkit/src/components/app-header.tsx +93 -0
  195. package/dist/templates/startkit/src/components/app-sidebar.tsx +95 -0
  196. package/dist/templates/startkit/src/components/data-table.tsx +80 -0
  197. package/dist/templates/startkit/src/components/empty-state.tsx +13 -0
  198. package/dist/templates/startkit/src/components/page-header.tsx +23 -0
  199. package/dist/templates/startkit/src/components/stat-card.tsx +24 -0
  200. package/dist/templates/startkit/src/features/accounts/account-filters.tsx +61 -0
  201. package/dist/templates/startkit/src/features/accounts/account-table.tsx +79 -0
  202. package/dist/templates/startkit/src/lib/format.ts +31 -0
  203. package/dist/templates/startkit/src/lib/mock-data.ts +441 -0
  204. package/dist/templates/startkit/src/lib/routes.ts +116 -0
  205. package/dist/templates/startkit/src/main.tsx +12 -0
  206. package/dist/templates/startkit/src/pages/_layout.tsx +56 -0
  207. package/dist/templates/startkit/src/pages/auth/_layout.tsx +7 -0
  208. package/dist/templates/startkit/src/pages/auth/login.tsx +129 -0
  209. package/dist/templates/startkit/src/pages/home.tsx +83 -0
  210. package/dist/templates/startkit/src/pages/not-found.tsx +24 -0
  211. package/dist/templates/startkit/src/pages/workspace/_layout.tsx +17 -0
  212. package/dist/templates/startkit/src/pages/workspace/accounts/index.tsx +217 -0
  213. package/dist/templates/startkit/src/pages/workspace/dashboard.tsx +118 -0
  214. package/dist/templates/startkit/src/pages/workspace/settings.tsx +218 -0
  215. package/dist/templates/startkit/src/router.tsx +7 -0
  216. package/dist/templates/startkit/src/routes/auth-config.ts +38 -0
  217. package/dist/templates/startkit/src/routes/auth.ts +8 -0
  218. package/dist/templates/startkit/src/routes/index.ts +28 -0
  219. package/dist/templates/startkit/src/routes/public.ts +8 -0
  220. package/dist/templates/startkit/src/routes/workspace/accounts.ts +8 -0
  221. package/dist/templates/startkit/src/routes/workspace/index.ts +14 -0
  222. package/dist/templates/startkit/src/styles/components.css +396 -0
  223. package/dist/templates/startkit/src/styles/layout.css +192 -0
  224. package/dist/templates/startkit/src/styles/reset.css +38 -0
  225. package/dist/templates/startkit/src/styles/theme.css +76 -0
  226. package/dist/templates/startkit/src/styles/tokens.css +67 -0
  227. package/dist/templates/startkit/src/styles.css +7 -0
  228. package/dist/templates/startkit/src/toast.ts +55 -0
  229. package/dist/templates/startkit/src/utils/join-classes.ts +4 -0
  230. package/dist/templates/startkit/src/vite-env.d.ts +5 -0
  231. package/dist/templates/startkit/tests/app.test.tsx +32 -0
  232. package/dist/templates/startkit/tests/preferences.test.ts +43 -0
  233. package/dist/templates/startkit/tests/resources.test.ts +82 -0
  234. package/dist/templates/startkit/tsconfig.json +20 -0
  235. package/dist/templates/startkit/tsconfig.node.json +10 -0
  236. package/dist/templates/startkit/vite.config.ts +32 -0
  237. package/dist/templates/startkit/vitest.config.ts +13 -0
  238. package/dist/update-DyW1na5V.js +1140 -0
  239. package/dist/update-DyW1na5V.js.map +1 -0
  240. package/dist/update.js +3 -0
  241. package/package.json +84 -0
  242. package/skills/askr-accessibility/SKILL.md +68 -0
  243. package/skills/askr-accessibility/agents/openai.yaml +4 -0
  244. package/skills/askr-agent-execution/SKILL.md +85 -0
  245. package/skills/askr-agent-execution/agents/openai.yaml +4 -0
  246. package/skills/askr-agent-workflows/SKILL.md +57 -0
  247. package/skills/askr-agent-workflows/agents/openai.yaml +4 -0
  248. package/skills/askr-api-integration/SKILL.md +79 -0
  249. package/skills/askr-api-integration/agents/openai.yaml +4 -0
  250. package/skills/askr-app-builder/SKILL.md +99 -0
  251. package/skills/askr-app-builder/agents/openai.yaml +4 -0
  252. package/skills/askr-auth-access/SKILL.md +74 -0
  253. package/skills/askr-auth-access/agents/openai.yaml +4 -0
  254. package/skills/askr-cli-vite/SKILL.md +76 -0
  255. package/skills/askr-cli-vite/agents/openai.yaml +4 -0
  256. package/skills/askr-dashboard-charts/SKILL.md +82 -0
  257. package/skills/askr-dashboard-charts/agents/openai.yaml +4 -0
  258. package/skills/askr-design-system/SKILL.md +86 -0
  259. package/skills/askr-design-system/agents/openai.yaml +4 -0
  260. package/skills/askr-env-config/SKILL.md +74 -0
  261. package/skills/askr-env-config/agents/openai.yaml +4 -0
  262. package/skills/askr-error-loading-empty/SKILL.md +89 -0
  263. package/skills/askr-error-loading-empty/agents/openai.yaml +4 -0
  264. package/skills/askr-file-upload-artifacts/SKILL.md +77 -0
  265. package/skills/askr-file-upload-artifacts/agents/openai.yaml +4 -0
  266. package/skills/askr-forms-tables-crud/SKILL.md +98 -0
  267. package/skills/askr-forms-tables-crud/agents/openai.yaml +4 -0
  268. package/skills/askr-mental-model/SKILL.md +109 -0
  269. package/skills/askr-mental-model/agents/openai.yaml +4 -0
  270. package/skills/askr-migration-react/SKILL.md +81 -0
  271. package/skills/askr-migration-react/agents/openai.yaml +4 -0
  272. package/skills/askr-observability-debugging/SKILL.md +83 -0
  273. package/skills/askr-observability-debugging/agents/openai.yaml +4 -0
  274. package/skills/askr-project-structure/SKILL.md +79 -0
  275. package/skills/askr-project-structure/agents/openai.yaml +4 -0
  276. package/skills/askr-query-mutation/SKILL.md +115 -0
  277. package/skills/askr-query-mutation/agents/openai.yaml +4 -0
  278. package/skills/askr-realtime-streaming/SKILL.md +76 -0
  279. package/skills/askr-realtime-streaming/agents/openai.yaml +4 -0
  280. package/skills/askr-resources-data/SKILL.md +100 -0
  281. package/skills/askr-resources-data/agents/openai.yaml +4 -0
  282. package/skills/askr-routing-layouts/SKILL.md +107 -0
  283. package/skills/askr-routing-layouts/agents/openai.yaml +4 -0
  284. package/skills/askr-runtime-reactivity/SKILL.md +92 -0
  285. package/skills/askr-runtime-reactivity/agents/openai.yaml +4 -0
  286. package/skills/askr-ssr-ssg/SKILL.md +76 -0
  287. package/skills/askr-ssr-ssg/agents/openai.yaml +4 -0
  288. package/skills/askr-testing-determinism/SKILL.md +75 -0
  289. package/skills/askr-testing-determinism/agents/openai.yaml +4 -0
  290. package/skills/askr-theming/SKILL.md +86 -0
  291. package/skills/askr-theming/agents/openai.yaml +4 -0
  292. package/skills/askr-ui-composition/SKILL.md +92 -0
  293. package/skills/askr-ui-composition/agents/openai.yaml +4 -0
  294. package/templates/full-stack/AGENTS.md +12 -0
  295. package/templates/full-stack/README.md +18 -0
  296. package/templates/full-stack/gitignore.template +4 -0
  297. package/templates/full-stack/index.html +14 -0
  298. package/templates/full-stack/package.json +37 -0
  299. package/templates/full-stack/server.ts +13 -0
  300. package/templates/full-stack/src/action-authorizations.ts +10 -0
  301. package/templates/full-stack/src/actions/create-message.ts +10 -0
  302. package/templates/full-stack/src/i18n.ts +8 -0
  303. package/templates/full-stack/src/main.tsx +12 -0
  304. package/templates/full-stack/src/pages/home.tsx +25 -0
  305. package/templates/full-stack/src/pages/layout.tsx +33 -0
  306. package/templates/full-stack/src/pages/not-found.tsx +4 -0
  307. package/templates/full-stack/src/routes.tsx +20 -0
  308. package/templates/full-stack/src/schemas.ts +11 -0
  309. package/templates/full-stack/src/server/action-registry.ts +12 -0
  310. package/templates/full-stack/src/server/actions/create-message.ts +14 -0
  311. package/templates/full-stack/src/server/app.ts +66 -0
  312. package/templates/full-stack/src/server/dependencies.ts +55 -0
  313. package/templates/full-stack/src/server/entry-server.ts +8 -0
  314. package/templates/full-stack/src/telemetry.ts +4 -0
  315. package/templates/full-stack/src/vite-server.d.ts +6 -0
  316. package/templates/full-stack/tests/actions/create-message.test.ts +13 -0
  317. package/templates/full-stack/tsconfig.json +16 -0
  318. package/templates/full-stack/vite.config.ts +11 -0
  319. package/templates/spa/AGENTS.md +60 -0
  320. package/templates/spa/README.md +96 -0
  321. package/templates/spa/gitignore.template +16 -0
  322. package/templates/spa/index.html +13 -0
  323. package/templates/spa/package.json +35 -0
  324. package/templates/spa/src/adapters/operations-client.ts +90 -0
  325. package/templates/spa/src/components/shared/metric-card.tsx +27 -0
  326. package/templates/spa/src/components/shared/status-badge.tsx +24 -0
  327. package/templates/spa/src/features/operations/operations.query.ts +9 -0
  328. package/templates/spa/src/main.tsx +10 -0
  329. package/templates/spa/src/pages/_layout.tsx +9 -0
  330. package/templates/spa/src/pages/_routes.tsx +27 -0
  331. package/templates/spa/src/pages/app/_layout.tsx +94 -0
  332. package/templates/spa/src/pages/app/_routes.tsx +10 -0
  333. package/templates/spa/src/pages/app/admin-home.tsx +152 -0
  334. package/templates/spa/src/pages/app/agent-runs.tsx +93 -0
  335. package/templates/spa/src/pages/app/settings.tsx +91 -0
  336. package/templates/spa/src/pages/auth/_layout.tsx +38 -0
  337. package/templates/spa/src/pages/auth/_routes.tsx +6 -0
  338. package/templates/spa/src/pages/auth/login.tsx +63 -0
  339. package/templates/spa/src/pages/not-found.tsx +22 -0
  340. package/templates/spa/src/pages/public/_layout.tsx +47 -0
  341. package/templates/spa/src/pages/public/_routes.tsx +6 -0
  342. package/templates/spa/src/pages/public/home.tsx +143 -0
  343. package/templates/spa/src/shared/format.ts +12 -0
  344. package/templates/spa/src/shared/navigation.ts +15 -0
  345. package/templates/spa/src/styles/components.css +49 -0
  346. package/templates/spa/src/styles/layout.css +192 -0
  347. package/templates/spa/src/styles/reset.css +44 -0
  348. package/templates/spa/src/styles/theme.css +57 -0
  349. package/templates/spa/src/styles/tokens.css +20 -0
  350. package/templates/spa/src/styles.css +7 -0
  351. package/templates/spa/src/styles.d.ts +1 -0
  352. package/templates/spa/tests/app.test.tsx +37 -0
  353. package/templates/spa/tests/components/shared.test.tsx +12 -0
  354. package/templates/spa/tests/resources.test.ts +22 -0
  355. package/templates/spa/tsconfig.json +20 -0
  356. package/templates/spa/tsconfig.node.json +10 -0
  357. package/templates/spa/vite.config.ts +24 -0
  358. package/templates/spa/vitest.config.ts +17 -0
  359. package/templates/ssg/AGENTS.md +55 -0
  360. package/templates/ssg/README.md +39 -0
  361. package/templates/ssg/gitignore.template +17 -0
  362. package/templates/ssg/index.html +13 -0
  363. package/templates/ssg/package.json +35 -0
  364. package/templates/ssg/src/app.tsx +14 -0
  365. package/templates/ssg/src/components/badge.tsx +3 -0
  366. package/templates/ssg/src/components/counter.tsx +30 -0
  367. package/templates/ssg/src/components/site-shell.tsx +111 -0
  368. package/templates/ssg/src/jsx.d.ts +23 -0
  369. package/templates/ssg/src/main.tsx +8 -0
  370. package/templates/ssg/src/pages/about.tsx +82 -0
  371. package/templates/ssg/src/pages/content.tsx +63 -0
  372. package/templates/ssg/src/pages/example.tsx +97 -0
  373. package/templates/ssg/src/pages/home.tsx +51 -0
  374. package/templates/ssg/src/resources/user.ts +15 -0
  375. package/templates/ssg/src/routes.tsx +15 -0
  376. package/templates/ssg/src/styles.css +89 -0
  377. package/templates/ssg/src/vite-env.d.ts +5 -0
  378. package/templates/ssg/ssg.config.ts +34 -0
  379. package/templates/ssg/tests/app.test.tsx +19 -0
  380. package/templates/ssg/tests/components/counter.test.tsx +18 -0
  381. package/templates/ssg/tests/resources.test.ts +11 -0
  382. package/templates/ssg/tests/ssg-config.test.ts +11 -0
  383. package/templates/ssg/tsconfig.json +20 -0
  384. package/templates/ssg/tsconfig.node.json +10 -0
  385. package/templates/ssg/vite.config.ts +24 -0
  386. package/templates/ssg/vitest.config.ts +17 -0
  387. package/templates/ssr/AGENTS.md +28 -0
  388. package/templates/ssr/README.md +38 -0
  389. package/templates/ssr/gitignore.template +16 -0
  390. package/templates/ssr/index.html +13 -0
  391. package/templates/ssr/package.json +34 -0
  392. package/templates/ssr/server.ts +16 -0
  393. package/templates/ssr/src/app.tsx +21 -0
  394. package/templates/ssr/src/components/counter.tsx +26 -0
  395. package/templates/ssr/src/entry-server.tsx +10 -0
  396. package/templates/ssr/src/main.tsx +11 -0
  397. package/templates/ssr/src/pages/about.tsx +75 -0
  398. package/templates/ssr/src/pages/example.tsx +113 -0
  399. package/templates/ssr/src/pages/home.tsx +56 -0
  400. package/templates/ssr/src/resources/user.ts +15 -0
  401. package/templates/ssr/src/routes.tsx +13 -0
  402. package/templates/ssr/src/styles.css +148 -0
  403. package/templates/ssr/src/vite-server.d.ts +7 -0
  404. package/templates/ssr/tests/app.test.tsx +24 -0
  405. package/templates/ssr/tests/components/counter.test.tsx +13 -0
  406. package/templates/ssr/tests/resources.test.ts +11 -0
  407. package/templates/ssr/tsconfig.json +22 -0
  408. package/templates/ssr/tsconfig.node.json +10 -0
  409. package/templates/ssr/tsconfig.server.json +15 -0
  410. package/templates/ssr/vite.config.ts +25 -0
  411. package/templates/ssr/vitest.config.ts +13 -0
  412. package/templates/startkit/AGENTS.md +77 -0
  413. package/templates/startkit/README.md +192 -0
  414. package/templates/startkit/gitignore.template +16 -0
  415. package/templates/startkit/index.html +13 -0
  416. package/templates/startkit/package.json +35 -0
  417. package/templates/startkit/src/components/app-header.tsx +93 -0
  418. package/templates/startkit/src/components/app-sidebar.tsx +95 -0
  419. package/templates/startkit/src/components/data-table.tsx +80 -0
  420. package/templates/startkit/src/components/empty-state.tsx +13 -0
  421. package/templates/startkit/src/components/page-header.tsx +23 -0
  422. package/templates/startkit/src/components/stat-card.tsx +24 -0
  423. package/templates/startkit/src/features/accounts/account-filters.tsx +61 -0
  424. package/templates/startkit/src/features/accounts/account-table.tsx +79 -0
  425. package/templates/startkit/src/lib/format.ts +31 -0
  426. package/templates/startkit/src/lib/mock-data.ts +441 -0
  427. package/templates/startkit/src/lib/routes.ts +116 -0
  428. package/templates/startkit/src/main.tsx +12 -0
  429. package/templates/startkit/src/pages/_layout.tsx +56 -0
  430. package/templates/startkit/src/pages/auth/_layout.tsx +7 -0
  431. package/templates/startkit/src/pages/auth/login.tsx +129 -0
  432. package/templates/startkit/src/pages/home.tsx +83 -0
  433. package/templates/startkit/src/pages/not-found.tsx +24 -0
  434. package/templates/startkit/src/pages/workspace/_layout.tsx +17 -0
  435. package/templates/startkit/src/pages/workspace/accounts/index.tsx +217 -0
  436. package/templates/startkit/src/pages/workspace/dashboard.tsx +118 -0
  437. package/templates/startkit/src/pages/workspace/settings.tsx +218 -0
  438. package/templates/startkit/src/router.tsx +7 -0
  439. package/templates/startkit/src/routes/auth-config.ts +38 -0
  440. package/templates/startkit/src/routes/auth.ts +8 -0
  441. package/templates/startkit/src/routes/index.ts +28 -0
  442. package/templates/startkit/src/routes/public.ts +8 -0
  443. package/templates/startkit/src/routes/workspace/accounts.ts +8 -0
  444. package/templates/startkit/src/routes/workspace/index.ts +14 -0
  445. package/templates/startkit/src/styles/components.css +396 -0
  446. package/templates/startkit/src/styles/layout.css +192 -0
  447. package/templates/startkit/src/styles/reset.css +38 -0
  448. package/templates/startkit/src/styles/theme.css +76 -0
  449. package/templates/startkit/src/styles/tokens.css +67 -0
  450. package/templates/startkit/src/styles.css +7 -0
  451. package/templates/startkit/src/toast.ts +55 -0
  452. package/templates/startkit/src/utils/join-classes.ts +4 -0
  453. package/templates/startkit/src/vite-env.d.ts +5 -0
  454. package/templates/startkit/tests/app.test.tsx +32 -0
  455. package/templates/startkit/tests/preferences.test.ts +43 -0
  456. package/templates/startkit/tests/resources.test.ts +82 -0
  457. package/templates/startkit/tsconfig.json +20 -0
  458. package/templates/startkit/tsconfig.node.json +10 -0
  459. package/templates/startkit/vite.config.ts +32 -0
  460. package/templates/startkit/vitest.config.ts +13 -0
@@ -0,0 +1,96 @@
1
+ # {{appName}} - SPA Template
2
+
3
+ A route-first Askr SPA built with `@askrjs/askr`, `@askrjs/ui`, `@askrjs/themes`, and `@askrjs/charts`.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npm install
9
+ npm run dev # Start dev server at http://localhost:5173
10
+ npm run build # Build for production
11
+ npm run preview # Preview production build
12
+ npm test # Run tests with Vitest
13
+ ```
14
+
15
+ ## Project Structure
16
+
17
+ ```
18
+ src/
19
+ |-- main.tsx # SPA boot and route manifest
20
+ |-- pages/
21
+ | |-- _routes.tsx # Top-level route branches
22
+ | |-- _layout.tsx # Theme provider and app root
23
+ | |-- public/ # Guest-facing landing pages and shell
24
+ | |-- auth/ # Sign-in routes and shell
25
+ | `-- app/ # Authenticated branch routes and shell
26
+ |-- components/shared/ # App-local wrappers around theme primitives
27
+ |-- features/operations/ # Product workflow queries and mutations
28
+ |-- adapters/ # API clients and transport adapters
29
+ |-- shared/ # Cross-cutting helpers and navigation data
30
+ `-- styles/ # reset.css, tokens.css, theme.css, layout.css, components.css
31
+ ```
32
+
33
+ ## Core Patterns
34
+
35
+ Routes live in `src/pages`, shells live in `_layout.tsx`, reusable UI lives in
36
+ `src/components/shared`, business workflows live in `src/features`, and adapter
37
+ code lives in `src/adapters`.
38
+
39
+ ```tsx
40
+ // src/pages/_routes.tsx
41
+ import { fallback, group, registerRoutes } from '@askrjs/askr/router';
42
+ import RootLayout from './_layout';
43
+ import NotFoundPage from './not-found';
44
+ import AuthLayout from './auth/_layout';
45
+ import { registerAuthRoutes } from './auth/_routes';
46
+ import AppLayout from './app/_layout';
47
+ import { registerAppRoutes } from './app/_routes';
48
+ import PublicLayout from './public/_layout';
49
+ import { registerPublicRoutes } from './public/_routes';
50
+
51
+ registerRoutes(() => {
52
+ group({ layout: RootLayout }, () => {
53
+ group({ layout: PublicLayout }, () => {
54
+ registerPublicRoutes();
55
+ });
56
+ group({ layout: AuthLayout }, () => {
57
+ registerAuthRoutes();
58
+ });
59
+ group({ layout: AppLayout }, () => {
60
+ registerAppRoutes();
61
+ });
62
+ fallback(NotFoundPage);
63
+ });
64
+ });
65
+ ```
66
+
67
+ The template uses the `@askrjs/themes/components` catalog for styled UI
68
+ composition and keeps charts in `@askrjs/charts`. Add app-local components only
69
+ when they compose those primitives into a product concept. Start with
70
+ `src/styles/tokens.css` for theme knobs, then tune `theme.css`, `layout.css`,
71
+ and `components.css`.
72
+
73
+ Async reads are owned by route or container components with `resource()` and
74
+ delegated through feature/adapters:
75
+
76
+ ```tsx
77
+ const operations = resource(({ signal }) => loadOperations({ signal }), []);
78
+ ```
79
+
80
+ Cancellation belongs in adapters, loading/error/value states stay visible in the
81
+ route, and event-sourced consistency states should be modeled explicitly.
82
+
83
+ ## What This Template Includes
84
+
85
+ - Public, auth, and authenticated app branches with separate layout shells
86
+ - Theme provider, header/nav/sidebar, cards, badges, buttons, empty states, and layout primitives
87
+ - A dashboard with async loading, charts, projection lag, and explicit refresh
88
+ - Feature and adapter boundaries for data ownership
89
+ - Tests that protect the route-first structure and cancellation behavior
90
+
91
+ ## Next Steps
92
+
93
+ 1. Replace the mock operations adapter with your generated API client.
94
+ 2. Tune `src/styles/tokens.css` and `src/styles/theme.css` to match your brand.
95
+ 3. Add route metadata for real auth and loader policies.
96
+ 4. Keep new screens route-first and compose solved UI through `@askrjs/themes`.
@@ -0,0 +1,16 @@
1
+ node_modules/
2
+ dist/
3
+ build/
4
+ .env.local
5
+ .env.*.local
6
+ npm-debug.log*
7
+ yarn-debug.log*
8
+ yarn-error.log*
9
+ pnpm-debug.log*
10
+ .DS_Store
11
+ Thumbs.db
12
+ .vscode/
13
+ .idea/
14
+ *.swp
15
+ *.swo
16
+ *~
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>{{appName}}</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "{{appName}}",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "clean": "npx rimraf node_modules dist",
7
+ "dev": "vp dev",
8
+ "build": "vp build",
9
+ "preview": "vp preview",
10
+ "test": "vp test run",
11
+ "typecheck": "tsc --noEmit",
12
+ "lint": "vp lint .",
13
+ "lint:fix": "npm run lint -- --fix",
14
+ "fmt": "vp fmt .",
15
+ "check": "npm run lint && npm run typecheck && npm test && npm run build"
16
+ },
17
+ "dependencies": {
18
+ "@askrjs/askr": ">=0.0.53 <0.1.0",
19
+ "@askrjs/charts": ">=0.0.3 <0.1.0",
20
+ "@askrjs/logos": ">=0.0.3 <0.1.0",
21
+ "@askrjs/lucide": ">=0.0.3 <0.1.0",
22
+ "@askrjs/themes": ">=0.0.12 <0.1.0",
23
+ "@askrjs/ui": ">=0.0.13 <0.1.0"
24
+ },
25
+ "devDependencies": {
26
+ "@askrjs/vite": ">=0.0.6 <0.1.0",
27
+ "@types/node": "^26.0.0",
28
+ "jsdom": "^29.1.1",
29
+ "typescript": "^6.0.3",
30
+ "vite-plus": "^0.2.4"
31
+ },
32
+ "engines": {
33
+ "node": "^20.19.0 || >=22.12.0"
34
+ }
35
+ }
@@ -0,0 +1,90 @@
1
+ import type { RunStatus } from '../components/shared/status-badge';
2
+
3
+ export type OperationRun = {
4
+ id: string;
5
+ title: string;
6
+ status: RunStatus;
7
+ owner: string;
8
+ updatedAt: string;
9
+ };
10
+
11
+ export type OperationsSnapshot = {
12
+ version: number;
13
+ consistency: 'fresh' | 'pending-write' | 'stale';
14
+ lastEventId: string;
15
+ metrics: Array<{ label: string; value: string; trend: string }>;
16
+ throughput: Array<{ label: string; value: number }>;
17
+ lag: Array<{ label: string; value: number }>;
18
+ runs: OperationRun[];
19
+ };
20
+
21
+ export async function getOperationsSnapshot({
22
+ signal,
23
+ }: {
24
+ signal: AbortSignal;
25
+ }): Promise<OperationsSnapshot> {
26
+ await delay(220, signal);
27
+
28
+ return {
29
+ version: 42,
30
+ consistency: 'fresh',
31
+ lastEventId: 'evt_18442',
32
+ metrics: [
33
+ { label: 'Active runs', value: '12', trend: '+3 today' },
34
+ { label: 'Pending approvals', value: '3', trend: '2 urgent' },
35
+ { label: 'Projection lag', value: '1.2s', trend: 'healthy' },
36
+ ],
37
+ throughput: [
38
+ { label: 'Research', value: 18 },
39
+ { label: 'Review', value: 11 },
40
+ { label: 'Deploy', value: 7 },
41
+ { label: 'Audit', value: 9 },
42
+ ],
43
+ lag: [
44
+ { label: '10:00', value: 4 },
45
+ { label: '10:10', value: 3 },
46
+ { label: '10:20', value: 2 },
47
+ { label: '10:30', value: 1 },
48
+ { label: '10:40', value: 2 },
49
+ { label: '10:50', value: 1 },
50
+ ],
51
+ runs: [
52
+ {
53
+ id: 'run_4812',
54
+ title: 'Summarize renewal risk',
55
+ status: 'running',
56
+ owner: 'Revenue ops',
57
+ updatedAt: '2026-05-22T09:52:00.000Z',
58
+ },
59
+ {
60
+ id: 'run_4811',
61
+ title: 'Approve workspace migration',
62
+ status: 'requires-action',
63
+ owner: 'Platform',
64
+ updatedAt: '2026-05-22T09:40:00.000Z',
65
+ },
66
+ {
67
+ id: 'run_4810',
68
+ title: 'Reconcile audit events',
69
+ status: 'succeeded',
70
+ owner: 'Security',
71
+ updatedAt: '2026-05-22T09:25:00.000Z',
72
+ },
73
+ ],
74
+ };
75
+ }
76
+
77
+ function delay(ms: number, signal: AbortSignal): Promise<void> {
78
+ return new Promise((resolve, reject) => {
79
+ const timeout = globalThis.setTimeout(resolve, ms);
80
+
81
+ signal.addEventListener(
82
+ 'abort',
83
+ () => {
84
+ globalThis.clearTimeout(timeout);
85
+ reject(new DOMException('Operation aborted', 'AbortError'));
86
+ },
87
+ { once: true }
88
+ );
89
+ });
90
+ }
@@ -0,0 +1,27 @@
1
+ import {
2
+ Card,
3
+ CardDescription,
4
+ CardHeader,
5
+ CardTitle,
6
+ } from '@askrjs/themes/components';
7
+ import { Inline } from '@askrjs/themes/components';
8
+
9
+ export type MetricCardProps = {
10
+ label: string;
11
+ value: string;
12
+ trend: string;
13
+ };
14
+
15
+ export default function MetricCard({ label, value, trend }: MetricCardProps) {
16
+ return (
17
+ <Card class="metric-card">
18
+ <CardHeader>
19
+ <Inline justify="between" align="center" gap="3">
20
+ <CardDescription>{label}</CardDescription>
21
+ <span class="metric-trend">{trend}</span>
22
+ </Inline>
23
+ <CardTitle>{value}</CardTitle>
24
+ </CardHeader>
25
+ </Card>
26
+ );
27
+ }
@@ -0,0 +1,24 @@
1
+ import { Badge } from '@askrjs/themes/components';
2
+
3
+ export type RunStatus =
4
+ | 'queued'
5
+ | 'running'
6
+ | 'requires-action'
7
+ | 'succeeded'
8
+ | 'failed';
9
+
10
+ export type StatusBadgeProps = {
11
+ status: RunStatus;
12
+ };
13
+
14
+ const labels: Record<RunStatus, string> = {
15
+ queued: 'queued',
16
+ running: 'running',
17
+ 'requires-action': 'needs review',
18
+ succeeded: 'succeeded',
19
+ failed: 'failed',
20
+ };
21
+
22
+ export default function StatusBadge({ status }: StatusBadgeProps) {
23
+ return <Badge data-status={status}>{labels[status]}</Badge>;
24
+ }
@@ -0,0 +1,9 @@
1
+ import { getOperationsSnapshot } from '../../adapters/operations-client';
2
+
3
+ export function loadOperations({
4
+ signal = new AbortController().signal,
5
+ }: {
6
+ signal?: AbortSignal;
7
+ }) {
8
+ return getOperationsSnapshot({ signal });
9
+ }
@@ -0,0 +1,10 @@
1
+ import { createSPA } from '@askrjs/askr/boot';
2
+ import { getManifest } from '@askrjs/askr/router';
3
+
4
+ import './styles.css';
5
+ import './pages/_routes';
6
+
7
+ await createSPA({
8
+ root: document.getElementById('app')!,
9
+ manifest: getManifest(),
10
+ });
@@ -0,0 +1,9 @@
1
+ import { ThemeScope } from '@askrjs/themes/theme';
2
+
3
+ export default function RootLayout({ children }: { children?: unknown }) {
4
+ return (
5
+ <ThemeScope defaultTheme="tabby">
6
+ <div class="app-root">{children}</div>
7
+ </ThemeScope>
8
+ );
9
+ }
@@ -0,0 +1,27 @@
1
+ import { fallback, group, registerRoutes } from '@askrjs/askr/router';
2
+ import RootLayout from './_layout';
3
+ import AuthLayout from './auth/_layout';
4
+ import { registerAuthRoutes } from './auth/_routes';
5
+ import { registerAppRoutes } from './app/_routes';
6
+ import AppLayout from './app/_layout';
7
+ import NotFoundPage from './not-found';
8
+ import { registerPublicRoutes } from './public/_routes';
9
+ import PublicLayout from './public/_layout';
10
+
11
+ registerRoutes(() => {
12
+ group({ layout: RootLayout }, () => {
13
+ group({ layout: PublicLayout }, () => {
14
+ registerPublicRoutes();
15
+ });
16
+
17
+ group({ layout: AuthLayout }, () => {
18
+ registerAuthRoutes();
19
+ });
20
+
21
+ group({ layout: AppLayout }, () => {
22
+ registerAppRoutes();
23
+ });
24
+
25
+ fallback(NotFoundPage);
26
+ });
27
+ });
@@ -0,0 +1,94 @@
1
+ import {
2
+ BotIcon,
3
+ HomeIcon,
4
+ LogOutIcon,
5
+ MoonIcon,
6
+ SettingsIcon,
7
+ SunIcon,
8
+ } from '@askrjs/lucide';
9
+ import { Link, navigate } from '@askrjs/askr/router';
10
+ import { Button } from '@askrjs/themes/components';
11
+ import { Container, Inline, Stack } from '@askrjs/themes/components';
12
+ import { Header, Shell, ShellMain, ShellNav } from '@askrjs/themes/components';
13
+ import {
14
+ NavBrand,
15
+ NavGroup,
16
+ NavLink,
17
+ Sidebar,
18
+ } from '@askrjs/themes/components';
19
+ import { Badge } from '@askrjs/themes/components';
20
+ import { ThemeToggle } from '@askrjs/themes/theme';
21
+ import { appNavItems } from '../../shared/navigation';
22
+
23
+ const icons = {
24
+ home: <HomeIcon size={16} aria-hidden="true" />,
25
+ agents: <BotIcon size={16} aria-hidden="true" />,
26
+ settings: <SettingsIcon size={16} aria-hidden="true" />,
27
+ };
28
+
29
+ export default function AppLayout({ children }: { children?: unknown }) {
30
+ return (
31
+ <Shell variant="sidebar" class="app-shell">
32
+ <ShellNav>
33
+ <Sidebar
34
+ aria-label="Workspace navigation"
35
+ breakpoint="md"
36
+ collapsible="icon"
37
+ >
38
+ <NavBrand>
39
+ <Link href="/app" class="brand-link">
40
+ <span class="brand-mark">A</span>
41
+ <strong>{'{{appName}}'}</strong>
42
+ </Link>
43
+ </NavBrand>
44
+ <NavGroup label="Workspace">
45
+ {appNavItems.map((item) => (
46
+ <NavLink href={item.href} match={item.match}>
47
+ <Inline as="span" gap="2" align="center">
48
+ {icons[item.icon]}
49
+ <span>{item.label}</span>
50
+ </Inline>
51
+ </NavLink>
52
+ ))}
53
+ </NavGroup>
54
+ <NavGroup label="Session" align="end">
55
+ <NavLink href="/" match="exact">
56
+ <Inline as="span" gap="2" align="center">
57
+ <LogOutIcon size={16} aria-hidden="true" />
58
+ <span>Sign out</span>
59
+ </Inline>
60
+ </NavLink>
61
+ </NavGroup>
62
+ </Sidebar>
63
+ </ShellNav>
64
+ <ShellMain>
65
+ <Header position="sticky" class="app-header">
66
+ <Container size="full">
67
+ <Inline justify="between" align="center" gap="3" wrap="wrap">
68
+ <Stack gap="none">
69
+ <span class="eyebrow">Operations console</span>
70
+ <strong>Agent workflow control plane</strong>
71
+ </Stack>
72
+ <Inline gap="2" align="center" wrap="wrap">
73
+ <Badge>event stream healthy</Badge>
74
+ <ThemeToggle
75
+ variant="ghost"
76
+ size="icon"
77
+ aria-label="Toggle color theme"
78
+ lightIcon={<SunIcon size={18} aria-hidden="true" />}
79
+ darkIcon={<MoonIcon size={18} aria-hidden="true" />}
80
+ />
81
+ <Button variant="secondary" onPress={() => navigate('/')}>
82
+ Public site
83
+ </Button>
84
+ </Inline>
85
+ </Inline>
86
+ </Container>
87
+ </Header>
88
+ <Container size="full" class="app-main">
89
+ {children}
90
+ </Container>
91
+ </ShellMain>
92
+ </Shell>
93
+ );
94
+ }
@@ -0,0 +1,10 @@
1
+ import { route } from '@askrjs/askr/router';
2
+ import AgentRunsPage from './agent-runs';
3
+ import AdminHomePage from './admin-home';
4
+ import SettingsPage from './settings';
5
+
6
+ export function registerAppRoutes(): void {
7
+ route('/app', AdminHomePage);
8
+ route('/app/agents', AgentRunsPage);
9
+ route('/app/settings', SettingsPage);
10
+ }
@@ -0,0 +1,152 @@
1
+ import { resource } from '@askrjs/askr/resources';
2
+ import { BarChart, Sparkline } from '@askrjs/charts/components';
3
+ import { AlertCircleIcon, RefreshCwIcon } from '@askrjs/lucide';
4
+ import { Button } from '@askrjs/themes/components';
5
+ import {
6
+ Alert,
7
+ Badge,
8
+ Card,
9
+ CardContent,
10
+ CardDescription,
11
+ CardHeader,
12
+ CardTitle,
13
+ Skeleton,
14
+ } from '@askrjs/themes/components';
15
+ import { Block, Inline, Section, Stack } from '@askrjs/themes/components';
16
+ import { EmptyState } from '@askrjs/themes/components';
17
+ import MetricCard from '../../components/shared/metric-card';
18
+ import StatusBadge from '../../components/shared/status-badge';
19
+ import { loadOperations } from '../../features/operations/operations.query';
20
+ import { formatRelativeTime } from '../../shared/format';
21
+
22
+ export default function AdminHomePage() {
23
+ const operations = resource(({ signal }) => loadOperations({ signal }), []);
24
+ const snapshot = operations.value;
25
+
26
+ if (operations.error && !snapshot) {
27
+ return (
28
+ <Section>
29
+ <EmptyState
30
+ icon={<AlertCircleIcon size={24} aria-hidden="true" />}
31
+ title="Operations could not load"
32
+ description="The dashboard keeps failures recoverable. Retry the owning resource instead of hiding the error in a toast."
33
+ actions={<Button onPress={() => operations.refresh()}>Retry</Button>}
34
+ />
35
+ </Section>
36
+ );
37
+ }
38
+
39
+ return (
40
+ <Stack gap="5">
41
+ <section class="page-heading">
42
+ <Stack gap="2">
43
+ <Badge>projection v{snapshot?.version ?? '...'}</Badge>
44
+ <h1>Workspace home</h1>
45
+ <p class="lead">
46
+ A consistency-aware dashboard for agent runs, queue health, and
47
+ event-sourced read models.
48
+ </p>
49
+ </Stack>
50
+ <Inline gap="2" align="center">
51
+ {operations.pending && snapshot ? <Badge>refreshing</Badge> : null}
52
+ <Button variant="secondary" onPress={() => operations.refresh()}>
53
+ <RefreshCwIcon size={14} aria-hidden="true" /> Refresh
54
+ </Button>
55
+ </Inline>
56
+ </section>
57
+
58
+ {operations.pending && !snapshot ? (
59
+ <Block gap="md">
60
+ <Skeleton style="height: 8rem" />
61
+ <Skeleton style="height: 8rem" />
62
+ <Skeleton style="height: 8rem" />
63
+ </Block>
64
+ ) : null}
65
+
66
+ {snapshot ? (
67
+ <>
68
+ <Block gap="md" class="metric-grid">
69
+ {snapshot.metrics.map((metric) => (
70
+ <MetricCard
71
+ label={metric.label}
72
+ value={metric.value}
73
+ trend={metric.trend}
74
+ />
75
+ ))}
76
+ </Block>
77
+
78
+ <Block gap="md" align="stretch" class="chart-grid">
79
+ <Card>
80
+ <CardHeader>
81
+ <CardTitle>Run throughput</CardTitle>
82
+ <CardDescription>
83
+ Accepted commands by work type.
84
+ </CardDescription>
85
+ </CardHeader>
86
+ <CardContent>
87
+ <BarChart label="Run throughput" data={snapshot.throughput} />
88
+ </CardContent>
89
+ </Card>
90
+ <Card>
91
+ <CardHeader>
92
+ <CardTitle>Projection lag</CardTitle>
93
+ <CardDescription>
94
+ Lower is better; stale states stay visible.
95
+ </CardDescription>
96
+ </CardHeader>
97
+ <CardContent>
98
+ <Sparkline label="Projection lag" data={snapshot.lag} />
99
+ </CardContent>
100
+ </Card>
101
+ </Block>
102
+
103
+ {snapshot.consistency !== 'fresh' ? (
104
+ <Alert variant="warning">
105
+ Read models are {snapshot.consistency}. Last processed event is{' '}
106
+ {snapshot.lastEventId}.
107
+ </Alert>
108
+ ) : null}
109
+
110
+ <Card>
111
+ <CardHeader>
112
+ <CardTitle>Recent agent runs</CardTitle>
113
+ <CardDescription>
114
+ Run state is modeled as product state, not a single loading
115
+ boolean.
116
+ </CardDescription>
117
+ </CardHeader>
118
+ <CardContent>
119
+ <div class="run-table-wrap">
120
+ <table class="run-table">
121
+ <thead>
122
+ <tr>
123
+ <th>Run</th>
124
+ <th>Status</th>
125
+ <th>Owner</th>
126
+ <th>Updated</th>
127
+ </tr>
128
+ </thead>
129
+ <tbody>
130
+ {snapshot.runs.map((run) => (
131
+ <tr>
132
+ <td>
133
+ <strong>{run.title}</strong>
134
+ <span>{run.id}</span>
135
+ </td>
136
+ <td>
137
+ <StatusBadge status={run.status} />
138
+ </td>
139
+ <td>{run.owner}</td>
140
+ <td>{formatRelativeTime(run.updatedAt)}</td>
141
+ </tr>
142
+ ))}
143
+ </tbody>
144
+ </table>
145
+ </div>
146
+ </CardContent>
147
+ </Card>
148
+ </>
149
+ ) : null}
150
+ </Stack>
151
+ );
152
+ }