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: Backend architecture overview for the Convex API. Covers folder structure, schema design patterns, function conventions, and getting started steps.
3
- globs: apps/api/**/*.ts
4
- ---
5
-
6
- # Backend API Architecture
7
-
8
- This is the Convex backend located in `apps/api/`. It uses `convex-ents` for relational data modeling and `zQuery`/`zMutation` wrappers from `convex-helpers` for all public functions.
9
-
10
- ## Folder Structure
11
-
12
- ```
13
- apps/api/
14
- ├── <entity>/
15
- │ ├── schema.ts # Ent definition (table shape + edges + indexes)
16
- │ ├── types.ts # Zod schemas and TypeScript types
17
- │ └── crud.ts # CRUD operations (GET → UPDATE → CREATE → DELETE)
18
- ├── schema.ts # Main schema — spreads all entity ent objects
19
- ├── types.ts # Shared context types (QueryCtx, MutationCtx, Ent<T>)
20
- └── functions.ts # zQuery / zMutation wrappers using convex-ents
21
- ```
22
-
23
- ### Example: `todos/`
24
-
25
- The `todos/` directory is the canonical example of how to structure a new entity:
26
-
27
- ```
28
- apps/api/todos/
29
- ├── schema.ts # todoEnts — defines the todos table
30
- ├── types.ts # CreateTodo, UpdateTodo Zod types
31
- └── crud.ts # getTodo, listTodos, updateTodo, createTodo, deleteTodo
32
- ```
33
-
34
- ## Adding a New Entity
35
-
36
- 1. Create `apps/api/<entity>/schema.ts` — define the ent and export `<entity>Ents`
37
- 2. Create `apps/api/<entity>/types.ts` — define Zod schemas and TypeScript types
38
- 3. Create `apps/api/<entity>/crud.ts` — implement CRUD using `zQuery`/`zMutation`
39
- 4. Spread the new ent in `apps/api/schema.ts`:
40
-
41
- ```typescript
42
- import { todoEnts } from "@/api/todos/schema";
43
- import { entityEnts } from "@/api/<entity>/schema";
44
- import { defineEntSchema, getEntDefinitions } from "convex-ents";
45
-
46
- const schema = defineEntSchema({
47
- ...todoEnts,
48
- ...entityEnts,
49
- });
50
-
51
- export default schema;
52
- export const entDefinitions = getEntDefinitions(schema);
53
- ```
54
-
55
- ## Schema Design Patterns
56
-
57
- ### Ent Definitions (`schema.ts`)
58
-
59
- ```typescript
60
- import { v } from "convex/values";
61
- import { defineEnt } from "convex-ents";
62
-
63
- export const entityEnts = {
64
- entities: defineEnt({
65
- title: v.string(),
66
- userId: v.string(),
67
- isCompleted: v.boolean(),
68
- })
69
- .edge("relatedEntity")
70
- .index("by_user_id", ["userId"]),
71
- };
72
- ```
73
-
74
- - Export as `{ tableName: defineEnt({...}) }` objects
75
- - Always add indexes for fields you query by
76
- - Name indexes `by_<field>` or `by_<field1>_and_<field2>`
77
-
78
- ### Types (`types.ts`)
79
-
80
- ```typescript
81
- import { z } from "zod";
82
-
83
- export type CreateEntity = z.infer<typeof CreateEntity>;
84
- export const CreateEntity = z.object({
85
- title: z.string().min(1),
86
- userId: z.string(),
87
- });
88
- ```
89
-
90
- - All Zod schemas go here, not in schema.ts
91
- - Use `zodToConvex()` from `convex-helpers/server/zod` when you need a Convex validator from a Zod schema
92
-
93
- ### CRUD (`crud.ts`)
94
-
95
- Functions are always ordered: **GET → UPDATE → CREATE → DELETE**
96
-
97
- ```typescript
98
- import { zMutation, zQuery } from "@/api/functions";
99
- import { zid } from "convex-helpers/server/zod";
100
- import { z } from "zod";
101
-
102
- export const getEntity = zQuery({
103
- args: { entityId: zid("entities") },
104
- handler: async (ctx, args) => ctx.table("entities").getX(args.entityId),
105
- });
106
-
107
- export const listEntities = zQuery({
108
- args: { userId: z.string() },
109
- handler: async (ctx, args) =>
110
- ctx.table("entities", "by_user_id", (q) => q.eq("userId", args.userId)),
111
- });
112
-
113
- export const updateEntity = zMutation({
114
- args: { entityId: zid("entities"), title: z.string().optional() },
115
- handler: async (ctx, args) => {
116
- const { entityId, ...updates } = args;
117
- const entity = await ctx.table("entities").getX(entityId);
118
- return entity.patch(updates);
119
- },
120
- });
121
-
122
- export const createEntity = zMutation({
123
- args: { title: z.string().min(1), userId: z.string() },
124
- handler: async (ctx, args) =>
125
- ctx.table("entities").insert({ title: args.title, userId: args.userId, isCompleted: false }),
126
- });
127
-
128
- export const deleteEntity = zMutation({
129
- args: { entityId: zid("entities") },
130
- handler: async (ctx, args) => {
131
- const entity = await ctx.table("entities").getX(args.entityId);
132
- await entity.delete();
133
- },
134
- });
135
- ```
136
-
137
- ## Documentation Style
138
-
139
- - **NEVER** add JSDoc or any comments before exported function definitions
140
- - Function names should be self-documenting
141
- - Only add inline comments for complex business logic that can't be expressed through code alone
142
- - NO comments like `// Get entity by ID` or `// Update entity` above functions
143
-
144
- ## Ent Methods
145
-
146
- Prefer the throwing variants when you expect the entity to exist:
147
-
148
- | Use | When |
149
- |---|---|
150
- | `getX(id)` | Entity must exist — throws if not found |
151
- | `get(id)` | Entity may not exist — returns `null` |
152
- | `uniqueX(...)` | Index query must return exactly one result |
153
- | `unique(...)` | Index query may return zero results |
154
- | `firstX(...)` | Query must return at least one result |
155
- | `first(...)` | Query may return zero results |
156
-
157
- ```typescript
158
- // Good — entity is expected to exist
159
- const todo = await ctx.table("todos").getX(todoId);
160
- return todo.patch(updates);
161
-
162
- // Good — entity may not exist
163
- const entity = await ctx.table("entities").get(entityId);
164
- if (!entity) {
165
- throw new ConvexError("Entity not found");
166
- }
167
-
168
- // Bad — redundant null-check on getX result
169
- const todo = await ctx.table("todos").get(todoId);
170
- if (!todo) {
171
- throw new ConvexError("Todo not found");
172
- }
173
- ```
174
-
175
- ## Error Handling
176
-
177
- - Use `ConvexError` from `convex/values` for all business logic errors
178
- - Trust `getX()` and `uniqueX()` to throw — don't add redundant null checks after them
179
- - Only add explicit null checks when using `get()` or `first()`
180
- - Keep error messages concise and actionable
181
-
182
- ```typescript
183
- import { ConvexError } from "convex/values";
184
-
185
- // validate before the DB operation
186
- if (count <= 0) {
187
- throw new ConvexError("Limit reached");
188
- }
189
- ```
190
-
191
- ## Common Patterns
192
-
193
- ### Edge Operations
194
-
195
- ```typescript
196
- // Load a related entity
197
- const related = await entity.edge("relatedEntity");
198
-
199
- // Add to an edge collection
200
- await entity.patch({
201
- relation: { add: [relatedId] },
202
- });
203
-
204
- // Remove from an edge collection
205
- await entity.patch({
206
- relation: { remove: [relatedId] },
207
- });
208
- ```
209
-
210
- ### Returning an Entity with Edges
211
-
212
- ```typescript
213
- const related = await entity.edge("relatedEntity");
214
- return { ...entity, related };
215
- ```
216
-
217
- ### Standard Update Pattern
218
-
219
- ```typescript
220
- const { entityId, ...updates } = args;
221
- const entity = await ctx.table("entities").getX(entityId);
222
- return entity.patch(updates);
223
- ```
224
-
225
- ### Index Queries
226
-
227
- ```typescript
228
- // Query by named index
229
- return ctx.table("entities", "by_user_id", (q) =>
230
- q.eq("userId", args.userId)
231
- );
232
-
233
- // Query with a filter (use indexes instead where possible)
234
- return ctx
235
- .table("entities")
236
- .filter((q) => q.eq(q.field("fieldName"), value))
237
- .first();
238
- ```
239
-
240
- ## Validation Helpers
241
-
242
- - Validation functions belong in the shared `@/utils/` package
243
- - Keep CRUD files focused solely on database operations
244
- - Reuse validators across multiple entities rather than duplicating logic
245
-
246
- ## Getting Started
247
-
248
- ### 1. Install dependencies
249
-
250
- ```bash
251
- bun install
252
- ```
253
-
254
- ### 2. Start the Convex dev server
255
-
256
- ```bash
257
- npx convex dev
258
- ```
259
-
260
- This pushes the schema and regenerates types in `_generated/`.
261
-
262
- ### 3. Configure environment
263
-
264
- Copy `.env.local.example` to `.env.local` and fill in:
265
- - `CONVEX_DEPLOYMENT` — from Convex dashboard
266
- - `NEXT_PUBLIC_CONVEX_URL` — from Convex dashboard
267
- - `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` — from Clerk dashboard
268
- - `CLERK_SECRET_KEY` — from Clerk dashboard
@@ -1,64 +0,0 @@
1
- ---
2
- description: Project-wide coding standards covering import ordering, naming conventions, code style, and testing policy. Apply across all TypeScript/TSX files.
3
- globs: **/*.ts,**/*.tsx
4
- ---
5
-
6
- # Coding Standards
7
-
8
- ## Naming Conventions
9
-
10
- ### Functions
11
- - Use verb + noun: `getEntity`, `updateEntity`, `createEntity`, `deleteEntity`
12
- - Be specific when needed: `getEntityByEmail`, `updateEntityField`
13
- - Avoid abbreviations unless widely understood
14
- - Avoid verbose qualifiers: prefer `updateEntity` over `updateEntityCoreDetails`
15
-
16
- ### Fields
17
- - `camelCase` for all field names
18
- - Use `userId` — not `clerkId` or other provider-specific names
19
-
20
- ### Variables
21
- - Keep names concise and descriptive
22
- - Use singular for single items (`todo`, `entity`) and plural for collections (`todos`, `entities`)
23
- - Destructure to extract IDs: `const { entityId, ...updates } = args;`
24
-
25
- ## Code Style
26
-
27
- ### Formatting
28
- - Single blank line between functions
29
- - No blank lines at the start or end of a function body
30
- - 2-space indentation
31
- - Trailing commas in multi-line arrays and objects
32
-
33
- ### Conditional Logic
34
-
35
- Prefer concise conditionals — avoid unnecessary intermediate variables:
36
-
37
- ```typescript
38
- // Good
39
- const count = entity.limit ?? 0;
40
- if (count <= 0) {
41
- throw new ConvexError("Limit reached");
42
- }
43
-
44
- // Bad
45
- const remaining = entity.limit ?? 0;
46
- if (!entity.limit || entity.limit <= 0) {
47
- throw new ConvexError("Limit reached");
48
- }
49
- ```
50
-
51
- ### Async / Await
52
- - Always `await` async operations — never fire-and-forget unless intentional
53
- - Chain operations when it improves readability
54
- - Use `Promise.all()` for independent parallel operations
55
-
56
- ### Validation
57
- - Validate business rules before any database operation
58
- - Centralise reusable validation in `@/utils/`
59
- - Throw `ConvexError` with clear, actionable messages
60
- - Keep CRUD files thin — validation logic belongs in utils
61
-
62
- ## Testing
63
-
64
- Test files **should not** be created unless explicitly requested. Focus on implementation quality over test coverage.