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,268 +0,0 @@
1
- ---
2
- description: Frontend coding standards for the Next.js web app. Covers TanStack Query + Convex data fetching, component structure, form handling, and UI patterns.
3
- globs: apps/web/**/*.tsx,apps/web/**/*.ts
4
- ---
5
-
6
- # Frontend Rules
7
-
8
- ## Surfaces & File Structure
9
-
10
- ### Surfaces as Route Entry Points
11
-
12
- Every route must have a corresponding **surface** — the single entry point for that page. Surfaces are isolated vertical slices: they own their data fetching and pass data strictly downward to child components. Pages are thin wrappers that simply render the surface.
13
-
14
- ```
15
- app/(dashboard)/todos/page.tsx → renders <AllTodosSurface />
16
- app/(dashboard)/todos/[id]/page.tsx → renders <SingleTodoSurface />
17
- ```
18
-
19
- ```typescript
20
- // app/(dashboard)/todos/page.tsx
21
- import { AllTodosSurface } from "@/surfaces/todos/all_todos_surface";
22
-
23
- export default function TodosPage() {
24
- return <AllTodosSurface />;
25
- }
26
- ```
27
-
28
- ### Naming Convention
29
-
30
- All file names must be **snake_case** (e.g. `all_todos_surface.tsx`, `create_todo_sheet.tsx`).
31
-
32
- Use **`All`** for list pages and **`Single`** for id-specific pages — both in the surface name and the file name:
33
-
34
- | Route | Surface component | File |
35
- |---|---|---|
36
- | `/todos` | `AllTodosSurface` | `surfaces/todos/all_todos_surface.tsx` |
37
- | `/todos/[id]` | `SingleTodoSurface` | `surfaces/todos/single_todo_surface.tsx` |
38
-
39
- ### Component Placement
40
-
41
- | What | Where |
42
- |---|---|
43
- | Shared components (used across surfaces) | `src/ui/` |
44
- | Components scoped to one surface | inside that surface's folder |
45
- | Multiple shared components within a surface | `src/surfaces/<feature>/ui/` subfolder |
46
- | Providers | `src/providers/` |
47
-
48
- ```
49
- src/
50
- surfaces/
51
- todos/
52
- all_todos_surface.tsx
53
- single_todo_surface.tsx
54
- ui/ ← shared components for this surface only
55
- todo_card.tsx
56
- todo_filters.tsx
57
- ui/ ← truly shared across the app
58
- sidebar/
59
- sidebar.tsx
60
- providers/
61
- convex_provider.tsx
62
- ```
63
-
64
-
65
-
66
-
67
-
68
- ## Data Fetching with TanStack Query
69
-
70
- **ALWAYS use TanStack Query for Convex queries and mutations**, never the direct Convex hooks.
71
-
72
- ### Queries
73
-
74
- ```typescript
75
- import { useQuery } from "@tanstack/react-query";
76
- import { convexQuery } from "@convex-dev/react-query";
77
- import { api } from "@/api/_generated/api";
78
-
79
- // Basic query
80
- const { data: todos } = useQuery(
81
- convexQuery(api.todos.crud.listTodos, { userId: user.id }),
82
- );
83
-
84
- // Conditional / skipped query
85
- const { data: todos } = useQuery(
86
- convexQuery(
87
- api.todos.crud.listTodos,
88
- user?.id ? { userId: user.id } : "skip"
89
- ),
90
- );
91
- ```
92
-
93
- ### Mutations
94
-
95
- ```typescript
96
- import { useMutation } from "@tanstack/react-query";
97
- import { useConvexMutation } from "@convex-dev/react-query";
98
- import { api } from "@/api/_generated/api";
99
-
100
- const { mutate, isPending } = useMutation({
101
- mutationFn: useConvexMutation(api.todos.crud.createTodo),
102
- });
103
-
104
- const handleButtonClick = () => {
105
- mutate({ title, userId });
106
- }
107
-
108
- ```
109
-
110
- ## Component Structure
111
-
112
- ### Declaration
113
-
114
- Always export components as **const arrow functions**:
115
-
116
- ```typescript
117
- // Good
118
- export const ComponentName = ({ prop1, prop2 }: ComponentNameProps) => {
119
- return <div />;
120
- };
121
-
122
- // Bad
123
- export function ComponentName({ prop1, prop2 }: ComponentNameProps) {
124
- return <div />;
125
- }
126
- ```
127
-
128
- ### Props Types
129
-
130
- Always define props as a **separate named type** above the component:
131
-
132
- ```typescript
133
- type ComponentNameProps = {
134
- entityId: Id<"entities">;
135
- onComplete: () => void;
136
- };
137
-
138
- export const ComponentName = ({ entityId, onComplete }: ComponentNameProps) => {
139
- // ...
140
- };
141
- ```
142
-
143
- ## Form Handling
144
-
145
- Use `react-hook-form` + `zod` + TanStack `useMutation`. Standard pattern:
146
-
147
- ```typescript
148
- export const CreateEntityForm = ({ onSuccess }: CreateEntityFormProps) => {
149
- const form = useForm<FormSchema>({
150
- resolver: zodResolver(formSchema),
151
- defaultValues: { title: "" },
152
- });
153
-
154
- const { mutate: createEntity, isPending } = useMutation({
155
- mutationFn: useConvexMutation(api.entities.crud.createEntity),
156
- onSuccess,
157
- });
158
-
159
- const handleSubmit = form.handleSubmit((values) => {
160
- createEntity(values);
161
- });
162
-
163
- return (
164
- <Form {...form}>
165
- <form
166
- onSubmit={handleSubmit}
167
- className="space-y-4"
168
- onKeyDown={(e) => {
169
- if (e.key === "Enter") {
170
- e.preventDefault();
171
- handleSubmit();
172
- }
173
- }}
174
- >
175
- <FormField
176
- control={form.control}
177
- name="title"
178
- render={({ field }) => (
179
- <FormItem>
180
- <FormLabel>Title</FormLabel>
181
- <FormControl>
182
- <Input {...field} />
183
- </FormControl>
184
- <FormMessage />
185
- </FormItem>
186
- )}
187
- />
188
- <Button type="submit" disabled={isPending}>
189
- {isPending ? "Saving..." : "Save"}
190
- </Button>
191
- </form>
192
- </Form>
193
- );
194
- };
195
- ```
196
-
197
- Key rules:
198
- - Store `form.handleSubmit(...)` in a `handleSubmit` const
199
- - Include `onKeyDown` to prevent implicit form submission on Enter
200
- - Use `isPending` for loading states
201
-
202
- ## Sheet / Dialog Components
203
-
204
- ```typescript
205
- export const CreateEntitySheet = ({ entityId }: CreateEntitySheetProps) => {
206
- return (
207
- <Sheet>
208
- <SheetTrigger asChild>
209
- <Button>
210
- <PlusIcon className="mr-2 h-4 w-4" />
211
- Add Entity
212
- </Button>
213
- </SheetTrigger>
214
- <SheetContent className="sm:max-w-[500px]">
215
- <DialogHeader>
216
- <DialogTitle>Add Entity</DialogTitle>
217
- <DialogDescription>Fill in the details below.</DialogDescription>
218
- </DialogHeader>
219
- {/* form content */}
220
- <DialogFooter>
221
- <Button type="submit">Save</Button>
222
- </DialogFooter>
223
- </SheetContent>
224
- </Sheet>
225
- );
226
- };
227
- ```
228
-
229
- - Use `SheetContent` with `DialogHeader` / `DialogTitle` / `DialogDescription` for consistent styling
230
- - Use `DialogFooter` for action buttons
231
-
232
- ## Import Aliases
233
-
234
- Always use alias-based imports — never relative paths outside the same directory:
235
-
236
- ```typescript
237
- import { api } from "@/api/_generated/api";
238
- import { Button } from "@/ui/base/button";
239
- import { SomeUtil } from "@/utils/some_util";
240
- ```
241
-
242
-
243
- ## Routing
244
-
245
- The app uses Next.js App Router:
246
-
247
- | Path | Description |
248
- |---|---|
249
- | `(auth)/sign-in` | Clerk sign-in (public) |
250
- | `(dashboard)/` | Authenticated area — wrapped in sidebar layout |
251
-
252
- Add new authenticated pages inside `apps/web/src/app/(dashboard)/`.
253
-
254
- ## Sidebar Navigation
255
-
256
- To add a nav item, update `apps/web/src/components/sidebar/sidebar.tsx`:
257
-
258
- ```typescript
259
- export const nav = {
260
- main: [
261
- { id: "dashboard", title: "Dashboard", url: "/", icon: HomeIcon },
262
- { id: "my-feature", title: "My Feature", url: "/my-feature", icon: SomeIcon },
263
- ],
264
- secondary: [
265
- { id: "settings", title: "Settings", url: "/settings", icon: SettingsIcon },
266
- ],
267
- };
268
- ```
@@ -1,3 +0,0 @@
1
- CLERK_SECRET_KEY=
2
- CLERK_JWT_ISSUER_DOMAIN=
3
- RESEND_API_KEY=
@@ -1,29 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- pull_request:
8
-
9
- permissions:
10
- actions: read
11
- contents: read
12
-
13
- jobs:
14
- main:
15
- name:
16
- runs-on: ubuntu-latest
17
- steps:
18
- - uses: actions/checkout@v4
19
- with:
20
- fetch-depth: 0
21
-
22
- - uses: oven-sh/setup-bun@v1
23
- with:
24
- bun-version: latest
25
-
26
- # - run: bun install --no-cache
27
- # - uses: nrwl/nx-set-shas@v4
28
-
29
- # - run: bun nx affected -t build
@@ -1,58 +0,0 @@
1
- # See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
2
-
3
- # compiled output
4
- dist
5
- tmp
6
- out-tsc
7
-
8
- # dependencies
9
- node_modules
10
-
11
- # IDEs and editors
12
- /.idea
13
- .project
14
- .classpath
15
- .c9/
16
- *.launch
17
- .settings/
18
- *.sublime-workspace
19
-
20
- # IDE - VSCode
21
- .vscode/*
22
- !.vscode/settings.json
23
- !.vscode/tasks.json
24
- !.vscode/launch.json
25
- !.vscode/extensions.json
26
-
27
- # misc
28
- .dist
29
- /.sass-cache
30
- /connect.lock
31
- /coverage
32
- /libpeerconnection.log
33
- npm-debug.log
34
- yarn-error.log
35
- testem.log
36
- /typings
37
-
38
- # environment variables
39
- .env
40
- .env.local
41
- .env.convex
42
-
43
- # System Files
44
- .DS_Store
45
- Thumbs.db
46
-
47
- .nx/cache
48
- .nx/workspace-data
49
-
50
- # Next.js
51
- .next
52
- out
53
-
54
- .cursor/rules/nx-rules.mdc
55
- .github/instructions/nx.instructions.md
56
-
57
- # clerk configuration (can include secrets)
58
- /.clerk/
@@ -1,73 +0,0 @@
1
- {
2
- "name": "@/source",
3
- "version": "0.0.0",
4
- "license": "MIT",
5
- "private": true,
6
- "scripts": {},
7
- "dependencies": {
8
- "@convex-dev/react-query": "^0.0.0-alpha.8",
9
- "@hookform/resolvers": "^3.9.1",
10
- "@radix-ui/react-accordion": "^1.2.2",
11
- "@radix-ui/react-alert-dialog": "^1.1.4",
12
- "@radix-ui/react-aspect-ratio": "^1.1.1",
13
- "@radix-ui/react-checkbox": "^1.1.3",
14
- "@radix-ui/react-collapsible": "^1.1.2",
15
- "@radix-ui/react-dropdown-menu": "^2.1.4",
16
- "@radix-ui/react-hover-card": "^1.1.4",
17
- "@radix-ui/react-label": "^2.1.1",
18
- "@radix-ui/react-popover": "^1.1.4",
19
- "@radix-ui/react-progress": "^1.1.1",
20
- "@radix-ui/react-radio-group": "^1.2.2",
21
- "@radix-ui/react-scroll-area": "^1.2.2",
22
- "@radix-ui/react-select": "^2.1.4",
23
- "@radix-ui/react-separator": "^1.1.1",
24
- "@radix-ui/react-slider": "^1.2.2",
25
- "@radix-ui/react-switch": "^1.1.2",
26
- "@radix-ui/react-tabs": "^1.1.2",
27
- "@radix-ui/react-tooltip": "^1.1.6",
28
- "@stepperize/react": "^5.1.5",
29
- "@tailwindcss/typography": "^0.5.16",
30
- "@tanstack/react-query": "^5.66.0",
31
- "@tanstack/react-store": "^0.7.0",
32
- "@tanstack/react-table": "^8.20.6",
33
- "class-variance-authority": "^0.7.1",
34
- "cmdk": "^1.0.4",
35
- "convex": "^1.28.0",
36
- "convex-ents": "^0.16.0",
37
- "convex-helpers": "^0.1.104",
38
- "dayjs": "^1.11.13",
39
- "lodash-es": "^4.17.21",
40
- "lucide-react": "^0.469.0",
41
- "nanoid": "^5.1.6",
42
- "react": "19.0.0",
43
- "react-dom": "19.0.0",
44
- "react-hook-form": "^7.54.2",
45
- "react-resizable-panels": "^4.7.2",
46
- "sonner": "^2.0.1",
47
- "ts-essentials": "^10.1.1",
48
- "tw-animate-css": "^1.3.8",
49
- "zod": "^3"
50
- },
51
- "devDependencies": {
52
- "@biomejs/biome": "^2.2.3",
53
- "@nx/js": "20.6.2",
54
- "@nx/workspace": "20.6.2",
55
- "@swc-node/register": "~1.9.1",
56
- "@swc/core": "~1.5.7",
57
- "@swc/helpers": "~0.5.11",
58
- "@tailwindcss/postcss": "^4.1.11",
59
- "@types/react": "19.0.0",
60
- "@types/react-dom": "19.0.0",
61
- "autoprefixer": "10.4.13",
62
- "nx": "20.6.2",
63
- "postcss": "8.4.38",
64
- "tailwind-merge": "^3.0.2",
65
- "tailwindcss": "^4.1.13",
66
- "tailwindcss-animate": "^1.0.7",
67
- "tslib": "^2.3.0",
68
- "typescript": "~5.7.2"
69
- },
70
- "workspaces": [
71
- "apps/*"
72
- ]
73
- }
@@ -1,3 +0,0 @@
1
- import { ConvexClient } from "convex/browser";
2
-
3
- export const convex = new ConvexClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
@@ -1,8 +0,0 @@
1
- # Convex
2
- CONVEX_DEPLOYMENT=
3
- CONVEX_DEPLOYMENT_URL=
4
- NEXT_PUBLIC_CONVEX_URL=
5
-
6
- # Authentication
7
- CLERK_SECRET_KEY=
8
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
@@ -1,6 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- declare module '*.svg' {
3
- const content: any;
4
- export const ReactComponent: any;
5
- export default content;
6
- }
@@ -1,5 +0,0 @@
1
- /// <reference types="next" />
2
- /// <reference types="next/image-types/global" />
3
-
4
- // NOTE: This file should not be edited
5
- // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -1,22 +0,0 @@
1
- //@ts-check
2
-
3
- // eslint-disable-next-line @typescript-eslint/no-var-requires
4
- const { composePlugins, withNx } = require("@nx/next");
5
-
6
- /**
7
- * @type {import('@nx/next/plugins/with-nx').WithNxOptions}
8
- **/
9
- const nextConfig = {
10
- nx: {
11
- // Set this to true if you would like to use SVGR
12
- // See: https://github.com/gregberge/svgr
13
- svgr: false,
14
- },
15
- };
16
-
17
- const plugins = [
18
- // Add more Next.js plugins to this list if needed.
19
- withNx,
20
- ];
21
-
22
- module.exports = composePlugins(...plugins)(nextConfig);
@@ -1,17 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2025.
3
- */
4
-
5
- const { join } = require("node:path");
6
-
7
- // Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build
8
- // option from your application's configuration (i.e. project.json).
9
- //
10
- // See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries
11
-
12
- module.exports = {
13
- plugins: {
14
- "@tailwindcss/postcss": {},
15
- autoprefixer: {},
16
- },
17
- };
@@ -1,22 +0,0 @@
1
- {
2
- "name": "my-app:web",
3
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
- "sourceRoot": "./apps/web",
5
- "projectType": "application",
6
- "tags": [],
7
- "targets": {
8
- "dev": {
9
- "executor": "nx:run-commands",
10
- "options": {
11
- "command": "bunx next dev apps/web --port 5001"
12
- }
13
- },
14
- "build": {
15
- "executor": "@nx/next:build",
16
- "options": {
17
- "root": "apps/web",
18
- "outputPath": "dist/apps/web"
19
- }
20
- }
21
- }
22
- }
@@ -1,21 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2025.
3
- */
4
-
5
- import "../app.css";
6
-
7
- import { Toaster } from "sonner";
8
-
9
-
10
- type RootLayoutProps = {
11
- children: React.ReactNode;
12
- };
13
-
14
- export default function AuthLayout({ children }: RootLayoutProps) {
15
- return (
16
- <main className="flex min-h-screen flex-col justify-center items-center overflow-hidden">
17
- {children}
18
- <Toaster />
19
- </main>
20
- );
21
- }
@@ -1,22 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2025.
3
- */
4
-
5
- import Link from "next/link";
6
-
7
- export const metadata: Metadata = {
8
- title: "Not Allowed",
9
- description: "You are not allowed to access this page.",
10
- };
11
-
12
- export default async function NotAllowed() {
13
- return (
14
- <div className="flex flex-col items-center justify-center h-screen">
15
- <h1 className="text-2xl font-bold">Not Allowed</h1>
16
- <p className="text-sm text-gray-500">You are not allowed to access this page.</p>
17
- <Link href="/sign-in" className="text-blue-500">
18
- Continue to login page
19
- </Link>
20
- </div>
21
- );
22
- }
@@ -1,15 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2025.
3
- */
4
-
5
- import { SignIn } from "@clerk/nextjs";
6
- import type { Metadata } from "next";
7
-
8
- export const metadata: Metadata = {
9
- title: "Sign In",
10
- description: "Sign In to your account",
11
- };
12
-
13
- export default function LoginPage() {
14
- return <SignIn withSignUp={true} />;
15
- }
@@ -1,27 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2025.
3
- */
4
-
5
- import { SidebarInset, SidebarProvider } from "@/ui/base/side_bar";
6
- import { Sidebar as AppSidebar } from "@/web/ui/sidebar/sidebar";
7
-
8
- type DashboardLayoutProps = {
9
- children: React.ReactNode;
10
- modal: React.ReactNode;
11
- };
12
-
13
- export default function DashboardLayout({ children }: DashboardLayoutProps) {
14
- return (
15
- <SidebarProvider
16
- style={
17
- {
18
- "--sidebar-width": "calc(var(--spacing) * 45)",
19
- "--header-height": "calc(var(--spacing) * 12)",
20
- } as React.CSSProperties
21
- }
22
- >
23
- <AppSidebar variant="inset" />
24
- <SidebarInset>{children}</SidebarInset>
25
- </SidebarProvider>
26
- );
27
- }
@@ -1,5 +0,0 @@
1
- import { HomeSurface } from "@/web/surfaces/home_surface";
2
-
3
- export default function HomePage() {
4
- return <HomeSurface />;
5
- }
@@ -1,23 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import type { Metadata } from "next";
6
-
7
- import type { TodoId } from "@/api/todos/types";
8
- import { SingleTodoSurface } from "@/web/surfaces/todos/single_todo_surface";
9
-
10
- type SingleTodoPageProps = {
11
- params: Promise<{ id: TodoId }>;
12
- };
13
-
14
- export const metadata: Metadata = {
15
- title: "Todo",
16
- description: "Todo",
17
- };
18
-
19
- export default async function SingleTodoPage({ params }: SingleTodoPageProps) {
20
- const { id } = await params;
21
-
22
- return <SingleTodoSurface todoId={id} />;
23
- }
@@ -1,16 +0,0 @@
1
- /*
2
- * Copyright (c) Aron Weston 2026.
3
- */
4
-
5
- import type { Metadata } from "next";
6
-
7
- import { AllTodosSurface } from "@/web/surfaces/todos/all_todos_surface";
8
-
9
- export const metadata: Metadata = {
10
- title: "Todos",
11
- description: "Todos",
12
- };
13
-
14
- export default function AllTodosPage() {
15
- return <AllTodosSurface />;
16
- }
@@ -1,3 +0,0 @@
1
- @import "../../../../shared/assets/src/styles/global.css";
2
- @source "../../../../shared/ui/src/**/*.{js,ts,jsx,tsx}";
3
- @source "../../../../apps/web/src/**/*.{js,ts,jsx,tsx}";