create-aron-app 0.1.6 → 0.1.7

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 (260) hide show
  1. package/dist/index.js +50 -115
  2. package/package.json +5 -2
  3. package/templates/{_base/.cursor → .cursor}/rules/api_architecture.mdc +27 -33
  4. package/templates/{_base/.cursor → .cursor}/rules/coding_standards.mdc +1 -1
  5. package/templates/{_base/.cursor → .cursor}/rules/convex_rules.mdc +78 -422
  6. package/templates/.cursor/rules/frontend_architecture_core.mdc +495 -0
  7. package/templates/.cursor/rules/frontend_architecture_nextjs.mdc +458 -0
  8. package/templates/.cursor/rules/frontend_architecture_reactrouter.mdc +473 -0
  9. package/templates/apps/api/_generated/api.d.ts +57 -0
  10. package/templates/apps/api/_generated/api.js +23 -0
  11. package/templates/apps/api/_generated/dataModel.d.ts +60 -0
  12. package/templates/apps/api/_generated/server.d.ts +143 -0
  13. package/templates/apps/api/_generated/server.js +93 -0
  14. package/templates/apps/api/http.ts +16 -0
  15. package/templates/apps/nextjs/.env.example +10 -0
  16. package/templates/{nextjs → apps/nextjs}/project.json +5 -5
  17. package/templates/{nextjs → apps/nextjs}/src/app/(auth)/not-allowed/page.tsx +1 -0
  18. package/templates/apps/nextjs/src/app/(dashboard)/layout.tsx +22 -0
  19. package/templates/apps/nextjs/src/app/(dashboard)/page.tsx +12 -0
  20. package/templates/{nextjs → apps/nextjs}/src/app/(dashboard)/todos/[id]/page.tsx +5 -2
  21. package/templates/apps/nextjs/src/app/(dashboard)/todos/page.tsx +19 -0
  22. package/templates/apps/nextjs/src/middleware.ts +18 -0
  23. package/templates/apps/nextjs/src/surfaces/home/bootstrap.ts +9 -0
  24. package/templates/apps/nextjs/src/surfaces/home/home.tsx +27 -0
  25. package/templates/apps/nextjs/src/surfaces/home/install.tsx +17 -0
  26. package/templates/apps/nextjs/src/surfaces/home/layout.tsx +44 -0
  27. package/templates/apps/nextjs/src/surfaces/home/main/create.tsx +34 -0
  28. package/templates/apps/nextjs/src/surfaces/sidebar/install.tsx +23 -0
  29. package/templates/apps/nextjs/src/surfaces/sidebar/layout.tsx +118 -0
  30. package/templates/apps/nextjs/src/surfaces/sidebar/nav_main/create.tsx +19 -0
  31. package/templates/apps/nextjs/src/surfaces/sidebar/nav_main/nav_config.ts +22 -0
  32. package/templates/apps/nextjs/src/surfaces/sidebar/nav_main/nav_main.tsx +25 -0
  33. package/templates/apps/nextjs/src/surfaces/sidebar/nav_secondary/create.tsx +21 -0
  34. package/templates/apps/nextjs/src/surfaces/sidebar/nav_secondary/nav_secondary.tsx +33 -0
  35. package/templates/apps/nextjs/src/surfaces/sidebar/sidebar.tsx +23 -0
  36. package/templates/{nextjs/src/ui/sidebar/nav_link.tsx → apps/nextjs/src/surfaces/sidebar/ui/sidebar_nav_link.tsx} +13 -10
  37. package/templates/apps/nextjs/src/surfaces/sidebar/user_menu/create.tsx +28 -0
  38. package/templates/apps/nextjs/src/surfaces/sidebar/user_menu/user_menu.tsx +42 -0
  39. package/templates/apps/nextjs/src/surfaces/todos/all_todos/all_todos.tsx +29 -0
  40. package/templates/apps/nextjs/src/surfaces/todos/all_todos/all_todos_controller.ts +61 -0
  41. package/templates/apps/nextjs/src/surfaces/todos/all_todos/bootstrap.ts +21 -0
  42. package/templates/apps/nextjs/src/surfaces/todos/all_todos/header/create.tsx +23 -0
  43. package/templates/apps/nextjs/src/surfaces/todos/all_todos/install.tsx +23 -0
  44. package/templates/apps/nextjs/src/surfaces/todos/all_todos/layout.tsx +44 -0
  45. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/create.tsx +49 -0
  46. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/main.tsx +70 -0
  47. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/new_todo_sheet/create.tsx +56 -0
  48. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/new_todo_sheet/new_todo_sheet.tsx +99 -0
  49. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/new_todo_sheet/schema.ts +11 -0
  50. package/templates/apps/nextjs/src/surfaces/todos/single_todo/bootstrap.ts +32 -0
  51. package/templates/apps/nextjs/src/surfaces/todos/single_todo/header/create.tsx +26 -0
  52. package/templates/apps/nextjs/src/surfaces/todos/single_todo/header/header.tsx +22 -0
  53. package/templates/apps/nextjs/src/surfaces/todos/single_todo/install.tsx +27 -0
  54. package/templates/apps/nextjs/src/surfaces/todos/single_todo/layout.tsx +55 -0
  55. package/templates/apps/nextjs/src/surfaces/todos/single_todo/main/create.tsx +38 -0
  56. package/templates/apps/nextjs/src/surfaces/todos/single_todo/main/main.tsx +49 -0
  57. package/templates/apps/nextjs/src/surfaces/todos/single_todo/single_todo.tsx +29 -0
  58. package/templates/apps/nextjs/src/surfaces/todos/single_todo/single_todo_controller.ts +13 -0
  59. package/templates/apps/nextjs/src/utils/auth.ts +18 -0
  60. package/templates/apps/react-router/.env.example +10 -0
  61. package/templates/apps/react-router/.react-router/types/+future.ts +9 -0
  62. package/templates/apps/react-router/.react-router/types/+routes.ts +71 -0
  63. package/templates/apps/react-router/.react-router/types/+server-build.d.ts +18 -0
  64. package/templates/apps/react-router/.react-router/types/src/+types/root.ts +59 -0
  65. package/templates/apps/react-router/.react-router/types/src/routes/(auth)/+types/layout.ts +62 -0
  66. package/templates/apps/react-router/.react-router/types/src/routes/(auth)/sign-in/+types/index.ts +65 -0
  67. package/templates/apps/react-router/.react-router/types/src/routes/(dashboard)/+types/index.ts +65 -0
  68. package/templates/apps/react-router/.react-router/types/src/routes/(dashboard)/+types/layout.ts +62 -0
  69. package/templates/apps/react-router/.react-router/types/src/routes/(dashboard)/todos/+types/[id].ts +65 -0
  70. package/templates/apps/react-router/.react-router/types/src/routes/(dashboard)/todos/+types/index.ts +65 -0
  71. package/templates/{react-router → apps/react-router}/project.json +4 -4
  72. package/templates/apps/react-router/src/app.css +3 -0
  73. package/templates/{react-router → apps/react-router}/src/components/error_boundary.tsx +1 -1
  74. package/templates/{react-router → apps/react-router}/src/providers/api_auth_provider.tsx +2 -0
  75. package/templates/{react-router/src/routes/auth → apps/react-router/src/routes/(auth)}/layout.tsx +1 -1
  76. package/templates/apps/react-router/src/routes/(dashboard)/index.tsx +19 -0
  77. package/templates/apps/react-router/src/routes/(dashboard)/layout.tsx +37 -0
  78. package/templates/apps/react-router/src/routes/(dashboard)/todos/[id].tsx +19 -0
  79. package/templates/apps/react-router/src/routes/(dashboard)/todos/index.tsx +19 -0
  80. package/templates/apps/react-router/src/routes.ts +12 -0
  81. package/templates/apps/react-router/src/surfaces/home/bootstrap.ts +9 -0
  82. package/templates/apps/react-router/src/surfaces/home/home.tsx +25 -0
  83. package/templates/apps/react-router/src/surfaces/home/install.tsx +17 -0
  84. package/templates/apps/react-router/src/surfaces/home/layout.tsx +35 -0
  85. package/templates/apps/react-router/src/surfaces/home/main/create.tsx +32 -0
  86. package/templates/apps/react-router/src/surfaces/sidebar/install.tsx +23 -0
  87. package/templates/apps/react-router/src/surfaces/sidebar/layout.tsx +110 -0
  88. package/templates/apps/react-router/src/surfaces/sidebar/nav_main/create.tsx +31 -0
  89. package/templates/apps/react-router/src/surfaces/sidebar/nav_main/nav_main.tsx +42 -0
  90. package/templates/apps/react-router/src/surfaces/sidebar/nav_secondary/create.tsx +21 -0
  91. package/templates/apps/react-router/src/surfaces/sidebar/nav_secondary/nav_secondary.tsx +31 -0
  92. package/templates/apps/react-router/src/surfaces/sidebar/sidebar.tsx +18 -0
  93. package/templates/apps/react-router/src/surfaces/sidebar/user_menu/create.tsx +26 -0
  94. package/templates/{react-router/src/layouts/sidebar/sidebar_aside → apps/react-router/src/surfaces/sidebar/user_menu}/user_menu.tsx +13 -9
  95. package/templates/apps/react-router/src/surfaces/todos/all_todos/all_todos.tsx +25 -0
  96. package/templates/apps/react-router/src/surfaces/todos/all_todos/all_todos_controller.ts +47 -0
  97. package/templates/apps/react-router/src/surfaces/todos/all_todos/bootstrap.ts +18 -0
  98. package/templates/apps/react-router/src/surfaces/todos/all_todos/header/create.tsx +21 -0
  99. package/templates/apps/react-router/src/surfaces/todos/all_todos/install.tsx +20 -0
  100. package/templates/apps/react-router/src/surfaces/todos/all_todos/layout.tsx +35 -0
  101. package/templates/apps/react-router/src/surfaces/todos/all_todos/main/create.tsx +47 -0
  102. package/templates/apps/react-router/src/surfaces/todos/all_todos/main/main.tsx +68 -0
  103. package/templates/apps/react-router/src/surfaces/todos/all_todos/main/new_todo_sheet/create.tsx +54 -0
  104. package/templates/apps/react-router/src/surfaces/todos/all_todos/main/new_todo_sheet/new_todo_sheet.tsx +97 -0
  105. package/templates/apps/react-router/src/surfaces/todos/all_todos/main/new_todo_sheet/schema.ts +11 -0
  106. package/templates/apps/react-router/src/surfaces/todos/single_todo/bootstrap.ts +36 -0
  107. package/templates/apps/react-router/src/surfaces/todos/single_todo/header/create.tsx +32 -0
  108. package/templates/apps/react-router/src/surfaces/todos/single_todo/header/header.tsx +25 -0
  109. package/templates/apps/react-router/src/surfaces/todos/single_todo/install.tsx +27 -0
  110. package/templates/apps/react-router/src/surfaces/todos/single_todo/layout.tsx +45 -0
  111. package/templates/apps/react-router/src/surfaces/todos/single_todo/main/create.tsx +35 -0
  112. package/templates/apps/react-router/src/surfaces/todos/single_todo/main/main.tsx +47 -0
  113. package/templates/apps/react-router/src/surfaces/todos/single_todo/single_todo.tsx +27 -0
  114. package/templates/apps/react-router/src/surfaces/todos/single_todo/single_todo_controller.ts +16 -0
  115. package/templates/{react-router → apps/react-router}/vite.config.ts +27 -3
  116. package/templates/{_base/biome.json → biome.json} +7 -0
  117. package/templates/bun.lock +3187 -0
  118. package/templates/{_base/emails → emails}/project.json +1 -1
  119. package/templates/{_base/nx.json → nx.json} +11 -0
  120. package/templates/package.json +92 -0
  121. package/templates/{_base/tsconfig.base.json → tsconfig.base.json} +4 -1
  122. package/templates/_base/.cursor/rules/frontend_rules.mdc +0 -268
  123. package/templates/_base/.env.convex.example +0 -3
  124. package/templates/_base/_gitignore +0 -58
  125. package/templates/_base/package.json +0 -73
  126. package/templates/nextjs/.env.example +0 -8
  127. package/templates/nextjs/src/app/(dashboard)/layout.tsx +0 -27
  128. package/templates/nextjs/src/app/(dashboard)/page.tsx +0 -5
  129. package/templates/nextjs/src/app/(dashboard)/todos/page.tsx +0 -16
  130. package/templates/nextjs/src/middleware.ts +0 -18
  131. package/templates/nextjs/src/surfaces/home_surface.tsx +0 -22
  132. package/templates/nextjs/src/surfaces/todos/all_todos_surface.tsx +0 -97
  133. package/templates/nextjs/src/surfaces/todos/create_todo_sheet.tsx +0 -107
  134. package/templates/nextjs/src/surfaces/todos/single_todo_surface.tsx +0 -90
  135. package/templates/nextjs/src/ui/sidebar/sidebar.tsx +0 -125
  136. package/templates/react-router/.env.example +0 -8
  137. package/templates/react-router/src/app.css +0 -3
  138. package/templates/react-router/src/layouts/sidebar/sidebar_aside/sidebar_aside.tsx +0 -76
  139. package/templates/react-router/src/layouts/sidebar/sidebar_layout.tsx +0 -22
  140. package/templates/react-router/src/routes/index.tsx +0 -9
  141. package/templates/react-router/src/routes/layout.tsx +0 -26
  142. package/templates/react-router/src/routes/todos/[id].tsx +0 -22
  143. package/templates/react-router/src/routes/todos/index.tsx +0 -13
  144. package/templates/react-router/src/routes.ts +0 -12
  145. package/templates/react-router/src/surfaces/home_surface.tsx +0 -20
  146. package/templates/react-router/src/surfaces/todos/all_todos_surface.tsx +0 -87
  147. package/templates/react-router/src/surfaces/todos/create_todo_sheet.tsx +0 -102
  148. package/templates/react-router/src/surfaces/todos/single_todo_surface.tsx +0 -81
  149. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/SKILL.md +0 -0
  150. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/SKILL.md +0 -0
  151. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/api-specs-context.sh +0 -0
  152. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/execute-request.sh +0 -0
  153. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/extract-endpoint-detail.sh +0 -0
  154. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/extract-tag-endpoints.sh +0 -0
  155. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/extract-tags.js +0 -0
  156. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/SKILL.md +0 -0
  157. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-2/custom-sign-in.md +0 -0
  158. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-2/custom-sign-up.md +0 -0
  159. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-3/custom-sign-in.md +0 -0
  160. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-3/custom-sign-up.md +0 -0
  161. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-3/show-component.md +0 -0
  162. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/SKILL.md +0 -0
  163. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/api-routes.md +0 -0
  164. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/caching-auth.md +0 -0
  165. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/middleware-strategies.md +0 -0
  166. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/server-actions.md +0 -0
  167. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/server-vs-client.md +0 -0
  168. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-webhooks/SKILL.md +0 -0
  169. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/SKILL.md +0 -0
  170. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/agents/openai.yml +0 -0
  171. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/assets/shadcn-small.png +0 -0
  172. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/assets/shadcn.png +0 -0
  173. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/cli.md +0 -0
  174. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/customization.md +0 -0
  175. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/evals/evals.json +0 -0
  176. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/mcp.md +0 -0
  177. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/base-vs-radix.md +0 -0
  178. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/composition.md +0 -0
  179. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/forms.md +0 -0
  180. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/icons.md +0 -0
  181. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/styling.md +0 -0
  182. /package/templates/{_base/.cursor → .cursor}/commands/builder.md +0 -0
  183. /package/templates/{_base/.cursor → .cursor}/commands/pr.md +0 -0
  184. /package/templates/{_base/.github → .github}/workflows/ci.yml +0 -0
  185. /package/templates/{_base/.nvmrc → .nvmrc} +0 -0
  186. /package/templates/{_base/.vscode → .vscode}/settings.json +0 -0
  187. /package/templates/{_base/apps → apps}/api/auth.config.ts +0 -0
  188. /package/templates/{_base/apps → apps}/api/functions.ts +0 -0
  189. /package/templates/{_base/apps → apps}/api/project.json +0 -0
  190. /package/templates/{_base/apps → apps}/api/schema.ts +0 -0
  191. /package/templates/{_base/apps → apps}/api/todos/crud.ts +0 -0
  192. /package/templates/{_base/apps → apps}/api/todos/schema.ts +0 -0
  193. /package/templates/{_base/apps → apps}/api/todos/types.ts +0 -0
  194. /package/templates/{_base/apps → apps}/api/tsconfig.json +0 -0
  195. /package/templates/{_base/apps → apps}/api/types.ts +0 -0
  196. /package/templates/{nextjs → apps/nextjs}/index.d.ts +0 -0
  197. /package/templates/{nextjs → apps/nextjs}/next-env.d.ts +0 -0
  198. /package/templates/{nextjs → apps/nextjs}/next.config.js +0 -0
  199. /package/templates/{nextjs → apps/nextjs}/postcss.config.js +0 -0
  200. /package/templates/{nextjs → apps/nextjs}/src/app/(auth)/layout.tsx +0 -0
  201. /package/templates/{nextjs → apps/nextjs}/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx +0 -0
  202. /package/templates/{nextjs → apps/nextjs}/src/app/app.css +0 -0
  203. /package/templates/{nextjs → apps/nextjs}/src/app/layout.tsx +0 -0
  204. /package/templates/{nextjs → apps/nextjs}/src/providers/convex_provider.tsx +0 -0
  205. /package/templates/{nextjs/src → apps/nextjs/src/utils}/convex.ts +0 -0
  206. /package/templates/{nextjs → apps/nextjs}/src/utils/font.ts +0 -0
  207. /package/templates/{nextjs → apps/nextjs}/tsconfig.json +0 -0
  208. /package/templates/{react-router → apps/react-router}/postcss.config.js +0 -0
  209. /package/templates/{react-router → apps/react-router}/public/favicon.ico +0 -0
  210. /package/templates/{react-router → apps/react-router}/react-router.config.ts +0 -0
  211. /package/templates/{react-router → apps/react-router}/src/root.tsx +0 -0
  212. /package/templates/{react-router/src/routes/auth/sign-in.tsx → apps/react-router/src/routes/(auth)/sign-in/index.tsx} +0 -0
  213. /package/templates/{react-router → apps/react-router}/tsconfig.json +0 -0
  214. /package/templates/{_base/convex.json → convex.json} +0 -0
  215. /package/templates/{_base/emails → emails}/tsconfig.json +0 -0
  216. /package/templates/{_base/emails → emails}/welcome_email.tsx +0 -0
  217. /package/templates/{_base/scripts → scripts}/sync_convex_env.ts +0 -0
  218. /package/templates/{_base/shared → shared}/assets/image.d.ts +0 -0
  219. /package/templates/{_base/shared → shared}/assets/src/styles/global.css +0 -0
  220. /package/templates/{_base/shared → shared}/assets/tsconfig.json +0 -0
  221. /package/templates/{_base/shared → shared}/ui/src/base/alert_dialog.tsx +0 -0
  222. /package/templates/{_base/shared → shared}/ui/src/base/badge.tsx +0 -0
  223. /package/templates/{_base/shared → shared}/ui/src/base/basic_data_table.tsx +0 -0
  224. /package/templates/{_base/shared → shared}/ui/src/base/button.tsx +0 -0
  225. /package/templates/{_base/shared → shared}/ui/src/base/button_group.tsx +0 -0
  226. /package/templates/{_base/shared → shared}/ui/src/base/card.tsx +0 -0
  227. /package/templates/{_base/shared → shared}/ui/src/base/checkbox.tsx +0 -0
  228. /package/templates/{_base/shared → shared}/ui/src/base/command.tsx +0 -0
  229. /package/templates/{_base/shared → shared}/ui/src/base/dialog.tsx +0 -0
  230. /package/templates/{_base/shared → shared}/ui/src/base/dropdown_menu.tsx +0 -0
  231. /package/templates/{_base/shared → shared}/ui/src/base/form.tsx +0 -0
  232. /package/templates/{_base/shared → shared}/ui/src/base/input.tsx +0 -0
  233. /package/templates/{_base/shared → shared}/ui/src/base/label.tsx +0 -0
  234. /package/templates/{_base/shared → shared}/ui/src/base/popover.tsx +0 -0
  235. /package/templates/{_base/shared → shared}/ui/src/base/radio_group.tsx +0 -0
  236. /package/templates/{_base/shared → shared}/ui/src/base/resizable.tsx +0 -0
  237. /package/templates/{_base/shared → shared}/ui/src/base/scroll_area.tsx +0 -0
  238. /package/templates/{_base/shared → shared}/ui/src/base/select.tsx +0 -0
  239. /package/templates/{_base/shared → shared}/ui/src/base/separator.tsx +0 -0
  240. /package/templates/{_base/shared → shared}/ui/src/base/sheet.tsx +0 -0
  241. /package/templates/{_base/shared → shared}/ui/src/base/side_bar.tsx +0 -0
  242. /package/templates/{_base/shared → shared}/ui/src/base/skeleton.tsx +0 -0
  243. /package/templates/{_base/shared → shared}/ui/src/base/spinner.tsx +0 -0
  244. /package/templates/{_base/shared → shared}/ui/src/base/switch.tsx +0 -0
  245. /package/templates/{_base/shared → shared}/ui/src/base/table.tsx +0 -0
  246. /package/templates/{_base/shared → shared}/ui/src/base/text_area.tsx +0 -0
  247. /package/templates/{_base/shared → shared}/ui/src/base/tooltip.tsx +0 -0
  248. /package/templates/{_base/shared → shared}/ui/src/base/utils.ts +0 -0
  249. /package/templates/{_base/shared → shared}/ui/src/hooks/use_keyboard_press.tsx +0 -0
  250. /package/templates/{_base/shared → shared}/ui/src/hooks/use_keyboard_release.tsx +0 -0
  251. /package/templates/{_base/shared → shared}/ui/src/hooks/use_mobile.tsx +0 -0
  252. /package/templates/{_base/shared → shared}/ui/src/hooks/use_mouse_click.tsx +0 -0
  253. /package/templates/{_base/shared → shared}/ui/src/hooks/use_mouse_location.tsx +0 -0
  254. /package/templates/{_base/shared → shared}/ui/src/hooks/use_outside_click.tsx +0 -0
  255. /package/templates/{_base/shared → shared}/ui/src/hooks/use_query_params.tsx +0 -0
  256. /package/templates/{_base/shared → shared}/ui/tsconfig.json +0 -0
  257. /package/templates/{_base/shared → shared}/utils/src/convex.ts +0 -0
  258. /package/templates/{_base/shared → shared}/utils/src/time.ts +0 -0
  259. /package/templates/{_base/shared → shared}/utils/tsconfig.json +0 -0
  260. /package/templates/{_base/skills-lock.json → skills-lock.json} +0 -0
@@ -0,0 +1,97 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { PlusIcon } from "lucide-react";
6
+ import { useFormContext } from "react-hook-form";
7
+
8
+ import { Button } from "@/ui/base/button";
9
+ import { DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/ui/base/dialog";
10
+ import { FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/ui/base/form";
11
+ import { Input } from "@/ui/base/input";
12
+ import { Sheet, SheetContent, SheetTrigger } from "@/ui/base/sheet";
13
+ import { TextArea } from "@/ui/base/text_area";
14
+ import type { NewTodoSchema } from "@/web/surfaces/todos/all_todos/main/new_todo_sheet/schema";
15
+
16
+ type NewTodoSheetProps = {
17
+ isPending: boolean;
18
+ onSubmit: () => void;
19
+ open: boolean;
20
+ onOpenChange: (open: boolean) => void;
21
+ };
22
+
23
+ export const NewTodoSheet = ({
24
+ isPending,
25
+ onSubmit,
26
+ open,
27
+ onOpenChange,
28
+ }: NewTodoSheetProps) => {
29
+ const form = useFormContext<NewTodoSchema>();
30
+
31
+ return (
32
+ <Sheet open={open} onOpenChange={onOpenChange}>
33
+ <SheetTrigger asChild>
34
+ <Button type="button">
35
+ <PlusIcon className="mr-2 size-4" />
36
+ New Todo
37
+ </Button>
38
+ </SheetTrigger>
39
+ <SheetContent className="sm:max-w-[440px]">
40
+ <DialogHeader>
41
+ <DialogTitle>Create Todo</DialogTitle>
42
+ <DialogDescription>Add a new item to your todo list.</DialogDescription>
43
+ </DialogHeader>
44
+ <form
45
+ onSubmit={(e) => {
46
+ e.preventDefault();
47
+ onSubmit();
48
+ }}
49
+ className="flex flex-col gap-4 pt-4"
50
+ onKeyDown={(e) => {
51
+ if (e.key === "Enter") {
52
+ e.preventDefault();
53
+ onSubmit();
54
+ }
55
+ }}
56
+ >
57
+ <FormField
58
+ control={form.control}
59
+ name="title"
60
+ render={({ field }) => (
61
+ <FormItem>
62
+ <FormLabel>Title</FormLabel>
63
+ <FormControl>
64
+ <Input placeholder="Buy groceries..." {...field} />
65
+ </FormControl>
66
+ <FormMessage />
67
+ </FormItem>
68
+ )}
69
+ />
70
+ <FormField
71
+ control={form.control}
72
+ name="description"
73
+ render={({ field }) => (
74
+ <FormItem>
75
+ <FormLabel>Description</FormLabel>
76
+ <FormControl>
77
+ <TextArea
78
+ placeholder="Optional details..."
79
+ className="resize-none"
80
+ rows={3}
81
+ {...field}
82
+ />
83
+ </FormControl>
84
+ <FormMessage />
85
+ </FormItem>
86
+ )}
87
+ />
88
+ <DialogFooter>
89
+ <Button type="submit" disabled={isPending}>
90
+ {isPending ? "Creating..." : "Create Todo"}
91
+ </Button>
92
+ </DialogFooter>
93
+ </form>
94
+ </SheetContent>
95
+ </Sheet>
96
+ );
97
+ };
@@ -0,0 +1,11 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { z } from "zod";
6
+
7
+ export type NewTodoSchema = z.infer<typeof newTodoSchema>;
8
+ export const newTodoSchema = z.object({
9
+ title: z.string().min(1, "Title is required"),
10
+ description: z.string().optional(),
11
+ });
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { convexQuery } from "@convex-dev/react-query";
6
+ import { redirect } from "react-router";
7
+
8
+ import { api } from "@/api/_generated/api";
9
+ import type { Todo, TodoId } from "@/api/todos/types";
10
+ import { queryClient } from "@/web/providers/api_auth_provider";
11
+
12
+ export type SingleTodoBootstrapArgs = {
13
+ params: { id?: string };
14
+ };
15
+
16
+ export type SingleTodoBootstrap = {
17
+ todoId: TodoId;
18
+ todo: Todo;
19
+ };
20
+
21
+ export const bootstrapSingleTodo = async ({
22
+ params,
23
+ }: SingleTodoBootstrapArgs): Promise<SingleTodoBootstrap> => {
24
+ if (!params.id) {
25
+ throw redirect("/todos");
26
+ }
27
+ const todoId = params.id as TodoId;
28
+ try {
29
+ const todo = await queryClient.ensureQueryData(
30
+ convexQuery(api.todos.crud.getTodo, { todoId }),
31
+ );
32
+ return { todoId, todo };
33
+ } catch {
34
+ throw redirect("/todos");
35
+ }
36
+ };
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { observer } from "mobx-react-lite";
6
+ import type { ComponentType } from "react";
7
+ import type { NavigateFunction } from "react-router";
8
+
9
+ import { Header } from "@/web/surfaces/todos/single_todo/header/header";
10
+
11
+ export type CreateHeaderOpts = {
12
+ navigate: NavigateFunction;
13
+ };
14
+
15
+ type HeaderProps = {
16
+ SomeComponent: ComponentType;
17
+ };
18
+
19
+ export const createHeader = ({ navigate }: CreateHeaderOpts) => {
20
+ return observer(({ SomeComponent }: HeaderProps) => {
21
+ return (
22
+ <div>
23
+ <SomeComponent />
24
+ <Header
25
+ onBack={() => {
26
+ navigate("/todos");
27
+ }}
28
+ />
29
+ </div>
30
+ );
31
+ });
32
+ };
@@ -0,0 +1,25 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { ArrowLeft } from "lucide-react";
6
+
7
+ import { Button } from "@/ui/base/button";
8
+
9
+ type HeaderProps = {
10
+ onBack: () => void;
11
+ };
12
+
13
+ export const Header = ({ onBack }: HeaderProps) => {
14
+ return (
15
+ <Button
16
+ variant="ghost"
17
+ className="-ml-2 w-fit text-muted-foreground"
18
+ type="button"
19
+ onClick={onBack}
20
+ >
21
+ <ArrowLeft className="mr-2 size-4" />
22
+ Back
23
+ </Button>
24
+ );
25
+ };
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import type { NavigateFunction } from "react-router";
6
+
7
+ import type { SingleTodoBootstrap } from "@/web/surfaces/todos/single_todo/bootstrap";
8
+ import type { SingleTodoLayoutController } from "@/web/surfaces/todos/single_todo/layout";
9
+ import { SingleTodoController } from "@/web/surfaces/todos/single_todo/single_todo_controller";
10
+
11
+ export type InstallSingleTodoOpts = {
12
+ layout: SingleTodoLayoutController;
13
+ bootstrap: SingleTodoBootstrap;
14
+ navigate: NavigateFunction;
15
+ };
16
+
17
+ export const installSingleTodo = ({ layout, bootstrap, navigate }: InstallSingleTodoOpts) => {
18
+ const controller = new SingleTodoController();
19
+
20
+ import("@/web/surfaces/todos/single_todo/header/create").then(({ createHeader }) => {
21
+ layout.setHeader(createHeader({ navigate }));
22
+ });
23
+
24
+ import("@/web/surfaces/todos/single_todo/main/create").then(({ createMain }) => {
25
+ layout.setMain(createMain({ controller, bootstrap }));
26
+ });
27
+ };
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { action, observable } from "mobx";
6
+ import { observer } from "mobx-react-lite";
7
+ import type { ComponentType } from "react";
8
+
9
+ import { Skeleton } from "@/ui/base/skeleton";
10
+
11
+ export class SingleTodoLayoutController {
12
+ @observable.ref
13
+ accessor Header: ComponentType | undefined = undefined;
14
+
15
+ @observable.ref
16
+ accessor Main: ComponentType | undefined = undefined;
17
+
18
+ @action
19
+ setHeader(Header: ComponentType) {
20
+ this.Header = Header;
21
+ }
22
+
23
+ @action
24
+ setMain(Main: ComponentType) {
25
+ this.Main = Main;
26
+ }
27
+ }
28
+
29
+ export const createLayout = () => {
30
+ const layout = new SingleTodoLayoutController();
31
+ return {
32
+ layout,
33
+ Layout: observer(() => {
34
+ const Header = layout.Header;
35
+ const Main = layout.Main;
36
+
37
+ return (
38
+ <div className="flex w-full flex-1 flex-col gap-4">
39
+ {Header ? <Header /> : <Skeleton className="h-10 w-48 rounded-md" />}
40
+ {Main ? <Main /> : <Skeleton className="h-64 w-full max-w-2xl rounded-md" />}
41
+ </div>
42
+ );
43
+ }),
44
+ };
45
+ };
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { convexQuery } from "@convex-dev/react-query";
6
+ import { useQuery } from "@tanstack/react-query";
7
+ import { observer } from "mobx-react-lite";
8
+
9
+ import { api } from "@/api/_generated/api";
10
+ import type { SingleTodoBootstrap } from "@/web/surfaces/todos/single_todo/bootstrap";
11
+ import type { SingleTodoController } from "@/web/surfaces/todos/single_todo/single_todo_controller";
12
+ import { Main } from "@/web/surfaces/todos/single_todo/main/main";
13
+
14
+ export type CreateMainOpts = {
15
+ controller: SingleTodoController;
16
+ bootstrap: SingleTodoBootstrap;
17
+ };
18
+
19
+ export const createMain = ({ controller, bootstrap }: CreateMainOpts) => {
20
+ return observer(() => {
21
+ const { data: todo } = useQuery({
22
+ ...convexQuery(api.todos.crud.getTodo, { todoId: bootstrap.todoId }),
23
+ initialData: bootstrap.todo as never,
24
+ });
25
+
26
+ return (
27
+ <Main
28
+ todo={todo}
29
+ onToggle={(todoId, isCompleted) => {
30
+ void controller.updateTodo({ todoId, isCompleted });
31
+ }}
32
+ />
33
+ );
34
+ });
35
+ };
@@ -0,0 +1,47 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import type { Todo, TodoId } from "@/api/todos/types";
6
+ import { Badge } from "@/ui/base/badge";
7
+ import { Checkbox } from "@/ui/base/checkbox";
8
+
9
+ type MainProps = {
10
+ todo: Todo | undefined;
11
+ onToggle: (todoId: TodoId, isCompleted: boolean) => void;
12
+ };
13
+
14
+ export const Main = ({ todo, onToggle }: MainProps) => {
15
+ if (!todo) {
16
+ return null;
17
+ }
18
+
19
+ return (
20
+ <main className="flex max-w-2xl flex-1 flex-col gap-6 overflow-auto p-6">
21
+ <div className="flex items-start gap-3">
22
+ <Checkbox
23
+ className="mt-1"
24
+ checked={todo.isCompleted}
25
+ onCheckedChange={(checked) =>
26
+ onToggle(todo._id, !!checked)
27
+ }
28
+ />
29
+ <div className="flex flex-col gap-2">
30
+ <h1
31
+ className="text-2xl font-semibold"
32
+ style={{
33
+ textDecoration: todo.isCompleted ? "line-through" : undefined,
34
+ }}
35
+ >
36
+ {todo.title}
37
+ </h1>
38
+ <Badge variant={todo.isCompleted ? "secondary" : "default"}>
39
+ {todo.isCompleted ? "Completed" : "In progress"}
40
+ </Badge>
41
+ </div>
42
+ </div>
43
+
44
+ {todo.description ? <p className="text-muted-foreground">{todo.description}</p> : null}
45
+ </main>
46
+ );
47
+ };
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { useMemo, useRef } from "react";
6
+ import { useNavigate } from "react-router";
7
+
8
+ import type { SingleTodoBootstrap } from "@/web/surfaces/todos/single_todo/bootstrap";
9
+ import { installSingleTodo } from "@/web/surfaces/todos/single_todo/install";
10
+ import { createLayout } from "@/web/surfaces/todos/single_todo/layout";
11
+
12
+ export type SingleTodoProps = {
13
+ bootstrap: SingleTodoBootstrap;
14
+ };
15
+
16
+ export const SingleTodo = ({ bootstrap }: SingleTodoProps) => {
17
+ const navigate = useNavigate();
18
+ const { layout, Layout } = useMemo(createLayout, []);
19
+ const installed = useRef(false);
20
+
21
+ if (!installed.current) {
22
+ installed.current = true;
23
+ installSingleTodo({ layout, bootstrap, navigate });
24
+ }
25
+
26
+ return <Layout />;
27
+ };
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Copyright (c) Aron Weston 2026.
3
+ */
4
+
5
+ import { action } from "mobx";
6
+
7
+ import { api } from "@/api/_generated/api";
8
+ import type { TodoId } from "@/api/todos/types";
9
+ import { convex } from "@/web/providers/api_auth_provider";
10
+
11
+ export class SingleTodoController {
12
+ @action
13
+ async updateTodo(args: { todoId: TodoId; isCompleted: boolean }) {
14
+ await convex.mutation(api.todos.crud.updateTodo, args);
15
+ }
16
+ }
@@ -1,12 +1,12 @@
1
1
  import path from "node:path";
2
2
 
3
+ import { transformAsync } from "@babel/core";
3
4
  import { reactRouter } from "@react-router/dev/vite";
4
5
  import tailwindcss from "@tailwindcss/vite";
5
6
  import { defineConfig, type PluginOption } from "vite";
6
7
  import devtoolsJson from "vite-plugin-devtools-json";
7
8
  import tsconfigPaths from "vite-tsconfig-paths";
8
-
9
- const workspaceRoot = path.resolve(__dirname, "../..");
9
+ import { uuid } from "zod/v4";
10
10
 
11
11
  if (!process.env.VITE_CLERK_PUBLISHABLE_KEY) {
12
12
  throw new Error("VITE_CLERK_PUBLISHABLE_KEY is not set");
@@ -16,12 +16,36 @@ if (!process.env.CLERK_SECRET_KEY) {
16
16
  throw new Error("CLERK_SECRET_KEY is not set");
17
17
  }
18
18
 
19
+ const workspaceRoot = path.resolve(__dirname, "../..");
20
+
21
+ const appRoot = path.resolve(__dirname, "src");
22
+
19
23
  export default defineConfig({
24
+ build: {
25
+ outDir: "dist",
26
+ },
20
27
  plugins: [
21
28
  tailwindcss(),
29
+ {
30
+ name: "mobx-decorators",
31
+ enforce: "pre",
32
+ async transform(code, id) {
33
+ if (!id.startsWith(appRoot) || !/\.[jt]sx?$/.test(id)) return null;
34
+ const result = await transformAsync(code, {
35
+ filename: id,
36
+ configFile: false,
37
+ babelrc: false,
38
+ presets: [
39
+ ["@babel/preset-typescript", { allExtensions: true, isTSX: id.endsWith(".tsx") }],
40
+ ],
41
+ plugins: [["@babel/plugin-proposal-decorators", { version: "2023-05" }]],
42
+ });
43
+ return result ? { code: result.code!, map: result.map } : null;
44
+ },
45
+ } as PluginOption,
22
46
  reactRouter(),
23
47
  tsconfigPaths(),
24
- devtoolsJson({ uuid: "my-app" }) as PluginOption,
48
+ devtoolsJson({ uuid: uuid().toString() }) as PluginOption,
25
49
  ],
26
50
  server: {
27
51
  fs: {
@@ -29,6 +29,9 @@
29
29
  "enabled": true
30
30
  },
31
31
  "css": {
32
+ "parser": {
33
+ "tailwindDirectives": true
34
+ },
32
35
  "formatter": {
33
36
  "enabled": true,
34
37
  "indentStyle": "space",
@@ -94,6 +97,10 @@
94
97
  "recommended": true,
95
98
  "style": {
96
99
  "noInferrableTypes": "error",
100
+ "useBlockStatements": {
101
+ "level": "error",
102
+ "fix": "safe"
103
+ },
97
104
  "noParameterAssign": "warn",
98
105
  "noUnusedTemplateLiteral": "error",
99
106
  "noUselessElse": "error",