@askrjs/cli 0.0.2 → 0.0.4

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 (310) hide show
  1. package/README.md +46 -7
  2. package/dist/add.d.ts +16 -0
  3. package/dist/add.js +558 -1
  4. package/dist/cli.d.ts +5 -0
  5. package/dist/cli.js +43 -16
  6. package/dist/create.d.ts +5 -0
  7. package/dist/create.js +104 -26
  8. package/dist/directory-swap-DWoHtx7C.js +35 -0
  9. package/dist/discovery-Difb7Y4G.js +323 -0
  10. package/dist/generate.d.ts +5 -0
  11. package/dist/generate.js +461 -0
  12. package/dist/is-direct-execution-Cdlr-ZUl.js +0 -2
  13. package/dist/openapi.d.ts +25 -0
  14. package/dist/openapi.js +49 -16
  15. package/dist/planner-VAj7qlxr.js +285 -0
  16. package/dist/range-YUs9eimn.js +125 -0
  17. package/dist/registry-CyrRHRG5.js +209 -0
  18. package/dist/skills/askr-dashboard-charts/SKILL.md +61 -44
  19. package/dist/skills/askr-dashboard-charts/agents/openai.yaml +2 -2
  20. package/dist/skills/askr-ssr-ssg/SKILL.md +3 -1
  21. package/dist/{skills-Bh0mEhIx.js → skills-B7CbWur9.js} +89 -26
  22. package/dist/skills.d.ts +18 -0
  23. package/dist/skills.js +1 -1
  24. package/dist/specification-DXnDOC-0.js +49 -0
  25. package/dist/ssg-config.d.ts +41 -0
  26. package/dist/ssg-config.js +1 -0
  27. package/dist/ssg.d.ts +61 -0
  28. package/dist/ssg.js +360 -24
  29. package/dist/templates/full-stack/AGENTS.md +0 -1
  30. package/dist/templates/full-stack/README.md +0 -1
  31. package/dist/templates/full-stack/index.html +0 -1
  32. package/dist/templates/full-stack/package.json +5 -3
  33. package/dist/templates/full-stack/server.ts +5 -9
  34. package/dist/templates/full-stack/src/action-authorizations.ts +2 -2
  35. package/dist/templates/full-stack/src/actions/create-message.ts +5 -5
  36. package/dist/templates/full-stack/src/i18n.ts +4 -4
  37. package/dist/templates/full-stack/src/main.tsx +4 -5
  38. package/dist/templates/full-stack/src/pages/home.tsx +5 -5
  39. package/dist/templates/full-stack/src/pages/layout.tsx +15 -5
  40. package/dist/templates/full-stack/src/pages/not-found.tsx +5 -2
  41. package/dist/templates/full-stack/src/routes.tsx +11 -12
  42. package/dist/templates/full-stack/src/schemas.ts +1 -2
  43. package/dist/templates/full-stack/src/server/action-registry.ts +5 -10
  44. package/dist/templates/full-stack/src/server/actions/create-message.ts +4 -4
  45. package/dist/templates/full-stack/src/server/app.ts +67 -57
  46. package/dist/templates/full-stack/src/server/dependencies.ts +10 -10
  47. package/dist/templates/full-stack/src/server/entry-server.ts +3 -3
  48. package/dist/templates/full-stack/src/telemetry.ts +1 -2
  49. package/dist/templates/full-stack/tests/actions/create-message.test.ts +7 -8
  50. package/dist/templates/full-stack/tsconfig.json +1 -2
  51. package/dist/templates/full-stack/vite.config.ts +5 -6
  52. package/dist/templates/spa/AGENTS.md +1 -1
  53. package/dist/templates/spa/package.json +3 -4
  54. package/dist/templates/spa/src/adapters/operations-client.ts +7 -2
  55. package/dist/templates/spa/src/pages/app/_routes.tsx +2 -0
  56. package/dist/templates/spa/src/pages/app/admin-home.tsx +21 -3
  57. package/dist/templates/spa/src/pages/public/_routes.tsx +2 -0
  58. package/dist/templates/spa/src/styles.css +1 -1
  59. package/dist/templates/spa/tsconfig.json +2 -1
  60. package/dist/templates/spa/vitest.config.ts +0 -4
  61. package/dist/templates/ssg/README.md +1 -1
  62. package/dist/templates/ssg/package.json +1 -1
  63. package/dist/templates/ssg/ssg.config.ts +7 -0
  64. package/dist/templates/ssg/tests/ssg-config.test.ts +5 -3
  65. package/dist/templates/ssg/tsconfig.json +2 -1
  66. package/dist/templates/ssg/vitest.config.ts +0 -4
  67. package/dist/templates/ssr/package.json +2 -2
  68. package/dist/templates/ssr/server.ts +4 -10
  69. package/dist/templates/ssr/src/entry-server.tsx +6 -4
  70. package/dist/templates/startkit/package.json +2 -2
  71. package/dist/templates/startkit/src/lib/mock-data.ts +17 -39
  72. package/dist/templates/startkit/tsconfig.json +2 -1
  73. package/dist/update.d.ts +41 -0
  74. package/dist/update.js +282 -2
  75. package/dist/writer-D8qe_7ud.js +226 -0
  76. package/package.json +23 -22
  77. package/dist/add-DqhqRzBQ.js +0 -555
  78. package/dist/add-DqhqRzBQ.js.map +0 -1
  79. package/dist/cli.js.map +0 -1
  80. package/dist/create.js.map +0 -1
  81. package/dist/is-direct-execution-Cdlr-ZUl.js.map +0 -1
  82. package/dist/openapi.js.map +0 -1
  83. package/dist/skills-Bh0mEhIx.js.map +0 -1
  84. package/dist/ssg.js.map +0 -1
  85. package/dist/templates/full-stack/src/vite-server.d.ts +0 -6
  86. package/dist/templates/spa/src/styles.d.ts +0 -1
  87. package/dist/templates/ssg/src/vite-env.d.ts +0 -5
  88. package/dist/templates/ssr/src/vite-server.d.ts +0 -7
  89. package/dist/templates/startkit/src/vite-env.d.ts +0 -5
  90. package/dist/update-DyW1na5V.js +0 -1140
  91. package/dist/update-DyW1na5V.js.map +0 -1
  92. package/skills/askr-accessibility/SKILL.md +0 -68
  93. package/skills/askr-accessibility/agents/openai.yaml +0 -4
  94. package/skills/askr-agent-execution/SKILL.md +0 -85
  95. package/skills/askr-agent-execution/agents/openai.yaml +0 -4
  96. package/skills/askr-agent-workflows/SKILL.md +0 -57
  97. package/skills/askr-agent-workflows/agents/openai.yaml +0 -4
  98. package/skills/askr-api-integration/SKILL.md +0 -79
  99. package/skills/askr-api-integration/agents/openai.yaml +0 -4
  100. package/skills/askr-app-builder/SKILL.md +0 -99
  101. package/skills/askr-app-builder/agents/openai.yaml +0 -4
  102. package/skills/askr-auth-access/SKILL.md +0 -74
  103. package/skills/askr-auth-access/agents/openai.yaml +0 -4
  104. package/skills/askr-cli-vite/SKILL.md +0 -76
  105. package/skills/askr-cli-vite/agents/openai.yaml +0 -4
  106. package/skills/askr-dashboard-charts/SKILL.md +0 -82
  107. package/skills/askr-dashboard-charts/agents/openai.yaml +0 -4
  108. package/skills/askr-design-system/SKILL.md +0 -86
  109. package/skills/askr-design-system/agents/openai.yaml +0 -4
  110. package/skills/askr-env-config/SKILL.md +0 -74
  111. package/skills/askr-env-config/agents/openai.yaml +0 -4
  112. package/skills/askr-error-loading-empty/SKILL.md +0 -89
  113. package/skills/askr-error-loading-empty/agents/openai.yaml +0 -4
  114. package/skills/askr-file-upload-artifacts/SKILL.md +0 -77
  115. package/skills/askr-file-upload-artifacts/agents/openai.yaml +0 -4
  116. package/skills/askr-forms-tables-crud/SKILL.md +0 -98
  117. package/skills/askr-forms-tables-crud/agents/openai.yaml +0 -4
  118. package/skills/askr-mental-model/SKILL.md +0 -109
  119. package/skills/askr-mental-model/agents/openai.yaml +0 -4
  120. package/skills/askr-migration-react/SKILL.md +0 -81
  121. package/skills/askr-migration-react/agents/openai.yaml +0 -4
  122. package/skills/askr-observability-debugging/SKILL.md +0 -83
  123. package/skills/askr-observability-debugging/agents/openai.yaml +0 -4
  124. package/skills/askr-project-structure/SKILL.md +0 -79
  125. package/skills/askr-project-structure/agents/openai.yaml +0 -4
  126. package/skills/askr-query-mutation/SKILL.md +0 -115
  127. package/skills/askr-query-mutation/agents/openai.yaml +0 -4
  128. package/skills/askr-realtime-streaming/SKILL.md +0 -76
  129. package/skills/askr-realtime-streaming/agents/openai.yaml +0 -4
  130. package/skills/askr-resources-data/SKILL.md +0 -100
  131. package/skills/askr-resources-data/agents/openai.yaml +0 -4
  132. package/skills/askr-routing-layouts/SKILL.md +0 -107
  133. package/skills/askr-routing-layouts/agents/openai.yaml +0 -4
  134. package/skills/askr-runtime-reactivity/SKILL.md +0 -92
  135. package/skills/askr-runtime-reactivity/agents/openai.yaml +0 -4
  136. package/skills/askr-ssr-ssg/SKILL.md +0 -76
  137. package/skills/askr-ssr-ssg/agents/openai.yaml +0 -4
  138. package/skills/askr-testing-determinism/SKILL.md +0 -75
  139. package/skills/askr-testing-determinism/agents/openai.yaml +0 -4
  140. package/skills/askr-theming/SKILL.md +0 -86
  141. package/skills/askr-theming/agents/openai.yaml +0 -4
  142. package/skills/askr-ui-composition/SKILL.md +0 -92
  143. package/skills/askr-ui-composition/agents/openai.yaml +0 -4
  144. package/templates/full-stack/AGENTS.md +0 -12
  145. package/templates/full-stack/README.md +0 -18
  146. package/templates/full-stack/gitignore.template +0 -4
  147. package/templates/full-stack/index.html +0 -14
  148. package/templates/full-stack/package.json +0 -37
  149. package/templates/full-stack/server.ts +0 -13
  150. package/templates/full-stack/src/action-authorizations.ts +0 -10
  151. package/templates/full-stack/src/actions/create-message.ts +0 -10
  152. package/templates/full-stack/src/i18n.ts +0 -8
  153. package/templates/full-stack/src/main.tsx +0 -12
  154. package/templates/full-stack/src/pages/home.tsx +0 -25
  155. package/templates/full-stack/src/pages/layout.tsx +0 -33
  156. package/templates/full-stack/src/pages/not-found.tsx +0 -4
  157. package/templates/full-stack/src/routes.tsx +0 -20
  158. package/templates/full-stack/src/schemas.ts +0 -11
  159. package/templates/full-stack/src/server/action-registry.ts +0 -12
  160. package/templates/full-stack/src/server/actions/create-message.ts +0 -14
  161. package/templates/full-stack/src/server/app.ts +0 -66
  162. package/templates/full-stack/src/server/dependencies.ts +0 -55
  163. package/templates/full-stack/src/server/entry-server.ts +0 -8
  164. package/templates/full-stack/src/telemetry.ts +0 -4
  165. package/templates/full-stack/src/vite-server.d.ts +0 -6
  166. package/templates/full-stack/tests/actions/create-message.test.ts +0 -13
  167. package/templates/full-stack/tsconfig.json +0 -16
  168. package/templates/full-stack/vite.config.ts +0 -11
  169. package/templates/spa/AGENTS.md +0 -60
  170. package/templates/spa/README.md +0 -96
  171. package/templates/spa/gitignore.template +0 -16
  172. package/templates/spa/index.html +0 -13
  173. package/templates/spa/package.json +0 -35
  174. package/templates/spa/src/adapters/operations-client.ts +0 -90
  175. package/templates/spa/src/components/shared/metric-card.tsx +0 -27
  176. package/templates/spa/src/components/shared/status-badge.tsx +0 -24
  177. package/templates/spa/src/features/operations/operations.query.ts +0 -9
  178. package/templates/spa/src/main.tsx +0 -10
  179. package/templates/spa/src/pages/_layout.tsx +0 -9
  180. package/templates/spa/src/pages/_routes.tsx +0 -27
  181. package/templates/spa/src/pages/app/_layout.tsx +0 -94
  182. package/templates/spa/src/pages/app/_routes.tsx +0 -10
  183. package/templates/spa/src/pages/app/admin-home.tsx +0 -152
  184. package/templates/spa/src/pages/app/agent-runs.tsx +0 -93
  185. package/templates/spa/src/pages/app/settings.tsx +0 -91
  186. package/templates/spa/src/pages/auth/_layout.tsx +0 -38
  187. package/templates/spa/src/pages/auth/_routes.tsx +0 -6
  188. package/templates/spa/src/pages/auth/login.tsx +0 -63
  189. package/templates/spa/src/pages/not-found.tsx +0 -22
  190. package/templates/spa/src/pages/public/_layout.tsx +0 -47
  191. package/templates/spa/src/pages/public/_routes.tsx +0 -6
  192. package/templates/spa/src/pages/public/home.tsx +0 -143
  193. package/templates/spa/src/shared/format.ts +0 -12
  194. package/templates/spa/src/shared/navigation.ts +0 -15
  195. package/templates/spa/src/styles/components.css +0 -49
  196. package/templates/spa/src/styles/layout.css +0 -192
  197. package/templates/spa/src/styles/reset.css +0 -44
  198. package/templates/spa/src/styles/theme.css +0 -57
  199. package/templates/spa/src/styles/tokens.css +0 -20
  200. package/templates/spa/src/styles.css +0 -7
  201. package/templates/spa/src/styles.d.ts +0 -1
  202. package/templates/spa/tests/app.test.tsx +0 -37
  203. package/templates/spa/tests/components/shared.test.tsx +0 -12
  204. package/templates/spa/tests/resources.test.ts +0 -22
  205. package/templates/spa/tsconfig.json +0 -20
  206. package/templates/spa/tsconfig.node.json +0 -10
  207. package/templates/spa/vite.config.ts +0 -24
  208. package/templates/spa/vitest.config.ts +0 -17
  209. package/templates/ssg/AGENTS.md +0 -55
  210. package/templates/ssg/README.md +0 -39
  211. package/templates/ssg/gitignore.template +0 -17
  212. package/templates/ssg/index.html +0 -13
  213. package/templates/ssg/package.json +0 -35
  214. package/templates/ssg/src/app.tsx +0 -14
  215. package/templates/ssg/src/components/badge.tsx +0 -3
  216. package/templates/ssg/src/components/counter.tsx +0 -30
  217. package/templates/ssg/src/components/site-shell.tsx +0 -111
  218. package/templates/ssg/src/jsx.d.ts +0 -23
  219. package/templates/ssg/src/main.tsx +0 -8
  220. package/templates/ssg/src/pages/about.tsx +0 -82
  221. package/templates/ssg/src/pages/content.tsx +0 -63
  222. package/templates/ssg/src/pages/example.tsx +0 -97
  223. package/templates/ssg/src/pages/home.tsx +0 -51
  224. package/templates/ssg/src/resources/user.ts +0 -15
  225. package/templates/ssg/src/routes.tsx +0 -15
  226. package/templates/ssg/src/styles.css +0 -89
  227. package/templates/ssg/src/vite-env.d.ts +0 -5
  228. package/templates/ssg/ssg.config.ts +0 -34
  229. package/templates/ssg/tests/app.test.tsx +0 -19
  230. package/templates/ssg/tests/components/counter.test.tsx +0 -18
  231. package/templates/ssg/tests/resources.test.ts +0 -11
  232. package/templates/ssg/tests/ssg-config.test.ts +0 -11
  233. package/templates/ssg/tsconfig.json +0 -20
  234. package/templates/ssg/tsconfig.node.json +0 -10
  235. package/templates/ssg/vite.config.ts +0 -24
  236. package/templates/ssg/vitest.config.ts +0 -17
  237. package/templates/ssr/AGENTS.md +0 -28
  238. package/templates/ssr/README.md +0 -38
  239. package/templates/ssr/gitignore.template +0 -16
  240. package/templates/ssr/index.html +0 -13
  241. package/templates/ssr/package.json +0 -34
  242. package/templates/ssr/server.ts +0 -16
  243. package/templates/ssr/src/app.tsx +0 -21
  244. package/templates/ssr/src/components/counter.tsx +0 -26
  245. package/templates/ssr/src/entry-server.tsx +0 -10
  246. package/templates/ssr/src/main.tsx +0 -11
  247. package/templates/ssr/src/pages/about.tsx +0 -75
  248. package/templates/ssr/src/pages/example.tsx +0 -113
  249. package/templates/ssr/src/pages/home.tsx +0 -56
  250. package/templates/ssr/src/resources/user.ts +0 -15
  251. package/templates/ssr/src/routes.tsx +0 -13
  252. package/templates/ssr/src/styles.css +0 -148
  253. package/templates/ssr/src/vite-server.d.ts +0 -7
  254. package/templates/ssr/tests/app.test.tsx +0 -24
  255. package/templates/ssr/tests/components/counter.test.tsx +0 -13
  256. package/templates/ssr/tests/resources.test.ts +0 -11
  257. package/templates/ssr/tsconfig.json +0 -22
  258. package/templates/ssr/tsconfig.node.json +0 -10
  259. package/templates/ssr/tsconfig.server.json +0 -15
  260. package/templates/ssr/vite.config.ts +0 -25
  261. package/templates/ssr/vitest.config.ts +0 -13
  262. package/templates/startkit/AGENTS.md +0 -77
  263. package/templates/startkit/README.md +0 -192
  264. package/templates/startkit/gitignore.template +0 -16
  265. package/templates/startkit/index.html +0 -13
  266. package/templates/startkit/package.json +0 -35
  267. package/templates/startkit/src/components/app-header.tsx +0 -93
  268. package/templates/startkit/src/components/app-sidebar.tsx +0 -95
  269. package/templates/startkit/src/components/data-table.tsx +0 -80
  270. package/templates/startkit/src/components/empty-state.tsx +0 -13
  271. package/templates/startkit/src/components/page-header.tsx +0 -23
  272. package/templates/startkit/src/components/stat-card.tsx +0 -24
  273. package/templates/startkit/src/features/accounts/account-filters.tsx +0 -61
  274. package/templates/startkit/src/features/accounts/account-table.tsx +0 -79
  275. package/templates/startkit/src/lib/format.ts +0 -31
  276. package/templates/startkit/src/lib/mock-data.ts +0 -441
  277. package/templates/startkit/src/lib/routes.ts +0 -116
  278. package/templates/startkit/src/main.tsx +0 -12
  279. package/templates/startkit/src/pages/_layout.tsx +0 -56
  280. package/templates/startkit/src/pages/auth/_layout.tsx +0 -7
  281. package/templates/startkit/src/pages/auth/login.tsx +0 -129
  282. package/templates/startkit/src/pages/home.tsx +0 -83
  283. package/templates/startkit/src/pages/not-found.tsx +0 -24
  284. package/templates/startkit/src/pages/workspace/_layout.tsx +0 -17
  285. package/templates/startkit/src/pages/workspace/accounts/index.tsx +0 -217
  286. package/templates/startkit/src/pages/workspace/dashboard.tsx +0 -118
  287. package/templates/startkit/src/pages/workspace/settings.tsx +0 -218
  288. package/templates/startkit/src/router.tsx +0 -7
  289. package/templates/startkit/src/routes/auth-config.ts +0 -38
  290. package/templates/startkit/src/routes/auth.ts +0 -8
  291. package/templates/startkit/src/routes/index.ts +0 -28
  292. package/templates/startkit/src/routes/public.ts +0 -8
  293. package/templates/startkit/src/routes/workspace/accounts.ts +0 -8
  294. package/templates/startkit/src/routes/workspace/index.ts +0 -14
  295. package/templates/startkit/src/styles/components.css +0 -396
  296. package/templates/startkit/src/styles/layout.css +0 -192
  297. package/templates/startkit/src/styles/reset.css +0 -38
  298. package/templates/startkit/src/styles/theme.css +0 -76
  299. package/templates/startkit/src/styles/tokens.css +0 -67
  300. package/templates/startkit/src/styles.css +0 -7
  301. package/templates/startkit/src/toast.ts +0 -55
  302. package/templates/startkit/src/utils/join-classes.ts +0 -4
  303. package/templates/startkit/src/vite-env.d.ts +0 -5
  304. package/templates/startkit/tests/app.test.tsx +0 -32
  305. package/templates/startkit/tests/preferences.test.ts +0 -43
  306. package/templates/startkit/tests/resources.test.ts +0 -82
  307. package/templates/startkit/tsconfig.json +0 -20
  308. package/templates/startkit/tsconfig.node.json +0 -10
  309. package/templates/startkit/vite.config.ts +0 -32
  310. package/templates/startkit/vitest.config.ts +0 -13
@@ -1,116 +0,0 @@
1
- export type AppRouteKind = 'public' | 'auth' | 'protected';
2
-
3
- export type AppRouteDefinition = {
4
- id: 'landing' | 'login' | 'dashboard' | 'accounts' | 'settings';
5
- href: string;
6
- label: string;
7
- navLabel: string;
8
- description: string;
9
- kind: AppRouteKind;
10
- };
11
-
12
- const appOrigin = 'https://{{appName}}.local';
13
-
14
- export const landingRoute: AppRouteDefinition = {
15
- id: 'landing',
16
- href: '/',
17
- label: 'Home',
18
- navLabel: 'Home',
19
- description: 'Marketing overview and entry points into the starter app.',
20
- kind: 'public',
21
- };
22
-
23
- export const loginRoute: AppRouteDefinition = {
24
- id: 'login',
25
- href: '/login',
26
- label: 'Login',
27
- navLabel: 'Sign in',
28
- description: 'Auth entry for the starter app.',
29
- kind: 'auth',
30
- };
31
-
32
- export const dashboardRoute: AppRouteDefinition = {
33
- id: 'dashboard',
34
- href: '/dashboard',
35
- label: 'Dashboard',
36
- navLabel: 'Dashboard',
37
- description: 'Overview of growth, usage, and recent workspace activity.',
38
- kind: 'protected',
39
- };
40
-
41
- export const accountsRoute: AppRouteDefinition = {
42
- id: 'accounts',
43
- href: '/accounts',
44
- label: 'Accounts',
45
- navLabel: 'Accounts',
46
- description: 'Search, filter, and manage account records.',
47
- kind: 'protected',
48
- };
49
-
50
- export const settingsRoute: AppRouteDefinition = {
51
- id: 'settings',
52
- href: '/settings',
53
- label: 'Settings',
54
- navLabel: 'Settings',
55
- description: 'Profile fields, preferences, and modal patterns.',
56
- kind: 'protected',
57
- };
58
-
59
- export const defaultProtectedRoute = dashboardRoute;
60
- export const protectedRoutes = [
61
- dashboardRoute,
62
- accountsRoute,
63
- settingsRoute,
64
- ] as const;
65
- export const workspaceRoutes = [...protectedRoutes] as const;
66
- export const routeCatalog = [
67
- landingRoute,
68
- loginRoute,
69
- ...protectedRoutes,
70
- ] as const;
71
-
72
- const routeByPath = new Map(routeCatalog.map((route) => [route.href, route]));
73
-
74
- function parseRouteTarget(target: string): URL | null {
75
- try {
76
- return new URL(target, appOrigin);
77
- } catch {
78
- return null;
79
- }
80
- }
81
-
82
- export function isProtectedRoute(pathname: string): boolean {
83
- return protectedRoutes.some((route) => route.href === pathname);
84
- }
85
-
86
- export function normalizeProtectedRouteTarget(
87
- target: string | null | undefined
88
- ): string {
89
- if (!target) {
90
- return defaultProtectedRoute.href;
91
- }
92
-
93
- const parsed = parseRouteTarget(target);
94
- if (
95
- !parsed ||
96
- parsed.origin !== appOrigin ||
97
- !isProtectedRoute(parsed.pathname)
98
- ) {
99
- return defaultProtectedRoute.href;
100
- }
101
-
102
- return `${parsed.pathname}${parsed.search}${parsed.hash}`;
103
- }
104
-
105
- export function buildLoginHref(nextTarget?: string | null): string {
106
- if (!nextTarget) {
107
- return loginRoute.href;
108
- }
109
-
110
- const target = normalizeProtectedRouteTarget(nextTarget);
111
- return `${loginRoute.href}?next=${encodeURIComponent(target)}`;
112
- }
113
-
114
- export function getRouteLabel(pathname: string): string {
115
- return routeByPath.get(pathname)?.label ?? 'Workspace';
116
- }
@@ -1,12 +0,0 @@
1
- import { createSPA } from '@askrjs/askr/boot';
2
- import { initializeAppSession } from './lib/mock-data';
3
- import { pageRegistry } from './router';
4
-
5
- initializeAppSession();
6
-
7
- // createSPA is async: it drains lazy() chunks, applies the registry,
8
- // resolves the initial route, and wires history navigation — all in one call.
9
- const root = document.getElementById('app');
10
- if (!root) throw new Error('Missing #app root element.');
11
-
12
- await createSPA({ root, registry: pageRegistry });
@@ -1,56 +0,0 @@
1
- import '../styles.css';
2
- import {
3
- ToastHost,
4
- Toast,
5
- ToastClose,
6
- ToastDescription,
7
- ToastTitle,
8
- ToastViewport,
9
- } from '@askrjs/ui/toast';
10
- import {
11
- clearToast,
12
- bindToast,
13
- setToastOpen,
14
- toastMessage,
15
- toastOpen,
16
- } from '../toast';
17
- import { state } from '@askrjs/askr';
18
-
19
- export default function App({ children }: { children?: unknown }) {
20
- const [messageState, setMessageState] = state(toastMessage());
21
- const [openState, setOpenState] = state(toastOpen());
22
-
23
- bindToast({
24
- setMessage: setMessageState,
25
- setOpen: setOpenState,
26
- });
27
-
28
- const messageTitle = () => messageState()?.title ?? '';
29
- const messageDescription = () => messageState()?.description;
30
-
31
- return (
32
- <ToastHost duration={2400}>
33
- <div class="app-root">{children}</div>
34
-
35
- <ToastViewport class="app-toast-viewport" />
36
- {messageState() && (
37
- <Toast
38
- open={openState()}
39
- onOpenChange={(open) => {
40
- setToastOpen(open);
41
- if (!open) {
42
- clearToast();
43
- }
44
- }}
45
- class="app-toast"
46
- >
47
- <ToastTitle>{messageTitle()}</ToastTitle>
48
- {messageDescription() && (
49
- <ToastDescription>{messageDescription()}</ToastDescription>
50
- )}
51
- <ToastClose aria-label="Dismiss notification">Dismiss</ToastClose>
52
- </Toast>
53
- )}
54
- </ToastHost>
55
- );
56
- }
@@ -1,7 +0,0 @@
1
- export default function AuthLayout(props: { children?: unknown }) {
2
- return (
3
- <div class="auth-layout-shell">
4
- <div class="auth-layout-card">{props.children}</div>
5
- </div>
6
- );
7
- }
@@ -1,129 +0,0 @@
1
- import { state } from '@askrjs/askr';
2
- import { Link, currentRoute, navigate } from '@askrjs/askr/router';
3
- import { Button } from '@askrjs/ui/button';
4
- import { Input } from '@askrjs/ui/input';
5
- import { Field } from '@askrjs/themes/components';
6
- import { LockKeyholeIcon, MailIcon } from '@askrjs/lucide';
7
- import { signIn } from '../../lib/mock-data';
8
- import {
9
- dashboardRoute,
10
- normalizeProtectedRouteTarget,
11
- } from '../../lib/routes';
12
- import { showToast } from '../../toast';
13
-
14
- export default function LoginPage() {
15
- const [emailState, setEmailState] = state('alex@example.com');
16
- const [passwordState, setPasswordState] = state('askr1234');
17
- const [errorTextState, setErrorTextState] = state('');
18
- const [submittingState, setSubmittingState] = state(false);
19
- const routeSnapshot = currentRoute();
20
-
21
- const redirectTarget = () =>
22
- normalizeProtectedRouteTarget(routeSnapshot.query.get('next')) ||
23
- dashboardRoute.href;
24
-
25
- const validate = () => {
26
- if (!emailState().trim().includes('@')) {
27
- return 'Enter a valid email address.';
28
- }
29
-
30
- if (passwordState().trim().length < 8) {
31
- return 'Password must be at least 8 characters.';
32
- }
33
-
34
- return '';
35
- };
36
-
37
- const submit = async (event: Event) => {
38
- event.preventDefault();
39
-
40
- const validationError = validate();
41
- if (validationError) {
42
- setErrorTextState(validationError);
43
- return;
44
- }
45
-
46
- setSubmittingState(true);
47
- setErrorTextState('');
48
-
49
- try {
50
- await signIn({ email: emailState(), password: passwordState() });
51
- showToast({
52
- title: 'Signed in',
53
- description: 'Welcome back. You can now access protected routes.',
54
- });
55
- navigate(redirectTarget(), { history: 'replace' });
56
- } catch (error) {
57
- setErrorTextState(
58
- error instanceof Error ? error.message : 'Could not sign in.'
59
- );
60
- setSubmittingState(false);
61
- }
62
- };
63
-
64
- return (
65
- <section class="auth-page panel">
66
- <h1>Sign in</h1>
67
- <p>Use your workspace account to continue.</p>
68
-
69
- <form class="auth-form" onSubmit={submit}>
70
- <Field id="login-email">
71
- <label htmlFor="login-email">Email</label>
72
- <label class="input-row">
73
- <MailIcon size={15} aria-hidden="true" />
74
- <Input
75
- type="email"
76
- id="login-email"
77
- value={emailState()}
78
- onInput={(event: Event) =>
79
- setEmailState((event.target as HTMLInputElement).value)
80
- }
81
- />
82
- </label>
83
- </Field>
84
-
85
- <Field id="login-password">
86
- <label htmlFor="login-password">Password</label>
87
- <label class="input-row">
88
- <LockKeyholeIcon size={15} aria-hidden="true" />
89
- <Input
90
- type="password"
91
- id="login-password"
92
- value={passwordState()}
93
- onInput={(event: Event) =>
94
- setPasswordState((event.target as HTMLInputElement).value)
95
- }
96
- />
97
- </label>
98
- </Field>
99
-
100
- {errorTextState() && (
101
- <p class="field-error" role="alert">
102
- {errorTextState()}
103
- </p>
104
- )}
105
-
106
- <Button type="submit" disabled={submittingState()}>
107
- {submittingState() ? 'Signing in...' : 'Sign in'}
108
- </Button>
109
- </form>
110
-
111
- <div class="auth-links">
112
- <Link href="/">Back to landing</Link>
113
- <button
114
- type="button"
115
- class="link-button"
116
- onClick={() =>
117
- showToast({
118
- title: 'Reset link sent',
119
- description:
120
- 'This is a starter example. Replace with your auth flow.',
121
- })
122
- }
123
- >
124
- Forgot password?
125
- </button>
126
- </div>
127
- </section>
128
- );
129
- }
@@ -1,83 +0,0 @@
1
- import { Link } from '@askrjs/askr/router';
2
- import {
3
- ShieldCheckIcon,
4
- WorkflowIcon,
5
- LayoutPanelTopIcon,
6
- SparklesIcon,
7
- } from '@askrjs/lucide';
8
- import { dashboardRoute, loginRoute } from '../lib/routes';
9
-
10
- const navButtonClass = 'button button-secondary';
11
-
12
- export default function LandingPage() {
13
- return (
14
- <section class="marketing-page">
15
- <header class="marketing-header">
16
- <Link href="/" class="brand-link">
17
- <span class="brand-pill" aria-hidden="true">
18
- A
19
- </span>
20
- <strong>{'{{appName}}'}</strong>
21
- </Link>
22
- <div class="marketing-actions">
23
- <Link href={loginRoute.href} class={navButtonClass}>
24
- {loginRoute.navLabel}
25
- </Link>
26
- </div>
27
- </header>
28
-
29
- <div class="hero-block panel">
30
- <p class="eyebrow">Production-ready starter</p>
31
- <h1>Build your Askr app like a real product from day one.</h1>
32
- <p>
33
- This starter combines Askr, askr-ui, askr-themes, and lucide icons in
34
- a practical SaaS baseline with semantic pages, composed route trees,
35
- and shared layouts.
36
- </p>
37
- <div class="hero-cta">
38
- <Link href={dashboardRoute.href} class="button">
39
- Open dashboard
40
- </Link>
41
- <Link href={loginRoute.href} class={navButtonClass}>
42
- Try login flow
43
- </Link>
44
- </div>
45
- </div>
46
-
47
- <section class="feature-grid">
48
- <article class="panel feature-card">
49
- <WorkflowIcon size={18} aria-hidden="true" />
50
- <h2>Composed routes</h2>
51
- <p>
52
- Public, auth, protected, and 404 routes are assembled from small
53
- child route modules instead of one large router file.
54
- </p>
55
- </article>
56
- <article class="panel feature-card">
57
- <LayoutPanelTopIcon size={18} aria-hidden="true" />
58
- <h2>Composed UI patterns</h2>
59
- <p>
60
- Reusable table, headers, empty states, stat cards, sidebar, and top
61
- app header.
62
- </p>
63
- </article>
64
- <article class="panel feature-card">
65
- <ShieldCheckIcon size={18} aria-hidden="true" />
66
- <h2>State and data flow</h2>
67
- <p>
68
- Deterministic mock data with loading, empty, error, and mutation
69
- states.
70
- </p>
71
- </article>
72
- <article class="panel feature-card">
73
- <SparklesIcon size={18} aria-hidden="true" />
74
- <h2>Calm visual baseline</h2>
75
- <p>
76
- CSS token system, neutral palette, one accent color, and restrained
77
- depth.
78
- </p>
79
- </article>
80
- </section>
81
- </section>
82
- );
83
- }
@@ -1,24 +0,0 @@
1
- import { Link } from '@askrjs/askr/router';
2
-
3
- const navButtonClass = 'button button-secondary';
4
-
5
- export default function NotFoundPage() {
6
- return (
7
- <section class="not-found-page panel">
8
- <p class="eyebrow">404</p>
9
- <h1>Page not found</h1>
10
- <p>
11
- The route you requested is not mapped in this starter. Use this page to
12
- wire your own fallback analytics and recovery flow.
13
- </p>
14
- <div class="hero-cta">
15
- <Link href="/dashboard" class="button">
16
- Go to dashboard
17
- </Link>
18
- <Link href="/" class={navButtonClass}>
19
- Back to landing
20
- </Link>
21
- </div>
22
- </section>
23
- );
24
- }
@@ -1,17 +0,0 @@
1
- import { Shell, ShellMain, ShellNav } from '@askrjs/themes/components';
2
- import AppHeader from '../../components/app-header';
3
- import AppSidebar from '../../components/app-sidebar';
4
-
5
- export default function AppLayout(props: { children?: unknown }) {
6
- return (
7
- <Shell variant="sidebar" class="app-shell">
8
- <ShellNav class="app-shell-nav">
9
- <AppSidebar />
10
- </ShellNav>
11
- <ShellMain class="app-shell-main">
12
- <AppHeader />
13
- <div class="app-main">{props.children}</div>
14
- </ShellMain>
15
- </Shell>
16
- );
17
- }
@@ -1,217 +0,0 @@
1
- import { state } from '@askrjs/askr';
2
- import { resource } from '@askrjs/askr/resources';
3
- import {
4
- AlertDialog,
5
- AlertDialogAction,
6
- AlertDialogCancel,
7
- AlertDialogContent,
8
- AlertDialogDescription,
9
- AlertDialogOverlay,
10
- AlertDialogPortal,
11
- AlertDialogTitle,
12
- AlertDialogTrigger,
13
- } from '@askrjs/ui/alert-dialog';
14
- import { Button } from '@askrjs/ui/button';
15
- import {
16
- Inline,
17
- Pagination,
18
- PaginationContent,
19
- PaginationItem,
20
- } from '@askrjs/themes/components';
21
- import { ArchiveIcon, PlusIcon } from '@askrjs/lucide';
22
- import PageHeader from '../../../components/page-header';
23
- import AccountFilters from '../../../features/accounts/account-filters';
24
- import AccountTable from '../../../features/accounts/account-table';
25
- import {
26
- archiveAccounts,
27
- listAccounts,
28
- type AccountRecord,
29
- type AccountStatus,
30
- } from '../../../lib/mock-data';
31
- import { showToast } from '../../../toast';
32
-
33
- export default function AccountsPage() {
34
- const [queryState, setQueryState] = state('');
35
- const [statusState, setStatusState] = state<AccountStatus | 'all'>('all');
36
- const [pageState, setPageState] = state(1);
37
- const [selectedIdsState, setSelectedIdsState] = state<string[]>([]);
38
- const [archivingState, setArchivingState] = state(false);
39
-
40
- const pageSize = 5;
41
-
42
- const accountsResource = resource(
43
- async ({ signal }) =>
44
- listAccounts({
45
- signal,
46
- query: queryState(),
47
- status: statusState(),
48
- page: pageState(),
49
- pageSize,
50
- }),
51
- [queryState(), statusState(), pageState()]
52
- );
53
-
54
- const rows = () => accountsResource.value?.items ?? [];
55
- const totalPages = () => accountsResource.value?.totalPages ?? 1;
56
-
57
- const toggleRow = (id: string) => {
58
- setSelectedIdsState((current) =>
59
- current.includes(id)
60
- ? current.filter((value) => value !== id)
61
- : [...current, id]
62
- );
63
- };
64
-
65
- const resetFilters = () => {
66
- setQueryState('');
67
- setStatusState('all');
68
- setPageState(1);
69
- };
70
-
71
- const openRow = (row: AccountRecord) => {
72
- showToast({
73
- title: row.name,
74
- description: `Open account ${row.id} details in your real product workflow.`,
75
- });
76
- };
77
-
78
- const archiveSelected = async () => {
79
- if (selectedIdsState().length === 0) {
80
- return;
81
- }
82
-
83
- setArchivingState(true);
84
-
85
- try {
86
- const result = await archiveAccounts({ ids: selectedIdsState() });
87
- setSelectedIdsState([]);
88
- showToast({
89
- title: 'Accounts archived',
90
- description: `${result.archived} account records moved to archived status.`,
91
- });
92
- await accountsResource.refresh();
93
- } catch (error) {
94
- showToast({
95
- title: 'Archive failed',
96
- description:
97
- error instanceof Error
98
- ? error.message
99
- : 'Could not archive selected rows.',
100
- });
101
- } finally {
102
- setArchivingState(false);
103
- }
104
- };
105
-
106
- return (
107
- <section class="stack-lg">
108
- <PageHeader
109
- title="Accounts"
110
- description="Search, filter, page, and run row actions against account records."
111
- actions={
112
- <Button
113
- onPress={() =>
114
- showToast({
115
- title: 'Create account',
116
- description:
117
- 'Wire this button into your real create-account form flow.',
118
- })
119
- }
120
- >
121
- <PlusIcon size={14} aria-hidden="true" /> Add account
122
- </Button>
123
- }
124
- />
125
-
126
- <section class="panel stack-md">
127
- <AccountFilters
128
- query={queryState()}
129
- status={statusState()}
130
- onQueryChange={(next) => {
131
- setQueryState(next);
132
- setPageState(1);
133
- }}
134
- onStatusChange={(next) => {
135
- setStatusState(next);
136
- setPageState(1);
137
- }}
138
- onReset={resetFilters}
139
- />
140
-
141
- <AccountTable
142
- rows={rows}
143
- selectedIds={selectedIdsState}
144
- onToggleRow={toggleRow}
145
- onOpenRow={openRow}
146
- loading={accountsResource.pending && !accountsResource.value}
147
- errorText={accountsResource.error?.message ?? null}
148
- />
149
-
150
- <Inline align="center" gap="var(--ak-space-lg)" wrap="wrap">
151
- <span class="muted">{selectedIdsState().length} selected</span>
152
-
153
- <AlertDialog>
154
- <AlertDialogTrigger asChild>
155
- <Button
156
- disabled={selectedIdsState().length === 0}
157
- class="button-secondary"
158
- >
159
- <ArchiveIcon size={14} aria-hidden="true" /> Archive selected
160
- </Button>
161
- </AlertDialogTrigger>
162
- <AlertDialogPortal>
163
- <AlertDialogOverlay />
164
- <AlertDialogContent class="panel stack-md">
165
- <AlertDialogTitle>Archive selected accounts?</AlertDialogTitle>
166
- <AlertDialogDescription>
167
- This updates selected account records in the mock data source.
168
- </AlertDialogDescription>
169
- <div class="inline-end">
170
- <AlertDialogCancel asChild>
171
- <Button class="button-secondary">Cancel</Button>
172
- </AlertDialogCancel>
173
- <AlertDialogAction asChild>
174
- <Button
175
- onPress={() => void archiveSelected()}
176
- disabled={archivingState()}
177
- >
178
- {archivingState() ? 'Archiving...' : 'Confirm archive'}
179
- </Button>
180
- </AlertDialogAction>
181
- </div>
182
- </AlertDialogContent>
183
- </AlertDialogPortal>
184
- </AlertDialog>
185
-
186
- <Pagination aria-label="Accounts pages">
187
- <PaginationContent>
188
- <PaginationItem>
189
- <Button
190
- class="button-secondary"
191
- disabled={pageState() <= 1}
192
- onPress={() => setPageState((page) => page - 1)}
193
- >
194
- Previous
195
- </Button>
196
- </PaginationItem>
197
- <PaginationItem>
198
- <span aria-current="page">
199
- Page {pageState()} of {totalPages()}
200
- </span>
201
- </PaginationItem>
202
- <PaginationItem>
203
- <Button
204
- class="button-secondary"
205
- disabled={pageState() >= totalPages()}
206
- onPress={() => setPageState((page) => page + 1)}
207
- >
208
- Next
209
- </Button>
210
- </PaginationItem>
211
- </PaginationContent>
212
- </Pagination>
213
- </Inline>
214
- </section>
215
- </section>
216
- );
217
- }