create-aron-app 0.1.7 → 0.1.10

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 (169) hide show
  1. package/.cursor/worktrees.json +3 -0
  2. package/README.md +24 -31
  3. package/dist/index.js +38 -49
  4. package/package.json +3 -7
  5. package/templates/.cursor/rules/backend.mdc +112 -0
  6. package/templates/.cursor/rules/coding_standards.mdc +85 -4
  7. package/templates/.cursor/rules/frontend_architecture.mdc +334 -0
  8. package/templates/.env.example +6 -0
  9. package/templates/apps/{react-router → web}/.react-router/types/+routes.ts +11 -6
  10. package/templates/apps/{react-router/.react-router/types/src/routes/(dashboard)/todos → web/.react-router/types/src/routes/(dashboard)/(todos)}/+types/[id].ts +5 -2
  11. package/templates/apps/{react-router/.react-router/types/src/routes/(dashboard)/todos → web/.react-router/types/src/routes/(dashboard)/(todos)}/+types/index.ts +5 -2
  12. package/templates/apps/web/.react-router/types/src/routes/(dashboard)/(todos)/+types/layout.ts +65 -0
  13. package/templates/apps/{react-router → web}/project.json +11 -4
  14. package/templates/apps/{react-router → web}/react-router.config.ts +1 -1
  15. package/templates/apps/web/src/libs/convex_query_client.ts +11 -0
  16. package/templates/apps/web/src/libs/react_query_client.ts +17 -0
  17. package/templates/apps/web/src/libs/server/auth.ts +32 -0
  18. package/templates/apps/web/src/libs/server/protected.ts +17 -0
  19. package/templates/apps/web/src/providers/api_auth_provider.tsx +26 -0
  20. package/templates/apps/web/src/providers/global_provider.tsx +28 -0
  21. package/templates/apps/web/src/providers/navigation_loading_bar_provider.tsx +72 -0
  22. package/templates/apps/web/src/root.tsx +68 -0
  23. package/templates/apps/web/src/routes/(dashboard)/(todos)/[id].tsx +33 -0
  24. package/templates/apps/web/src/routes/(dashboard)/(todos)/index.tsx +26 -0
  25. package/templates/apps/web/src/routes/(dashboard)/(todos)/layout.tsx +9 -0
  26. package/templates/apps/{react-router → web}/src/routes/(dashboard)/index.tsx +3 -2
  27. package/templates/apps/web/src/routes/(dashboard)/layout.tsx +20 -0
  28. package/templates/apps/{react-router → web}/src/routes.ts +4 -2
  29. package/templates/apps/{react-router → web}/src/surfaces/sidebar/install.tsx +1 -5
  30. package/templates/apps/{react-router → web}/src/surfaces/sidebar/layout.tsx +24 -15
  31. package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/all_todos.tsx +1 -1
  32. package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/all_todos_controller.ts +1 -1
  33. package/templates/apps/web/src/surfaces/todos/all_todos/bootstrap.ts +21 -0
  34. package/templates/apps/{react-router → web}/src/surfaces/todos/single_todo/bootstrap.ts +4 -5
  35. package/templates/apps/{nextjs → web}/src/surfaces/todos/single_todo/header/create.tsx +4 -6
  36. package/templates/apps/{react-router → web}/src/surfaces/todos/single_todo/single_todo_controller.ts +1 -1
  37. package/templates/components.json +20 -0
  38. package/templates/gitignore +60 -0
  39. package/templates/nx.json +0 -11
  40. package/templates/package.json +2 -3
  41. package/templates/shared/assets/src/styles/global.css +14 -8
  42. package/templates/shared/ui/src/base/collapsible.tsx +31 -0
  43. package/templates/shared/ui/src/base/hover-card.tsx +42 -0
  44. package/templates/shared/ui/src/base/input-group.tsx +168 -0
  45. package/templates/shared/ui/src/base/panel.tsx +93 -0
  46. package/templates/shared/ui/src/hooks/use_mobile.tsx +1 -1
  47. package/templates/shared/ui/src/hooks/use_query_params.tsx +6 -7
  48. package/templates/shared/utils/src/convex.ts +2 -1
  49. package/templates/tsconfig.base.json +2 -4
  50. package/templates/.cursor/commands/builder.md +0 -0
  51. package/templates/.cursor/rules/api_architecture.mdc +0 -262
  52. package/templates/.cursor/rules/convex_rules.mdc +0 -331
  53. package/templates/.cursor/rules/frontend_architecture_core.mdc +0 -495
  54. package/templates/.cursor/rules/frontend_architecture_nextjs.mdc +0 -458
  55. package/templates/.cursor/rules/frontend_architecture_reactrouter.mdc +0 -473
  56. package/templates/.github/workflows/ci.yml +0 -29
  57. package/templates/apps/api/tsconfig.json +0 -23
  58. package/templates/apps/nextjs/.env.example +0 -10
  59. package/templates/apps/nextjs/index.d.ts +0 -6
  60. package/templates/apps/nextjs/next-env.d.ts +0 -5
  61. package/templates/apps/nextjs/next.config.js +0 -22
  62. package/templates/apps/nextjs/postcss.config.js +0 -17
  63. package/templates/apps/nextjs/project.json +0 -22
  64. package/templates/apps/nextjs/src/app/(auth)/layout.tsx +0 -21
  65. package/templates/apps/nextjs/src/app/(auth)/not-allowed/page.tsx +0 -23
  66. package/templates/apps/nextjs/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx +0 -15
  67. package/templates/apps/nextjs/src/app/(dashboard)/layout.tsx +0 -22
  68. package/templates/apps/nextjs/src/app/(dashboard)/page.tsx +0 -12
  69. package/templates/apps/nextjs/src/app/(dashboard)/todos/[id]/page.tsx +0 -26
  70. package/templates/apps/nextjs/src/app/(dashboard)/todos/page.tsx +0 -19
  71. package/templates/apps/nextjs/src/app/app.css +0 -3
  72. package/templates/apps/nextjs/src/app/layout.tsx +0 -26
  73. package/templates/apps/nextjs/src/middleware.ts +0 -18
  74. package/templates/apps/nextjs/src/providers/convex_provider.tsx +0 -44
  75. package/templates/apps/nextjs/src/surfaces/home/home.tsx +0 -27
  76. package/templates/apps/nextjs/src/surfaces/home/layout.tsx +0 -44
  77. package/templates/apps/nextjs/src/surfaces/home/main/create.tsx +0 -34
  78. package/templates/apps/nextjs/src/surfaces/sidebar/install.tsx +0 -23
  79. package/templates/apps/nextjs/src/surfaces/sidebar/layout.tsx +0 -118
  80. package/templates/apps/nextjs/src/surfaces/sidebar/nav_main/create.tsx +0 -19
  81. package/templates/apps/nextjs/src/surfaces/sidebar/nav_main/nav_config.ts +0 -22
  82. package/templates/apps/nextjs/src/surfaces/sidebar/nav_main/nav_main.tsx +0 -25
  83. package/templates/apps/nextjs/src/surfaces/sidebar/nav_secondary/create.tsx +0 -21
  84. package/templates/apps/nextjs/src/surfaces/sidebar/nav_secondary/nav_secondary.tsx +0 -33
  85. package/templates/apps/nextjs/src/surfaces/sidebar/sidebar.tsx +0 -23
  86. package/templates/apps/nextjs/src/surfaces/sidebar/ui/sidebar_nav_link.tsx +0 -39
  87. package/templates/apps/nextjs/src/surfaces/sidebar/user_menu/create.tsx +0 -28
  88. package/templates/apps/nextjs/src/surfaces/sidebar/user_menu/user_menu.tsx +0 -42
  89. package/templates/apps/nextjs/src/surfaces/todos/all_todos/all_todos.tsx +0 -29
  90. package/templates/apps/nextjs/src/surfaces/todos/all_todos/all_todos_controller.ts +0 -61
  91. package/templates/apps/nextjs/src/surfaces/todos/all_todos/bootstrap.ts +0 -21
  92. package/templates/apps/nextjs/src/surfaces/todos/all_todos/header/create.tsx +0 -23
  93. package/templates/apps/nextjs/src/surfaces/todos/all_todos/install.tsx +0 -23
  94. package/templates/apps/nextjs/src/surfaces/todos/all_todos/layout.tsx +0 -44
  95. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/create.tsx +0 -49
  96. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/main.tsx +0 -70
  97. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/new_todo_sheet/create.tsx +0 -56
  98. package/templates/apps/nextjs/src/surfaces/todos/all_todos/main/new_todo_sheet/new_todo_sheet.tsx +0 -99
  99. package/templates/apps/nextjs/src/surfaces/todos/single_todo/bootstrap.ts +0 -32
  100. package/templates/apps/nextjs/src/surfaces/todos/single_todo/header/header.tsx +0 -22
  101. package/templates/apps/nextjs/src/surfaces/todos/single_todo/install.tsx +0 -27
  102. package/templates/apps/nextjs/src/surfaces/todos/single_todo/layout.tsx +0 -55
  103. package/templates/apps/nextjs/src/surfaces/todos/single_todo/main/create.tsx +0 -38
  104. package/templates/apps/nextjs/src/surfaces/todos/single_todo/main/main.tsx +0 -49
  105. package/templates/apps/nextjs/src/surfaces/todos/single_todo/single_todo.tsx +0 -29
  106. package/templates/apps/nextjs/src/surfaces/todos/single_todo/single_todo_controller.ts +0 -13
  107. package/templates/apps/nextjs/src/utils/auth.ts +0 -18
  108. package/templates/apps/nextjs/src/utils/convex.ts +0 -11
  109. package/templates/apps/nextjs/src/utils/font.ts +0 -9
  110. package/templates/apps/nextjs/tsconfig.json +0 -42
  111. package/templates/apps/react-router/src/providers/api_auth_provider.tsx +0 -40
  112. package/templates/apps/react-router/src/root.tsx +0 -37
  113. package/templates/apps/react-router/src/routes/(dashboard)/layout.tsx +0 -37
  114. package/templates/apps/react-router/src/routes/(dashboard)/todos/[id].tsx +0 -19
  115. package/templates/apps/react-router/src/routes/(dashboard)/todos/index.tsx +0 -19
  116. package/templates/apps/react-router/src/surfaces/home/bootstrap.ts +0 -9
  117. package/templates/apps/react-router/src/surfaces/home/install.tsx +0 -17
  118. package/templates/apps/react-router/src/surfaces/sidebar/nav_secondary/create.tsx +0 -21
  119. package/templates/apps/react-router/src/surfaces/sidebar/nav_secondary/nav_secondary.tsx +0 -31
  120. package/templates/apps/react-router/src/surfaces/todos/all_todos/bootstrap.ts +0 -18
  121. package/templates/apps/react-router/src/surfaces/todos/all_todos/main/new_todo_sheet/schema.ts +0 -11
  122. package/templates/apps/react-router/src/surfaces/todos/single_todo/header/create.tsx +0 -32
  123. package/templates/apps/react-router/tsconfig.json +0 -20
  124. package/templates/biome.json +0 -121
  125. package/templates/bun.lock +0 -3187
  126. package/templates/emails/tsconfig.json +0 -5
  127. package/templates/shared/assets/tsconfig.json +0 -5
  128. package/templates/shared/ui/tsconfig.json +0 -8
  129. package/templates/shared/utils/tsconfig.json +0 -5
  130. /package/templates/apps/{react-router → web}/.env.example +0 -0
  131. /package/templates/apps/{react-router → web}/.react-router/types/+future.ts +0 -0
  132. /package/templates/apps/{react-router → web}/.react-router/types/+server-build.d.ts +0 -0
  133. /package/templates/apps/{react-router → web}/.react-router/types/src/+types/root.ts +0 -0
  134. /package/templates/apps/{react-router → web}/.react-router/types/src/routes/(auth)/+types/layout.ts +0 -0
  135. /package/templates/apps/{react-router → web}/.react-router/types/src/routes/(auth)/sign-in/+types/index.ts +0 -0
  136. /package/templates/apps/{react-router → web}/.react-router/types/src/routes/(dashboard)/+types/index.ts +0 -0
  137. /package/templates/apps/{react-router → web}/.react-router/types/src/routes/(dashboard)/+types/layout.ts +0 -0
  138. /package/templates/apps/{react-router → web}/postcss.config.js +0 -0
  139. /package/templates/apps/{react-router → web}/public/favicon.ico +0 -0
  140. /package/templates/apps/{react-router → web}/src/app.css +0 -0
  141. /package/templates/apps/{react-router → web}/src/components/error_boundary.tsx +0 -0
  142. /package/templates/apps/{react-router → web}/src/routes/(auth)/layout.tsx +0 -0
  143. /package/templates/apps/{react-router → web}/src/routes/(auth)/sign-in/index.tsx +0 -0
  144. /package/templates/apps/{nextjs → web}/src/surfaces/home/bootstrap.ts +0 -0
  145. /package/templates/apps/{react-router → web}/src/surfaces/home/home.tsx +0 -0
  146. /package/templates/apps/{nextjs → web}/src/surfaces/home/install.tsx +0 -0
  147. /package/templates/apps/{react-router → web}/src/surfaces/home/layout.tsx +0 -0
  148. /package/templates/apps/{react-router → web}/src/surfaces/home/main/create.tsx +0 -0
  149. /package/templates/apps/{react-router → web}/src/surfaces/sidebar/nav_main/create.tsx +0 -0
  150. /package/templates/apps/{react-router → web}/src/surfaces/sidebar/nav_main/nav_main.tsx +0 -0
  151. /package/templates/apps/{react-router → web}/src/surfaces/sidebar/sidebar.tsx +0 -0
  152. /package/templates/apps/{react-router → web}/src/surfaces/sidebar/user_menu/create.tsx +0 -0
  153. /package/templates/apps/{react-router → web}/src/surfaces/sidebar/user_menu/user_menu.tsx +0 -0
  154. /package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/header/create.tsx +0 -0
  155. /package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/install.tsx +0 -0
  156. /package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/layout.tsx +0 -0
  157. /package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/main/create.tsx +0 -0
  158. /package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/main/main.tsx +0 -0
  159. /package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/main/new_todo_sheet/create.tsx +0 -0
  160. /package/templates/apps/{react-router → web}/src/surfaces/todos/all_todos/main/new_todo_sheet/new_todo_sheet.tsx +0 -0
  161. /package/templates/apps/{nextjs → web}/src/surfaces/todos/all_todos/main/new_todo_sheet/schema.ts +0 -0
  162. /package/templates/apps/{react-router → web}/src/surfaces/todos/single_todo/header/header.tsx +0 -0
  163. /package/templates/apps/{react-router → web}/src/surfaces/todos/single_todo/install.tsx +0 -0
  164. /package/templates/apps/{react-router → web}/src/surfaces/todos/single_todo/layout.tsx +0 -0
  165. /package/templates/apps/{react-router → web}/src/surfaces/todos/single_todo/main/create.tsx +0 -0
  166. /package/templates/apps/{react-router → web}/src/surfaces/todos/single_todo/main/main.tsx +0 -0
  167. /package/templates/apps/{react-router → web}/src/surfaces/todos/single_todo/single_todo.tsx +0 -0
  168. /package/templates/apps/{react-router → web}/vite.config.ts +0 -0
  169. /package/templates/emails/{welcome_email.tsx → src/welcome_email.tsx} +0 -0
@@ -1,38 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- "use client";
6
-
7
- import { convexQuery } from "@convex-dev/react-query";
8
- import { useQuery } from "@tanstack/react-query";
9
- import { observer } from "mobx-react-lite";
10
-
11
- import { api } from "@/api/_generated/api";
12
-
13
- import type { SingleTodoBootstrap } from "@/web/surfaces/todos/single_todo/bootstrap";
14
- import type { SingleTodoController } from "@/web/surfaces/todos/single_todo/single_todo_controller";
15
- import { Main } from "@/web/surfaces/todos/single_todo/main/main";
16
-
17
- export type CreateMainOpts = {
18
- controller: SingleTodoController;
19
- bootstrap: SingleTodoBootstrap;
20
- };
21
-
22
- export const createMain = ({ controller, bootstrap }: CreateMainOpts) => {
23
- return observer(() => {
24
- const { data: todo } = useQuery({
25
- ...convexQuery(api.todos.crud.getTodo, { todoId: bootstrap.todoId }),
26
- initialData: bootstrap.todo as never,
27
- });
28
-
29
- return (
30
- <Main
31
- todo={todo}
32
- onToggle={(todoId, isCompleted) => {
33
- void controller.updateTodo({ todoId, isCompleted });
34
- }}
35
- />
36
- );
37
- });
38
- };
@@ -1,49 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- "use client";
6
-
7
- import type { Todo, TodoId } from "@/api/todos/types";
8
- import { Badge } from "@/ui/base/badge";
9
- import { Checkbox } from "@/ui/base/checkbox";
10
-
11
- type MainProps = {
12
- todo: Todo | undefined;
13
- onToggle: (todoId: TodoId, isCompleted: boolean) => void;
14
- };
15
-
16
- export const Main = ({ todo, onToggle }: MainProps) => {
17
- if (!todo) {
18
- return null;
19
- }
20
-
21
- return (
22
- <main className="flex max-w-2xl flex-1 flex-col gap-6 overflow-auto p-6">
23
- <div className="flex items-start gap-3">
24
- <Checkbox
25
- className="mt-1"
26
- checked={todo.isCompleted}
27
- onCheckedChange={(checked) =>
28
- onToggle(todo._id, !!checked)
29
- }
30
- />
31
- <div className="flex flex-col gap-2">
32
- <h1
33
- className="text-2xl font-semibold"
34
- style={{
35
- textDecoration: todo.isCompleted ? "line-through" : undefined,
36
- }}
37
- >
38
- {todo.title}
39
- </h1>
40
- <Badge variant={todo.isCompleted ? "secondary" : "default"}>
41
- {todo.isCompleted ? "Completed" : "In progress"}
42
- </Badge>
43
- </div>
44
- </div>
45
-
46
- {todo.description ? <p className="text-muted-foreground">{todo.description}</p> : null}
47
- </main>
48
- );
49
- };
@@ -1,29 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- "use client";
6
-
7
- import { useRouter } from "next/navigation";
8
- import { useMemo, useRef } from "react";
9
-
10
- import type { SingleTodoBootstrap } from "@/web/surfaces/todos/single_todo/bootstrap";
11
- import { installSingleTodo } from "@/web/surfaces/todos/single_todo/install";
12
- import { createLayout } from "@/web/surfaces/todos/single_todo/layout";
13
-
14
- export type SingleTodoProps = {
15
- bootstrap: SingleTodoBootstrap;
16
- };
17
-
18
- export const SingleTodo = ({ bootstrap }: SingleTodoProps) => {
19
- const router = useRouter();
20
- const { layout, Layout } = useMemo(() => createLayout(), []);
21
- const installed = useRef(false);
22
-
23
- if (!installed.current) {
24
- installed.current = true;
25
- installSingleTodo({ layout, bootstrap, router });
26
- }
27
-
28
- return <Layout />;
29
- };
@@ -1,13 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { api } from "@/api/_generated/api";
6
- import type { TodoId } from "@/api/todos/types";
7
- import { convex } from "@/web/utils/convex";
8
-
9
- export class SingleTodoController {
10
- async updateTodo(args: { todoId: TodoId; isCompleted: boolean }) {
11
- await convex.mutation(api.todos.crud.updateTodo, args);
12
- }
13
- }
@@ -1,18 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- // "use server";
6
-
7
- import { auth } from "@clerk/nextjs/server";
8
- import { redirect } from "next/navigation";
9
-
10
- export const getAuthToken = async () => {
11
- const token = await (await auth()).getToken({ template: "convex" });
12
-
13
- if (!token) {
14
- return redirect("/sign-in");
15
- }
16
-
17
- return token;
18
- };
@@ -1,11 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2025.
3
- */
4
-
5
- import { ConvexClient } from "convex/browser";
6
-
7
- if (!process.env.NEXT_PUBLIC_CONVEX_URL) {
8
- throw new Error("Missing NEXT_PUBLIC_CONVEX_URL in your .env file");
9
- }
10
-
11
- export const convex = new ConvexClient(process.env.NEXT_PUBLIC_CONVEX_URL);
@@ -1,9 +0,0 @@
1
- import { Inter } from "next/font/google";
2
-
3
- const inter = Inter({
4
- variable: "--font-inter",
5
- subsets: ["latin"],
6
- display: "swap",
7
- });
8
-
9
- export const fontCn = `${inter.className}`;
@@ -1,42 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "jsx": "preserve",
5
- "lib": ["dom", "dom.iterable", "esnext"],
6
- "noEmit": true,
7
- "emitDeclarationOnly": false,
8
- "esModuleInterop": true,
9
- "resolveJsonModule": true,
10
- "allowJs": true,
11
- "allowSyntheticDefaultImports": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "incremental": true,
14
- "plugins": [{"name": "next"}],
15
- "outDir": "dist",
16
- "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo"
17
- },
18
- "include": [
19
- ".next/types/**/*.ts",
20
- "index.d.ts",
21
- "next-env.d.ts",
22
- "next-env.d.ts",
23
- "src/**/*.js",
24
- "src/**/*.jsx",
25
- "src/**/*.ts",
26
- "src/**/*.tsx",
27
- "../../dist/apps/web/.next/types/**/*.ts",
28
- "../../apps/web/dist/.next/types/**/*.ts"
29
- ],
30
- "exclude": [
31
- "out-tsc",
32
- "dist",
33
- "node_modules",
34
- "jest.config.ts",
35
- "src/**/*.spec.ts",
36
- "src/**/*.test.ts",
37
- ".next",
38
- "eslint.config.js",
39
- "eslint.config.cjs",
40
- "eslint.config.mjs"
41
- ]
42
- }
@@ -1,40 +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
- export { convex, queryClient };
27
-
28
- type ApiAuthProviderProps = {
29
- children: React.ReactNode;
30
- };
31
-
32
- export const ApiAuthProvider = ({ children }: ApiAuthProviderProps) => {
33
- return (
34
- <ClerkProvider publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY as string}>
35
- <ConvexProviderWithClerk client={convex} useAuth={useAuth}>
36
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
37
- </ConvexProviderWithClerk>
38
- </ClerkProvider>
39
- );
40
- };
@@ -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,37 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { convexQuery } from "@convex-dev/react-query";
6
- import type { CSSProperties } from "react";
7
- import { Outlet, redirect } from "react-router";
8
-
9
- import { api } from "@/api/_generated/api";
10
- import { SidebarInset, SidebarProvider } from "@/ui/base/side_bar";
11
- import { queryClient } from "@/web/providers/api_auth_provider";
12
- import { Sidebar } from "@/web/surfaces/sidebar/sidebar";
13
-
14
- import type { Route } from "./+types/layout";
15
-
16
- export async function clientLoader(_args: Route.ClientLoaderArgs) {
17
- try {
18
- await queryClient.ensureQueryData(convexQuery(api.todos.crud.listTodos, {}));
19
- } catch {
20
- return redirect("/sign-in");
21
- }
22
- return null;
23
- }
24
-
25
- export default function DashboardLayout() {
26
- return (
27
- <SidebarProvider
28
- style={{ "--sidebar-width": "265px" } as CSSProperties}
29
- defaultOpen={true}
30
- >
31
- <Sidebar />
32
- <SidebarInset>
33
- <Outlet />
34
- </SidebarInset>
35
- </SidebarProvider>
36
- );
37
- }
@@ -1,19 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import type { Route } from "@/router/src/routes/(dashboard)/+types";
6
- import { bootstrapSingleTodo } from "@/web/surfaces/todos/single_todo/bootstrap";
7
- import { SingleTodo } from "@/web/surfaces/todos/single_todo/single_todo";
8
-
9
- export async function clientLoader({ params }: Route.ClientLoaderArgs) {
10
- return bootstrapSingleTodo({ params });
11
- }
12
-
13
- export function meta({ loaderData: bootstrap }: Route.MetaArgs) {
14
- return [{ title: bootstrap?.todo?.title ?? "Todo" }, { name: "description", content: "Todo" }];
15
- }
16
-
17
- export default function TodoPage({ loaderData: bootstrap }: Route.ComponentProps) {
18
- return <SingleTodo bootstrap={bootstrap} />;
19
- }
@@ -1,19 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import type { Route } from "./+types/index";
6
- import { AllTodos } from "../../../surfaces/todos/all_todos/all_todos";
7
- import { bootstrapAllTodos } from "../../../surfaces/todos/all_todos/bootstrap";
8
-
9
- export async function clientLoader(_args: Route.ClientLoaderArgs) {
10
- return bootstrapAllTodos();
11
- }
12
-
13
- export function meta({ loaderData: bootstrap }: Route.MetaArgs) {
14
- return [{ title: "Todos" }, { name: "description", content: "Todos" }];
15
- }
16
-
17
- export default function TodosPage({ loaderData: bootstrap }: Route.ComponentProps) {
18
- return <AllTodos bootstrap={bootstrap} />;
19
- }
@@ -1,9 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- export type HomeBootstrap = Record<string, never>;
6
-
7
- export const bootstrapHome = async (): Promise<HomeBootstrap> => {
8
- return {};
9
- };
@@ -1,17 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import type { HomeBootstrap } from "@/web/surfaces/home/bootstrap";
6
- import type { HomeLayoutController } from "@/web/surfaces/home/layout";
7
-
8
- export type InstallHomeOpts = {
9
- layout: HomeLayoutController;
10
- bootstrap: HomeBootstrap;
11
- };
12
-
13
- export const installHome = ({ layout, bootstrap }: InstallHomeOpts) => {
14
- import("@/web/surfaces/home/main/create").then(({ createMain }) => {
15
- layout.setMain(createMain({ bootstrap }));
16
- });
17
- };
@@ -1,21 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { observer } from "mobx-react-lite";
6
- import { useLocation } from "react-router";
7
-
8
- import { useSidebar } from "@/ui/base/side_bar";
9
-
10
- import { NavSecondary } from "@/web/surfaces/sidebar/nav_secondary/nav_secondary";
11
-
12
- export const createNavSecondary = () => {
13
- return observer(() => {
14
- const location = useLocation();
15
- const { setOpenMobile } = useSidebar();
16
-
17
- return (
18
- <NavSecondary pathname={location.pathname} onNavigate={() => setOpenMobile(false)} />
19
- );
20
- });
21
- };
@@ -1,31 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { Settings } from "lucide-react";
6
- import { Link } from "react-router";
7
-
8
- import { SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "@/ui/base/side_bar";
9
-
10
- type NavSecondaryProps = {
11
- pathname: string;
12
- onNavigate: () => void;
13
- };
14
-
15
- export const NavSecondary = ({ pathname, onNavigate }: NavSecondaryProps) => {
16
- const settingsPath = "/settings";
17
- const isActive = pathname === settingsPath || pathname.startsWith(`${settingsPath}/`);
18
-
19
- return (
20
- <SidebarMenu>
21
- <SidebarMenuItem>
22
- <SidebarMenuButton isActive={isActive} asChild onClick={onNavigate}>
23
- <Link to={settingsPath}>
24
- <Settings className="size-4" />
25
- <span>Settings</span>
26
- </Link>
27
- </SidebarMenuButton>
28
- </SidebarMenuItem>
29
- </SidebarMenu>
30
- );
31
- };
@@ -1,18 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import { convexQuery } from "@convex-dev/react-query";
6
-
7
- import { api } from "@/api/_generated/api";
8
- import type { Todo } from "@/api/todos/types";
9
- import { queryClient } from "@/web/providers/api_auth_provider";
10
-
11
- export type AllTodosBootstrap = {
12
- todos: Todo[];
13
- };
14
-
15
- export const bootstrapAllTodos = async (): Promise<AllTodosBootstrap> => {
16
- const todos = await queryClient.ensureQueryData(convexQuery(api.todos.crud.listTodos, {}));
17
- return { todos };
18
- };
@@ -1,11 +0,0 @@
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
- });
@@ -1,32 +0,0 @@
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
- };
@@ -1,20 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "lib": ["DOM", "DOM.Iterable", "ES2022"],
5
- "types": ["node", "vite/client"],
6
- "target": "ES2022",
7
- "module": "ES2022",
8
- "moduleResolution": "bundler",
9
- "jsx": "react-jsx",
10
- "rootDirs": [".", "./.react-router/types"],
11
- "esModuleInterop": true,
12
- "verbatimModuleSyntax": true,
13
- "noEmit": true,
14
- "resolveJsonModule": true,
15
- "skipLibCheck": true,
16
- "strict": true
17
- },
18
- "include": ["**/*", "**/.server/**/*", "**/.client/**/*", ".react-router/types/**/*"],
19
- "exclude": ["node_modules", "dist", "build", "public"]
20
- }
@@ -1,121 +0,0 @@
1
- {
2
- "$schema": "https://biomejs.dev/schemas/2.2.6/schema.json",
3
- "assist": {
4
- "actions": {
5
- "source": {
6
- "organizeImports": {
7
- "level": "on",
8
- "options": {
9
- "groups": [
10
- ":BUN:",
11
- ":BLANK_LINE:",
12
- ":NODE:",
13
- ":BLANK_LINE:",
14
- ":PACKAGE:",
15
- ":BLANK_LINE:",
16
- ":PACKAGE_WITH_PROTOCOL:",
17
- ":BLANK_LINE:",
18
- ":ALIAS:",
19
- ":BLANK_LINE:",
20
- ":PATH:",
21
- ":BLANK_LINE:",
22
- ":URL:"
23
- ]
24
- }
25
- },
26
- "recommended": true
27
- }
28
- },
29
- "enabled": true
30
- },
31
- "css": {
32
- "parser": {
33
- "tailwindDirectives": true
34
- },
35
- "formatter": {
36
- "enabled": true,
37
- "indentStyle": "space",
38
- "indentWidth": 2,
39
- "lineWidth": 80,
40
- "quoteStyle": "double"
41
- },
42
- "linter": {
43
- "enabled": true
44
- }
45
- },
46
- "files": {
47
- "ignoreUnknown": false,
48
- "includes": [
49
- "**/*",
50
- "!.nx",
51
- "!**/*/.next",
52
- "!node_modules",
53
- "!**/*/dist",
54
- "!**/*/output",
55
- "!**/*/public",
56
- "!**/*/tmp",
57
- "!convex/_generated/**/*",
58
- "!convex/_generated/**/*.d.ts",
59
- "!package.json"
60
- ]
61
- },
62
- "formatter": {
63
- "enabled": true,
64
- "indentStyle": "space"
65
- },
66
- "javascript": {
67
- "formatter": {
68
- "indentStyle": "space",
69
- "indentWidth": 2,
70
- "lineEnding": "lf",
71
- "lineWidth": 100,
72
- "quoteStyle": "double"
73
- }
74
- },
75
- "json": {
76
- "formatter": {
77
- "enabled": true,
78
- "indentStyle": "space",
79
- "indentWidth": 2,
80
- "lineEnding": "lf",
81
- "lineWidth": 100
82
- },
83
- "linter": {
84
- "enabled": true
85
- }
86
- },
87
- "linter": {
88
- "enabled": true,
89
- "rules": {
90
- "correctness": {
91
- "noUnusedImports": {
92
- "fix": "safe",
93
- "level": "error"
94
- },
95
- "useExhaustiveDependencies": "warn"
96
- },
97
- "recommended": true,
98
- "style": {
99
- "noInferrableTypes": "error",
100
- "useBlockStatements": {
101
- "level": "error",
102
- "fix": "safe"
103
- },
104
- "noParameterAssign": "warn",
105
- "noUnusedTemplateLiteral": "error",
106
- "noUselessElse": "error",
107
- "useAsConstAssertion": "error",
108
- "useDefaultParameterLast": "error",
109
- "useEnumInitializers": "error",
110
- "useNumberNamespace": "error",
111
- "useSelfClosingElements": "error",
112
- "useSingleVarDeclarator": "error"
113
- }
114
- }
115
- },
116
- "vcs": {
117
- "clientKind": "git",
118
- "enabled": false,
119
- "useIgnoreFile": false
120
- }
121
- }