create-aron-app 0.1.6 → 0.1.8

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 (234) hide show
  1. package/README.md +24 -31
  2. package/dist/index.js +39 -115
  3. package/package.json +7 -4
  4. package/templates/.cursor/rules/backend.mdc +112 -0
  5. package/templates/.cursor/rules/coding_standards.mdc +145 -0
  6. package/templates/.cursor/rules/frontend_architecture.mdc +334 -0
  7. package/templates/.github/workflows/ci.yml +40 -0
  8. package/templates/apps/api/_generated/api.d.ts +57 -0
  9. package/templates/apps/api/_generated/api.js +23 -0
  10. package/templates/apps/api/_generated/dataModel.d.ts +60 -0
  11. package/templates/apps/api/_generated/server.d.ts +143 -0
  12. package/templates/apps/api/_generated/server.js +93 -0
  13. package/templates/apps/api/http.ts +16 -0
  14. package/templates/apps/web/.env.example +10 -0
  15. package/templates/apps/web/.react-router/types/+future.ts +9 -0
  16. package/templates/apps/web/.react-router/types/+routes.ts +76 -0
  17. package/templates/apps/web/.react-router/types/+server-build.d.ts +18 -0
  18. package/templates/apps/web/.react-router/types/src/+types/root.ts +59 -0
  19. package/templates/apps/web/.react-router/types/src/routes/(auth)/+types/layout.ts +62 -0
  20. package/templates/apps/web/.react-router/types/src/routes/(auth)/sign-in/+types/index.ts +65 -0
  21. package/templates/apps/web/.react-router/types/src/routes/(dashboard)/(todos)/+types/[id].ts +68 -0
  22. package/templates/apps/web/.react-router/types/src/routes/(dashboard)/(todos)/+types/index.ts +68 -0
  23. package/templates/apps/web/.react-router/types/src/routes/(dashboard)/(todos)/+types/layout.ts +65 -0
  24. package/templates/apps/web/.react-router/types/src/routes/(dashboard)/+types/index.ts +65 -0
  25. package/templates/apps/web/.react-router/types/src/routes/(dashboard)/+types/layout.ts +62 -0
  26. package/templates/{react-router → apps/web}/project.json +9 -2
  27. package/templates/{react-router → apps/web}/react-router.config.ts +1 -1
  28. package/templates/apps/web/src/app.css +3 -0
  29. package/templates/{react-router → apps/web}/src/components/error_boundary.tsx +1 -1
  30. package/templates/apps/web/src/libs/convex_query_client.ts +11 -0
  31. package/templates/apps/web/src/libs/react_query_client.ts +17 -0
  32. package/templates/apps/web/src/libs/server/auth.ts +32 -0
  33. package/templates/apps/web/src/libs/server/protected.ts +17 -0
  34. package/templates/apps/web/src/providers/api_auth_provider.tsx +26 -0
  35. package/templates/apps/web/src/providers/global_provider.tsx +28 -0
  36. package/templates/apps/web/src/providers/navigation_loading_bar_provider.tsx +72 -0
  37. package/templates/apps/web/src/root.tsx +68 -0
  38. package/templates/{react-router/src/routes/auth → apps/web/src/routes/(auth)}/layout.tsx +1 -1
  39. package/templates/apps/web/src/routes/(dashboard)/(todos)/[id].tsx +33 -0
  40. package/templates/apps/web/src/routes/(dashboard)/(todos)/index.tsx +26 -0
  41. package/templates/apps/web/src/routes/(dashboard)/(todos)/layout.tsx +9 -0
  42. package/templates/apps/web/src/routes/(dashboard)/index.tsx +20 -0
  43. package/templates/apps/web/src/routes/(dashboard)/layout.tsx +20 -0
  44. package/templates/apps/web/src/routes.ts +14 -0
  45. package/templates/apps/web/src/surfaces/home/bootstrap.ts +9 -0
  46. package/templates/apps/web/src/surfaces/home/home.tsx +25 -0
  47. package/templates/apps/web/src/surfaces/home/install.tsx +17 -0
  48. package/templates/apps/web/src/surfaces/home/layout.tsx +35 -0
  49. package/templates/apps/web/src/surfaces/home/main/create.tsx +32 -0
  50. package/templates/apps/web/src/surfaces/sidebar/install.tsx +19 -0
  51. package/templates/apps/web/src/surfaces/sidebar/layout.tsx +119 -0
  52. package/templates/apps/web/src/surfaces/sidebar/nav_main/create.tsx +31 -0
  53. package/templates/apps/web/src/surfaces/sidebar/nav_main/nav_main.tsx +42 -0
  54. package/templates/apps/web/src/surfaces/sidebar/sidebar.tsx +18 -0
  55. package/templates/apps/web/src/surfaces/sidebar/user_menu/create.tsx +26 -0
  56. package/templates/{react-router/src/layouts/sidebar/sidebar_aside → apps/web/src/surfaces/sidebar/user_menu}/user_menu.tsx +13 -9
  57. package/templates/apps/web/src/surfaces/todos/all_todos/all_todos.tsx +25 -0
  58. package/templates/apps/web/src/surfaces/todos/all_todos/all_todos_controller.ts +47 -0
  59. package/templates/apps/web/src/surfaces/todos/all_todos/bootstrap.ts +21 -0
  60. package/templates/apps/web/src/surfaces/todos/all_todos/header/create.tsx +21 -0
  61. package/templates/apps/web/src/surfaces/todos/all_todos/install.tsx +20 -0
  62. package/templates/apps/web/src/surfaces/todos/all_todos/layout.tsx +35 -0
  63. package/templates/apps/web/src/surfaces/todos/all_todos/main/create.tsx +47 -0
  64. package/templates/apps/web/src/surfaces/todos/all_todos/main/main.tsx +68 -0
  65. package/templates/apps/web/src/surfaces/todos/all_todos/main/new_todo_sheet/create.tsx +54 -0
  66. package/templates/apps/web/src/surfaces/todos/all_todos/main/new_todo_sheet/new_todo_sheet.tsx +97 -0
  67. package/templates/apps/web/src/surfaces/todos/all_todos/main/new_todo_sheet/schema.ts +11 -0
  68. package/templates/apps/web/src/surfaces/todos/single_todo/bootstrap.ts +35 -0
  69. package/templates/apps/web/src/surfaces/todos/single_todo/header/create.tsx +24 -0
  70. package/templates/apps/web/src/surfaces/todos/single_todo/header/header.tsx +25 -0
  71. package/templates/apps/web/src/surfaces/todos/single_todo/install.tsx +27 -0
  72. package/templates/apps/web/src/surfaces/todos/single_todo/layout.tsx +45 -0
  73. package/templates/apps/web/src/surfaces/todos/single_todo/main/create.tsx +35 -0
  74. package/templates/apps/web/src/surfaces/todos/single_todo/main/main.tsx +47 -0
  75. package/templates/apps/web/src/surfaces/todos/single_todo/single_todo.tsx +27 -0
  76. package/templates/apps/web/src/surfaces/todos/single_todo/single_todo_controller.ts +16 -0
  77. package/templates/{react-router → apps/web}/vite.config.ts +27 -3
  78. package/templates/{_base/biome.json → biome.json} +12 -0
  79. package/templates/bun.lock +1917 -0
  80. package/templates/{_base/emails → emails}/project.json +1 -1
  81. package/templates/package.json +91 -0
  82. package/templates/{_base/shared → shared}/assets/src/styles/global.css +14 -8
  83. package/templates/shared/ui/src/base/collapsible.tsx +31 -0
  84. package/templates/shared/ui/src/base/hover-card.tsx +42 -0
  85. package/templates/shared/ui/src/base/input-group.tsx +168 -0
  86. package/templates/shared/ui/src/base/panel.tsx +93 -0
  87. package/templates/{_base/shared → shared}/ui/src/hooks/use_mobile.tsx +1 -1
  88. package/templates/{_base/shared → shared}/ui/src/hooks/use_query_params.tsx +6 -7
  89. package/templates/{_base/shared → shared}/ui/tsconfig.json +1 -1
  90. package/templates/shared/utils/src/convex.ts +4 -0
  91. package/templates/{_base/tsconfig.base.json → tsconfig.base.json} +2 -1
  92. package/templates/_base/.cursor/commands/builder.md +0 -0
  93. package/templates/_base/.cursor/rules/api_architecture.mdc +0 -268
  94. package/templates/_base/.cursor/rules/coding_standards.mdc +0 -64
  95. package/templates/_base/.cursor/rules/convex_rules.mdc +0 -675
  96. package/templates/_base/.cursor/rules/frontend_rules.mdc +0 -268
  97. package/templates/_base/.env.convex.example +0 -3
  98. package/templates/_base/.github/workflows/ci.yml +0 -29
  99. package/templates/_base/_gitignore +0 -58
  100. package/templates/_base/package.json +0 -73
  101. package/templates/_base/shared/utils/src/convex.ts +0 -3
  102. package/templates/nextjs/.env.example +0 -8
  103. package/templates/nextjs/index.d.ts +0 -6
  104. package/templates/nextjs/next-env.d.ts +0 -5
  105. package/templates/nextjs/next.config.js +0 -22
  106. package/templates/nextjs/postcss.config.js +0 -17
  107. package/templates/nextjs/project.json +0 -22
  108. package/templates/nextjs/src/app/(auth)/layout.tsx +0 -21
  109. package/templates/nextjs/src/app/(auth)/not-allowed/page.tsx +0 -22
  110. package/templates/nextjs/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx +0 -15
  111. package/templates/nextjs/src/app/(dashboard)/layout.tsx +0 -27
  112. package/templates/nextjs/src/app/(dashboard)/page.tsx +0 -5
  113. package/templates/nextjs/src/app/(dashboard)/todos/[id]/page.tsx +0 -23
  114. package/templates/nextjs/src/app/(dashboard)/todos/page.tsx +0 -16
  115. package/templates/nextjs/src/app/app.css +0 -3
  116. package/templates/nextjs/src/app/layout.tsx +0 -26
  117. package/templates/nextjs/src/convex.ts +0 -11
  118. package/templates/nextjs/src/middleware.ts +0 -18
  119. package/templates/nextjs/src/providers/convex_provider.tsx +0 -44
  120. package/templates/nextjs/src/surfaces/home_surface.tsx +0 -22
  121. package/templates/nextjs/src/surfaces/todos/all_todos_surface.tsx +0 -97
  122. package/templates/nextjs/src/surfaces/todos/create_todo_sheet.tsx +0 -107
  123. package/templates/nextjs/src/surfaces/todos/single_todo_surface.tsx +0 -90
  124. package/templates/nextjs/src/ui/sidebar/nav_link.tsx +0 -36
  125. package/templates/nextjs/src/ui/sidebar/sidebar.tsx +0 -125
  126. package/templates/nextjs/src/utils/font.ts +0 -9
  127. package/templates/nextjs/tsconfig.json +0 -42
  128. package/templates/react-router/.env.example +0 -8
  129. package/templates/react-router/src/app.css +0 -3
  130. package/templates/react-router/src/layouts/sidebar/sidebar_aside/sidebar_aside.tsx +0 -76
  131. package/templates/react-router/src/layouts/sidebar/sidebar_layout.tsx +0 -22
  132. package/templates/react-router/src/providers/api_auth_provider.tsx +0 -38
  133. package/templates/react-router/src/root.tsx +0 -37
  134. package/templates/react-router/src/routes/index.tsx +0 -9
  135. package/templates/react-router/src/routes/layout.tsx +0 -26
  136. package/templates/react-router/src/routes/todos/[id].tsx +0 -22
  137. package/templates/react-router/src/routes/todos/index.tsx +0 -13
  138. package/templates/react-router/src/routes.ts +0 -12
  139. package/templates/react-router/src/surfaces/home_surface.tsx +0 -20
  140. package/templates/react-router/src/surfaces/todos/all_todos_surface.tsx +0 -87
  141. package/templates/react-router/src/surfaces/todos/create_todo_sheet.tsx +0 -102
  142. package/templates/react-router/src/surfaces/todos/single_todo_surface.tsx +0 -81
  143. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/SKILL.md +0 -0
  144. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/SKILL.md +0 -0
  145. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/api-specs-context.sh +0 -0
  146. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/execute-request.sh +0 -0
  147. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/extract-endpoint-detail.sh +0 -0
  148. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/extract-tag-endpoints.sh +0 -0
  149. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-backend-api/scripts/extract-tags.js +0 -0
  150. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/SKILL.md +0 -0
  151. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-2/custom-sign-in.md +0 -0
  152. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-2/custom-sign-up.md +0 -0
  153. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-3/custom-sign-in.md +0 -0
  154. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-3/custom-sign-up.md +0 -0
  155. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-custom-ui/core-3/show-component.md +0 -0
  156. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/SKILL.md +0 -0
  157. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/api-routes.md +0 -0
  158. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/caching-auth.md +0 -0
  159. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/middleware-strategies.md +0 -0
  160. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/server-actions.md +0 -0
  161. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-nextjs-patterns/references/server-vs-client.md +0 -0
  162. /package/templates/{_base/.cursor → .cursor}/agents/skills/clerk/clerk-webhooks/SKILL.md +0 -0
  163. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/SKILL.md +0 -0
  164. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/agents/openai.yml +0 -0
  165. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/assets/shadcn-small.png +0 -0
  166. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/assets/shadcn.png +0 -0
  167. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/cli.md +0 -0
  168. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/customization.md +0 -0
  169. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/evals/evals.json +0 -0
  170. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/mcp.md +0 -0
  171. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/base-vs-radix.md +0 -0
  172. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/composition.md +0 -0
  173. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/forms.md +0 -0
  174. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/icons.md +0 -0
  175. /package/templates/{_base/.cursor → .cursor}/agents/skills/shadcn/rules/styling.md +0 -0
  176. /package/templates/{_base/.cursor → .cursor}/commands/pr.md +0 -0
  177. /package/templates/{_base/.nvmrc → .nvmrc} +0 -0
  178. /package/templates/{_base/.vscode → .vscode}/settings.json +0 -0
  179. /package/templates/{_base/apps → apps}/api/auth.config.ts +0 -0
  180. /package/templates/{_base/apps → apps}/api/functions.ts +0 -0
  181. /package/templates/{_base/apps → apps}/api/project.json +0 -0
  182. /package/templates/{_base/apps → apps}/api/schema.ts +0 -0
  183. /package/templates/{_base/apps → apps}/api/todos/crud.ts +0 -0
  184. /package/templates/{_base/apps → apps}/api/todos/schema.ts +0 -0
  185. /package/templates/{_base/apps → apps}/api/todos/types.ts +0 -0
  186. /package/templates/{_base/apps → apps}/api/tsconfig.json +0 -0
  187. /package/templates/{_base/apps → apps}/api/types.ts +0 -0
  188. /package/templates/{react-router → apps/web}/postcss.config.js +0 -0
  189. /package/templates/{react-router → apps/web}/public/favicon.ico +0 -0
  190. /package/templates/{react-router/src/routes/auth/sign-in.tsx → apps/web/src/routes/(auth)/sign-in/index.tsx} +0 -0
  191. /package/templates/{react-router → apps/web}/tsconfig.json +0 -0
  192. /package/templates/{_base/convex.json → convex.json} +0 -0
  193. /package/templates/{_base/emails → emails}/tsconfig.json +0 -0
  194. /package/templates/{_base/emails → emails}/welcome_email.tsx +0 -0
  195. /package/templates/{_base/nx.json → nx.json} +0 -0
  196. /package/templates/{_base/scripts → scripts}/sync_convex_env.ts +0 -0
  197. /package/templates/{_base/shared → shared}/assets/image.d.ts +0 -0
  198. /package/templates/{_base/shared → shared}/assets/tsconfig.json +0 -0
  199. /package/templates/{_base/shared → shared}/ui/src/base/alert_dialog.tsx +0 -0
  200. /package/templates/{_base/shared → shared}/ui/src/base/badge.tsx +0 -0
  201. /package/templates/{_base/shared → shared}/ui/src/base/basic_data_table.tsx +0 -0
  202. /package/templates/{_base/shared → shared}/ui/src/base/button.tsx +0 -0
  203. /package/templates/{_base/shared → shared}/ui/src/base/button_group.tsx +0 -0
  204. /package/templates/{_base/shared → shared}/ui/src/base/card.tsx +0 -0
  205. /package/templates/{_base/shared → shared}/ui/src/base/checkbox.tsx +0 -0
  206. /package/templates/{_base/shared → shared}/ui/src/base/command.tsx +0 -0
  207. /package/templates/{_base/shared → shared}/ui/src/base/dialog.tsx +0 -0
  208. /package/templates/{_base/shared → shared}/ui/src/base/dropdown_menu.tsx +0 -0
  209. /package/templates/{_base/shared → shared}/ui/src/base/form.tsx +0 -0
  210. /package/templates/{_base/shared → shared}/ui/src/base/input.tsx +0 -0
  211. /package/templates/{_base/shared → shared}/ui/src/base/label.tsx +0 -0
  212. /package/templates/{_base/shared → shared}/ui/src/base/popover.tsx +0 -0
  213. /package/templates/{_base/shared → shared}/ui/src/base/radio_group.tsx +0 -0
  214. /package/templates/{_base/shared → shared}/ui/src/base/resizable.tsx +0 -0
  215. /package/templates/{_base/shared → shared}/ui/src/base/scroll_area.tsx +0 -0
  216. /package/templates/{_base/shared → shared}/ui/src/base/select.tsx +0 -0
  217. /package/templates/{_base/shared → shared}/ui/src/base/separator.tsx +0 -0
  218. /package/templates/{_base/shared → shared}/ui/src/base/sheet.tsx +0 -0
  219. /package/templates/{_base/shared → shared}/ui/src/base/side_bar.tsx +0 -0
  220. /package/templates/{_base/shared → shared}/ui/src/base/skeleton.tsx +0 -0
  221. /package/templates/{_base/shared → shared}/ui/src/base/spinner.tsx +0 -0
  222. /package/templates/{_base/shared → shared}/ui/src/base/switch.tsx +0 -0
  223. /package/templates/{_base/shared → shared}/ui/src/base/table.tsx +0 -0
  224. /package/templates/{_base/shared → shared}/ui/src/base/text_area.tsx +0 -0
  225. /package/templates/{_base/shared → shared}/ui/src/base/tooltip.tsx +0 -0
  226. /package/templates/{_base/shared → shared}/ui/src/base/utils.ts +0 -0
  227. /package/templates/{_base/shared → shared}/ui/src/hooks/use_keyboard_press.tsx +0 -0
  228. /package/templates/{_base/shared → shared}/ui/src/hooks/use_keyboard_release.tsx +0 -0
  229. /package/templates/{_base/shared → shared}/ui/src/hooks/use_mouse_click.tsx +0 -0
  230. /package/templates/{_base/shared → shared}/ui/src/hooks/use_mouse_location.tsx +0 -0
  231. /package/templates/{_base/shared → shared}/ui/src/hooks/use_outside_click.tsx +0 -0
  232. /package/templates/{_base/shared → shared}/utils/src/time.ts +0 -0
  233. /package/templates/{_base/shared → shared}/utils/tsconfig.json +0 -0
  234. /package/templates/{_base/skills-lock.json → skills-lock.json} +0 -0
@@ -1,76 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { CheckSquare, Home } from "lucide-react";
6
- import { Link, useLocation } from "react-router";
7
-
8
- import {
9
- Sidebar,
10
- SidebarContent,
11
- SidebarFooter,
12
- SidebarHeader,
13
- SidebarMenu,
14
- SidebarMenuButton,
15
- SidebarMenuItem,
16
- useSidebar,
17
- } from "@/ui/base/side_bar";
18
- import { cn } from "@/ui/base/utils";
19
- import { UserMenu } from "@/web/layouts/sidebar/sidebar_aside/user_menu";
20
-
21
- type SidebarAsideProps = React.ComponentProps<typeof Sidebar>;
22
-
23
- const NAV_ITEMS = [
24
- { to: "/", label: "Home", icon: Home, exact: true },
25
- { to: "/todos", label: "Todos", icon: CheckSquare, exact: false },
26
- ];
27
-
28
- export const SidebarAside = ({ className, ...props }: SidebarAsideProps) => {
29
- const { setOpenMobile } = useSidebar();
30
- const location = useLocation();
31
-
32
- return (
33
- <Sidebar
34
- data-slot="app-sidebar"
35
- className={cn("border-r border-sidebar-border", className)}
36
- collapsible="offcanvas"
37
- {...props}
38
- >
39
- <SidebarHeader>
40
- <SidebarMenu>
41
- <SidebarMenuItem>
42
- <SidebarMenuButton size="lg" asChild>
43
- <Link to="/" onClick={() => setOpenMobile(false)}>
44
- <div className="flex size-8 items-center justify-center rounded-md bg-primary text-primary-foreground text-sm font-bold">
45
- A
46
- </div>
47
- <span className="font-semibold">My App</span>
48
- </Link>
49
- </SidebarMenuButton>
50
- </SidebarMenuItem>
51
- </SidebarMenu>
52
- </SidebarHeader>
53
-
54
- <SidebarContent className="px-2">
55
- <SidebarMenu>
56
- {NAV_ITEMS.map(({ to, label, icon: Icon, exact }) => {
57
- const isActive = exact ? location.pathname === to : location.pathname.startsWith(to);
58
- return (
59
- <SidebarMenuItem key={to}>
60
- <SidebarMenuButton isActive={isActive} asChild onClick={() => setOpenMobile(false)}>
61
- <Link to={to}>
62
- <Icon className="size-4" />
63
- <span>{label}</span>
64
- </Link>
65
- </SidebarMenuButton>
66
- </SidebarMenuItem>
67
- );
68
- })}
69
- </SidebarMenu>
70
- </SidebarContent>
71
- <SidebarFooter>
72
- <UserMenu />
73
- </SidebarFooter>
74
- </Sidebar>
75
- );
76
- };
@@ -1,22 +0,0 @@
1
- import { SidebarInset, SidebarProvider } from "@/ui/base/side_bar";
2
- import { SidebarAside } from "@/web/layouts/sidebar/sidebar_aside/sidebar_aside";
3
-
4
- type SideBarLayoutProps = {
5
- children: React.ReactNode;
6
- };
7
-
8
- export const SideBarLayout = ({ children }: SideBarLayoutProps) => {
9
- return (
10
- <SidebarProvider
11
- style={
12
- {
13
- "--sidebar-width": "calc(var(--spacing) * 45)",
14
- "--header-height": "calc(var(--spacing) * 12)",
15
- } as React.CSSProperties
16
- }
17
- >
18
- <SidebarAside variant="inset" />
19
- <SidebarInset>{children}</SidebarInset>
20
- </SidebarProvider>
21
- );
22
- };
@@ -1,38 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { ClerkProvider, useAuth } from "@clerk/react-router";
6
- import { ConvexQueryClient } from "@convex-dev/react-query";
7
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
8
- import { ConvexReactClient } from "convex/react";
9
- import { ConvexProviderWithClerk } from "convex/react-clerk";
10
-
11
- const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);
12
- const convexQueryClient = new ConvexQueryClient(convex);
13
-
14
- const queryClient = new QueryClient({
15
- defaultOptions: {
16
- queries: {
17
- queryFn: convexQueryClient.queryFn(),
18
- gcTime: 0,
19
- staleTime: 0,
20
- },
21
- },
22
- });
23
-
24
- convexQueryClient.connect(queryClient);
25
-
26
- type ApiAuthProviderProps = {
27
- children: React.ReactNode;
28
- };
29
-
30
- export const ApiAuthProvider = ({ children }: ApiAuthProviderProps) => {
31
- return (
32
- <ClerkProvider publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY as string}>
33
- <ConvexProviderWithClerk client={convex} useAuth={useAuth}>
34
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
35
- </ConvexProviderWithClerk>
36
- </ClerkProvider>
37
- );
38
- };
@@ -1,37 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import "./app.css";
6
-
7
- import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router";
8
- import { Toaster } from "sonner";
9
-
10
- import { ApiAuthProvider } from "@/web/providers/api_auth_provider";
11
-
12
- export function Layout({ children }: { children: React.ReactNode }) {
13
- return (
14
- <html lang="en">
15
- <head>
16
- <meta charSet="utf-8" />
17
- <meta name="viewport" content="width=device-width, initial-scale=1" />
18
- <Meta />
19
- <Links />
20
- </head>
21
- <body>
22
- {children}
23
- <ScrollRestoration />
24
- <Scripts />
25
- </body>
26
- </html>
27
- );
28
- }
29
-
30
- export default function App() {
31
- return (
32
- <ApiAuthProvider>
33
- <Outlet />
34
- <Toaster richColors position="top-center" />
35
- </ApiAuthProvider>
36
- );
37
- }
@@ -1,9 +0,0 @@
1
- import { HomeSurface } from "@/web/surfaces/home_surface";
2
-
3
- export function meta() {
4
- return [{ title: "Home" }, { name: "description", content: "Home" }];
5
- }
6
-
7
- export default function Home() {
8
- return <HomeSurface />;
9
- }
@@ -1,26 +0,0 @@
1
- /*
2
- * Copyright (c) SalesStar Limited 2026.
3
- */
4
-
5
- import { useAuth } from "@clerk/react-router";
6
- import { Navigate, Outlet } from "react-router";
7
-
8
- import { SideBarLayout } from "@/web/layouts/sidebar/sidebar_layout";
9
-
10
- export default function Layout() {
11
- const { isLoaded, isSignedIn } = useAuth();
12
-
13
- if (!isLoaded) {
14
- return null;
15
- }
16
-
17
- if (!isSignedIn) {
18
- return <Navigate to="/sign-in" replace />;
19
- }
20
-
21
- return (
22
- <SideBarLayout>
23
- <Outlet />
24
- </SideBarLayout>
25
- );
26
- }
@@ -1,22 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { useParams } from "react-router";
6
-
7
- import type { TodoId } from "@/api/todos/types";
8
- import { SingleTodoSurface } from "@/web/surfaces/todos/single_todo_surface";
9
-
10
- export function meta() {
11
- return [{ title: "Todo" }, { name: "description", content: "Todo" }];
12
- }
13
-
14
- export default function TodoPage() {
15
- const { id } = useParams<{ id: TodoId }>();
16
-
17
- if (!id) {
18
- return <div>Todo not found</div>;
19
- }
20
-
21
- return <SingleTodoSurface todoId={id} />;
22
- }
@@ -1,13 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { AllTodosSurface } from "@/web/surfaces/todos/all_todos_surface";
6
-
7
- export function meta() {
8
- return [{ title: "Todos" }, { name: "description", content: "Todos" }];
9
- }
10
-
11
- export default function TodosPage() {
12
- return <AllTodosSurface />;
13
- }
@@ -1,12 +0,0 @@
1
- import { index, layout, prefix, type RouteConfig, route } from "@react-router/dev/routes";
2
-
3
- export default [
4
- layout("./routes/auth/layout.tsx", [route("/sign-in/*", "./routes/auth/sign-in.tsx")]),
5
- layout("./routes/layout.tsx", [
6
- index("./routes/index.tsx"),
7
- ...prefix("todos", [
8
- index("./routes/todos/index.tsx"),
9
- route(":id", "./routes/todos/[id].tsx"),
10
- ]),
11
- ]),
12
- ] satisfies RouteConfig;
@@ -1,20 +0,0 @@
1
- import { useUser } from "@clerk/react-router";
2
- import { Link } from "react-router";
3
-
4
- import { Button } from "@/ui/base/button";
5
-
6
- export const HomeSurface = () => {
7
- const { user } = useUser();
8
-
9
- return (
10
- <main className="flex flex-1 flex-col items-center justify-center gap-4 p-8">
11
- <h1 className="text-3xl font-bold">
12
- Welcome{user?.firstName ? `, ${user.firstName}` : ""}
13
- </h1>
14
- <p className="text-muted-foreground">Get started by managing your todos.</p>
15
- <Button asChild>
16
- <Link to="/todos">View Todos</Link>
17
- </Button>
18
- </main>
19
- );
20
- };
@@ -1,87 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { convexQuery, useConvexMutation } from "@convex-dev/react-query";
6
- import { useMutation, useQuery } from "@tanstack/react-query";
7
- import { Trash2 } from "lucide-react";
8
- import { Link } from "react-router";
9
-
10
- import { api } from "@/api/_generated/api";
11
- import type { Id } from "@/api/_generated/dataModel";
12
- import { Button } from "@/ui/base/button";
13
- import { Checkbox } from "@/ui/base/checkbox";
14
- import { Spinner } from "@/ui/base/spinner";
15
- import { CreateTodoSheet } from "@/web/surfaces/todos/create_todo_sheet";
16
-
17
- export const AllTodosSurface = () => {
18
- const { data: todos, isPending } = useQuery(convexQuery(api.todos.crud.listTodos, {}));
19
-
20
- const { mutate: updateTodo } = useMutation({
21
- mutationFn: useConvexMutation(api.todos.crud.updateTodo),
22
- });
23
-
24
- const { mutate: deleteTodo } = useMutation({
25
- mutationFn: useConvexMutation(api.todos.crud.deleteTodo),
26
- });
27
-
28
- return (
29
- <main className="flex flex-1 flex-col overflow-auto p-6">
30
- <div className="flex items-center justify-between mb-6">
31
- <h1 className="text-2xl font-semibold">Todos</h1>
32
- <CreateTodoSheet />
33
- </div>
34
-
35
- {isPending && (
36
- <div className="flex flex-1 items-center justify-center">
37
- <Spinner />
38
- </div>
39
- )}
40
-
41
- {!isPending && todos?.length === 0 && (
42
- <div className="flex flex-1 flex-col items-center justify-center gap-2 text-muted-foreground">
43
- <p>No todos yet.</p>
44
- <CreateTodoSheet />
45
- </div>
46
- )}
47
-
48
- {todos && todos.length > 0 && (
49
- <ul className="flex flex-col gap-2 max-w-2xl">
50
- {todos.map((todo) => (
51
- <li
52
- key={todo._id}
53
- className="flex items-center gap-3 rounded-lg border bg-card px-4 py-3"
54
- >
55
- <Checkbox
56
- checked={todo.isCompleted}
57
- onCheckedChange={(checked) =>
58
- updateTodo({
59
- todoId: todo._id as Id<"todos">,
60
- isCompleted: !!checked,
61
- })
62
- }
63
- />
64
- <Link
65
- to={`/todos/${todo._id}`}
66
- className="flex-1 truncate text-sm hover:underline"
67
- style={{
68
- textDecoration: todo.isCompleted ? "line-through" : undefined,
69
- }}
70
- >
71
- {todo.title}
72
- </Link>
73
- <Button
74
- variant="ghost"
75
- size="icon"
76
- className="size-7 shrink-0 text-muted-foreground hover:text-destructive"
77
- onClick={() => deleteTodo({ todoId: todo._id as Id<"todos"> })}
78
- >
79
- <Trash2 className="size-4" />
80
- </Button>
81
- </li>
82
- ))}
83
- </ul>
84
- )}
85
- </main>
86
- );
87
- };
@@ -1,102 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { useConvexMutation } from "@convex-dev/react-query";
6
- import { zodResolver } from "@hookform/resolvers/zod";
7
- import { useMutation } from "@tanstack/react-query";
8
- import { Plus } from "lucide-react";
9
- import { useForm } from "react-hook-form";
10
- import { z } from "zod";
11
-
12
- import { api } from "@/api/_generated/api";
13
- import { Button } from "@/ui/base/button";
14
- import { DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/ui/base/dialog";
15
- import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/ui/base/form";
16
- import { Input } from "@/ui/base/input";
17
- import { Sheet, SheetContent, SheetTrigger } from "@/ui/base/sheet";
18
- import { TextArea } from "@/ui/base/text_area";
19
-
20
- const createTodoSchema = z.object({
21
- title: z.string().min(1, "Title is required"),
22
- description: z.string().optional(),
23
- });
24
-
25
- type CreateTodoSchema = z.infer<typeof createTodoSchema>;
26
-
27
- export const CreateTodoSheet = () => {
28
- const form = useForm<CreateTodoSchema>({
29
- resolver: zodResolver(createTodoSchema),
30
- defaultValues: { title: "", description: "" },
31
- });
32
-
33
- const { mutate: createTodo, isPending } = useMutation({
34
- mutationFn: useConvexMutation(api.todos.crud.createTodo),
35
- onSuccess: () => form.reset(),
36
- });
37
-
38
- const handleSubmit = form.handleSubmit((values) => {
39
- createTodo(values);
40
- });
41
-
42
- return (
43
- <Sheet>
44
- <SheetTrigger asChild>
45
- <Button size="sm">
46
- <Plus className="mr-2 size-4" />
47
- New Todo
48
- </Button>
49
- </SheetTrigger>
50
- <SheetContent className="sm:max-w-[480px]">
51
- <DialogHeader>
52
- <DialogTitle>New Todo</DialogTitle>
53
- <DialogDescription>Add a new todo to your list.</DialogDescription>
54
- </DialogHeader>
55
- <Form {...form}>
56
- <form
57
- onSubmit={handleSubmit}
58
- className="flex flex-col gap-4 pt-4"
59
- onKeyDown={(e) => {
60
- if (e.key === "Enter" && !e.shiftKey) {
61
- e.preventDefault();
62
- handleSubmit();
63
- }
64
- }}
65
- >
66
- <FormField
67
- control={form.control}
68
- name="title"
69
- render={({ field }) => (
70
- <FormItem>
71
- <FormLabel>Title</FormLabel>
72
- <FormControl>
73
- <Input placeholder="Buy groceries" {...field} />
74
- </FormControl>
75
- <FormMessage />
76
- </FormItem>
77
- )}
78
- />
79
- <FormField
80
- control={form.control}
81
- name="description"
82
- render={({ field }) => (
83
- <FormItem>
84
- <FormLabel>Description</FormLabel>
85
- <FormControl>
86
- <TextArea placeholder="Optional details..." rows={3} {...field} />
87
- </FormControl>
88
- <FormMessage />
89
- </FormItem>
90
- )}
91
- />
92
- <DialogFooter>
93
- <Button type="submit" disabled={isPending}>
94
- {isPending ? "Creating…" : "Create Todo"}
95
- </Button>
96
- </DialogFooter>
97
- </form>
98
- </Form>
99
- </SheetContent>
100
- </Sheet>
101
- );
102
- };
@@ -1,81 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { convexQuery, useConvexMutation } from "@convex-dev/react-query";
6
- import { useMutation, useQuery } from "@tanstack/react-query";
7
- import { ArrowLeft } from "lucide-react";
8
- import { Link } from "react-router";
9
-
10
- import { api } from "@/api/_generated/api";
11
- import type { TodoId } from "@/api/todos/types";
12
- import { Badge } from "@/ui/base/badge";
13
- import { Button } from "@/ui/base/button";
14
- import { Checkbox } from "@/ui/base/checkbox";
15
- import { Spinner } from "@/ui/base/spinner";
16
-
17
- type SingleTodoSurfaceProps = {
18
- todoId: TodoId;
19
- };
20
-
21
- export const SingleTodoSurface = ({ todoId }: SingleTodoSurfaceProps) => {
22
- const { data: todo, isPending } = useQuery(convexQuery(api.todos.crud.getTodo, { todoId }));
23
-
24
- const { mutate: updateTodo } = useMutation({
25
- mutationFn: useConvexMutation(api.todos.crud.updateTodo),
26
- });
27
-
28
- if (isPending) {
29
- return (
30
- <main className="flex flex-1 items-center justify-center">
31
- <Spinner />
32
- </main>
33
- );
34
- }
35
-
36
- if (!todo) {
37
- return (
38
- <main className="flex flex-1 flex-col items-center justify-center gap-4">
39
- <p className="text-muted-foreground">Todo not found.</p>
40
- <Button variant="outline" asChild>
41
- <Link to="/todos">
42
- <ArrowLeft className="mr-2 size-4" />
43
- Back to todos
44
- </Link>
45
- </Button>
46
- </main>
47
- );
48
- }
49
-
50
- return (
51
- <main className="flex flex-1 flex-col gap-6 overflow-auto p-6 max-w-2xl">
52
- <Button variant="ghost" className="w-fit -ml-2 text-muted-foreground" asChild>
53
- <Link to="/todos">
54
- <ArrowLeft className="mr-2 size-4" />
55
- Back
56
- </Link>
57
- </Button>
58
-
59
- <div className="flex items-start gap-3">
60
- <Checkbox
61
- className="mt-1"
62
- checked={todo.isCompleted}
63
- onCheckedChange={(checked) => updateTodo({ todoId, isCompleted: !!checked })}
64
- />
65
- <div className="flex flex-col gap-2">
66
- <h1
67
- className="text-2xl font-semibold"
68
- style={{ textDecoration: todo.isCompleted ? "line-through" : undefined }}
69
- >
70
- {todo.title}
71
- </h1>
72
- <Badge variant={todo.isCompleted ? "secondary" : "default"}>
73
- {todo.isCompleted ? "Completed" : "In progress"}
74
- </Badge>
75
- </div>
76
- </div>
77
-
78
- {todo.description && <p className="text-muted-foreground">{todo.description}</p>}
79
- </main>
80
- );
81
- };
File without changes
File without changes
File without changes
File without changes