create-tigra 1.1.0 → 2.0.1

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 (243) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +80 -87
  3. package/bin/create-tigra.js +259 -308
  4. package/package.json +49 -41
  5. package/template/_claude/QUICK_REFERENCE.md +193 -0
  6. package/template/_claude/README.md +53 -0
  7. package/template/_claude/commands/create-client.md +881 -0
  8. package/template/_claude/commands/create-server.md +383 -0
  9. package/template/_claude/rules/client/01-project-structure.md +133 -0
  10. package/template/_claude/rules/client/02-components-and-types.md +146 -0
  11. package/template/_claude/rules/client/03-data-and-state.md +156 -0
  12. package/template/_claude/rules/client/04-design-system.md +185 -0
  13. package/template/_claude/rules/client/05-security.md +55 -0
  14. package/template/_claude/rules/client/06-ux-checklist.md +81 -0
  15. package/template/_claude/rules/client/core.md +42 -0
  16. package/template/_claude/rules/global/core.md +77 -0
  17. package/template/_claude/rules/server/core.md +50 -0
  18. package/template/_claude/rules/server/database.md +124 -0
  19. package/template/_claude/rules/server/project-conventions.md +150 -0
  20. package/template/_claude/rules/server/response-handling.md +144 -0
  21. package/template/client/.env.example +5 -0
  22. package/template/client/README.md +36 -0
  23. package/template/client/components.json +23 -0
  24. package/template/client/eslint.config.mjs +18 -0
  25. package/template/client/next.config.ts +34 -0
  26. package/template/client/package.json +44 -0
  27. package/template/client/postcss.config.mjs +7 -0
  28. package/template/client/src/app/(auth)/layout.tsx +18 -0
  29. package/template/client/src/app/(auth)/login/page.tsx +13 -0
  30. package/template/client/src/app/(auth)/register/page.tsx +13 -0
  31. package/template/client/src/app/(main)/dashboard/page.tsx +22 -0
  32. package/template/client/src/app/(main)/layout.tsx +11 -0
  33. package/template/client/src/app/error.tsx +27 -0
  34. package/template/client/src/app/favicon.ico +0 -0
  35. package/template/client/src/app/globals.css +145 -0
  36. package/template/client/src/app/layout.tsx +36 -0
  37. package/template/client/src/app/loading.tsx +11 -0
  38. package/template/client/src/app/not-found.tsx +23 -0
  39. package/template/client/src/app/page.tsx +45 -0
  40. package/template/client/src/app/providers.tsx +43 -0
  41. package/template/client/src/components/common/ConfirmDialog.tsx +56 -0
  42. package/template/client/src/components/common/EmptyState.tsx +31 -0
  43. package/template/client/src/components/common/LoadingSpinner.tsx +30 -0
  44. package/template/client/src/components/common/Pagination.tsx +55 -0
  45. package/template/client/src/components/layout/Footer.tsx +17 -0
  46. package/template/client/src/components/layout/Header.tsx +173 -0
  47. package/template/client/src/components/layout/MainLayout.tsx +18 -0
  48. package/template/client/src/components/ui/alert-dialog.tsx +196 -0
  49. package/template/client/src/components/ui/badge.tsx +48 -0
  50. package/template/client/src/components/ui/button.tsx +64 -0
  51. package/template/client/src/components/ui/card.tsx +92 -0
  52. package/template/client/src/components/ui/input.tsx +21 -0
  53. package/template/client/src/components/ui/label.tsx +24 -0
  54. package/template/client/src/components/ui/select.tsx +190 -0
  55. package/template/client/src/components/ui/skeleton.tsx +13 -0
  56. package/template/client/src/components/ui/table.tsx +116 -0
  57. package/template/client/src/features/auth/components/AuthInitializer.tsx +55 -0
  58. package/template/client/src/features/auth/components/LoginForm.tsx +107 -0
  59. package/template/client/src/features/auth/components/RegisterForm.tsx +178 -0
  60. package/template/client/src/features/auth/hooks/useAuth.ts +84 -0
  61. package/template/client/src/features/auth/services/auth.service.ts +52 -0
  62. package/template/client/src/features/auth/store/authSlice.ts +38 -0
  63. package/template/client/src/features/auth/types/auth.types.ts +32 -0
  64. package/template/client/src/hooks/useDebounce.ts +14 -0
  65. package/template/client/src/hooks/useLocalStorage.ts +55 -0
  66. package/template/client/src/hooks/useMediaQuery.ts +27 -0
  67. package/template/client/src/lib/api/api.types.ts +34 -0
  68. package/template/client/src/lib/api/axios.config.ts +98 -0
  69. package/template/client/src/lib/constants/api-endpoints.ts +18 -0
  70. package/template/client/src/lib/constants/app.constants.ts +12 -0
  71. package/template/client/src/lib/constants/routes.ts +9 -0
  72. package/template/client/src/lib/utils/error.ts +32 -0
  73. package/template/client/src/lib/utils/format.ts +37 -0
  74. package/template/client/src/lib/utils/security.ts +34 -0
  75. package/template/client/src/lib/utils.ts +6 -0
  76. package/template/client/src/middleware.ts +57 -0
  77. package/template/client/src/store/hooks.ts +7 -0
  78. package/template/client/src/store/index.ts +12 -0
  79. package/template/client/src/types/index.ts +3 -0
  80. package/template/client/tsconfig.json +34 -0
  81. package/template/gitignore +34 -0
  82. package/template/server/.dockerignore +66 -0
  83. package/template/server/.env.example +96 -69
  84. package/template/server/.env.production.example +90 -0
  85. package/template/server/Dockerfile +94 -0
  86. package/template/server/docker-compose.yml +82 -111
  87. package/template/server/docs/logging.md +62 -0
  88. package/template/server/eslint.config.mjs +17 -0
  89. package/template/server/package.json +68 -81
  90. package/template/server/phpmyadmin-config.php +26 -0
  91. package/template/server/postman_collection.json +666 -0
  92. package/template/server/prisma/schema.prisma +77 -93
  93. package/template/server/prisma/seed.ts +46 -142
  94. package/template/server/scripts/flush-redis.ts +41 -0
  95. package/template/server/src/app.ts +243 -71
  96. package/template/server/src/config/env.ts +67 -94
  97. package/template/server/src/libs/auth.ts +88 -0
  98. package/template/server/src/libs/cleanup.ts +35 -0
  99. package/template/server/src/libs/cookies.ts +46 -0
  100. package/template/server/src/libs/logger.ts +33 -60
  101. package/template/server/src/libs/monitoring.ts +205 -0
  102. package/template/server/src/libs/password.ts +38 -0
  103. package/template/server/src/libs/prisma.ts +68 -0
  104. package/template/server/src/libs/redis.ts +60 -79
  105. package/template/server/src/libs/requestLogger.ts +66 -0
  106. package/template/server/src/libs/storage/file-storage.service.ts +211 -0
  107. package/template/server/src/libs/storage/file-validator.ts +97 -0
  108. package/template/server/src/libs/storage/filename-sanitizer.ts +71 -0
  109. package/template/server/src/libs/storage/image-optimizer.service.ts +144 -0
  110. package/template/server/src/modules/auth/__tests__/auth.service.test.ts +365 -0
  111. package/template/server/src/modules/auth/auth.controller.ts +90 -141
  112. package/template/server/src/modules/auth/auth.repo.ts +120 -218
  113. package/template/server/src/modules/auth/auth.routes.ts +96 -83
  114. package/template/server/src/modules/auth/auth.schemas.ts +35 -137
  115. package/template/server/src/modules/auth/auth.service.ts +286 -329
  116. package/template/server/src/modules/auth/session.repo.ts +110 -0
  117. package/template/server/src/modules/users/users.controller.ts +120 -0
  118. package/template/server/src/modules/users/users.repo.ts +77 -0
  119. package/template/server/src/modules/users/users.routes.ts +89 -0
  120. package/template/server/src/modules/users/users.schemas.ts +21 -0
  121. package/template/server/src/modules/users/users.service.ts +169 -0
  122. package/template/server/src/server.ts +58 -139
  123. package/template/server/src/shared/errors/AppError.ts +21 -0
  124. package/template/server/src/shared/errors/errors.ts +43 -0
  125. package/template/server/src/shared/responses/paginatedResponse.ts +38 -0
  126. package/template/server/src/shared/responses/successResponse.ts +17 -0
  127. package/template/server/src/shared/schemas/pagination.schema.ts +12 -0
  128. package/template/server/src/shared/types/index.ts +26 -0
  129. package/template/server/src/test/setup.ts +74 -38
  130. package/template/server/tsconfig.json +27 -89
  131. package/template/server/uploads/avatars/.gitkeep +1 -0
  132. package/template/server/vitest.config.ts +43 -98
  133. package/template/.agent/rules/client/01-project-structure.md +0 -326
  134. package/template/.agent/rules/client/02-component-patterns.md +0 -249
  135. package/template/.agent/rules/client/03-typescript-rules.md +0 -226
  136. package/template/.agent/rules/client/04-state-management.md +0 -474
  137. package/template/.agent/rules/client/05-api-integration.md +0 -129
  138. package/template/.agent/rules/client/06-forms-validation.md +0 -129
  139. package/template/.agent/rules/client/07-common-patterns.md +0 -150
  140. package/template/.agent/rules/client/08-color-system.md +0 -93
  141. package/template/.agent/rules/client/09-security-rules.md +0 -97
  142. package/template/.agent/rules/client/10-testing-strategy.md +0 -370
  143. package/template/.agent/rules/global/ai-edit-safety.md +0 -38
  144. package/template/.agent/rules/server/01-db-and-migrations.md +0 -242
  145. package/template/.agent/rules/server/02-general-rules.md +0 -111
  146. package/template/.agent/rules/server/03-migrations.md +0 -20
  147. package/template/.agent/rules/server/04-pagination.md +0 -130
  148. package/template/.agent/rules/server/05-project-conventions.md +0 -71
  149. package/template/.agent/rules/server/06-response-handling.md +0 -173
  150. package/template/.agent/rules/server/07-testing-strategy.md +0 -506
  151. package/template/.agent/rules/server/08-observability.md +0 -180
  152. package/template/.agent/rules/server/10-background-jobs-v2.md +0 -185
  153. package/template/.agent/rules/server/11-rate-limiting-v2.md +0 -210
  154. package/template/.agent/rules/server/12-performance-optimization.md +0 -567
  155. package/template/.claude/rules/client-01-project-structure.md +0 -327
  156. package/template/.claude/rules/client-02-component-patterns.md +0 -250
  157. package/template/.claude/rules/client-03-typescript-rules.md +0 -227
  158. package/template/.claude/rules/client-04-state-management.md +0 -475
  159. package/template/.claude/rules/client-05-api-integration.md +0 -130
  160. package/template/.claude/rules/client-06-forms-validation.md +0 -130
  161. package/template/.claude/rules/client-07-common-patterns.md +0 -151
  162. package/template/.claude/rules/client-08-color-system.md +0 -94
  163. package/template/.claude/rules/client-09-security-rules.md +0 -98
  164. package/template/.claude/rules/client-10-testing-strategy.md +0 -371
  165. package/template/.claude/rules/global-ai-edit-safety.md +0 -39
  166. package/template/.claude/rules/server-01-db-and-migrations.md +0 -243
  167. package/template/.claude/rules/server-02-general-rules.md +0 -112
  168. package/template/.claude/rules/server-03-migrations.md +0 -21
  169. package/template/.claude/rules/server-04-pagination.md +0 -131
  170. package/template/.claude/rules/server-05-project-conventions.md +0 -72
  171. package/template/.claude/rules/server-06-response-handling.md +0 -174
  172. package/template/.claude/rules/server-07-testing-strategy.md +0 -507
  173. package/template/.claude/rules/server-08-observability.md +0 -181
  174. package/template/.claude/rules/server-10-background-jobs-v2.md +0 -186
  175. package/template/.claude/rules/server-11-rate-limiting-v2.md +0 -211
  176. package/template/.claude/rules/server-12-performance-optimization.md +0 -568
  177. package/template/.cursor/rules/client-01-project-structure.mdc +0 -327
  178. package/template/.cursor/rules/client-02-component-patterns.mdc +0 -250
  179. package/template/.cursor/rules/client-03-typescript-rules.mdc +0 -227
  180. package/template/.cursor/rules/client-04-state-management.mdc +0 -475
  181. package/template/.cursor/rules/client-05-api-integration.mdc +0 -130
  182. package/template/.cursor/rules/client-06-forms-validation.mdc +0 -130
  183. package/template/.cursor/rules/client-07-common-patterns.mdc +0 -151
  184. package/template/.cursor/rules/client-08-color-system.mdc +0 -94
  185. package/template/.cursor/rules/client-09-security-rules.mdc +0 -98
  186. package/template/.cursor/rules/client-10-testing-strategy.mdc +0 -371
  187. package/template/.cursor/rules/global-ai-edit-safety.mdc +0 -39
  188. package/template/.cursor/rules/server-01-db-and-migrations.mdc +0 -243
  189. package/template/.cursor/rules/server-02-general-rules.mdc +0 -112
  190. package/template/.cursor/rules/server-03-migrations.mdc +0 -21
  191. package/template/.cursor/rules/server-04-pagination.mdc +0 -131
  192. package/template/.cursor/rules/server-05-project-conventions.mdc +0 -72
  193. package/template/.cursor/rules/server-06-response-handling.mdc +0 -174
  194. package/template/.cursor/rules/server-07-testing-strategy.mdc +0 -507
  195. package/template/.cursor/rules/server-08-observability.mdc +0 -181
  196. package/template/.cursor/rules/server-09-api-documentation-v2.mdc +0 -169
  197. package/template/.cursor/rules/server-10-background-jobs-v2.mdc +0 -186
  198. package/template/.cursor/rules/server-11-rate-limiting-v2.mdc +0 -211
  199. package/template/.cursor/rules/server-12-performance-optimization.mdc +0 -568
  200. package/template/CLAUDE.md +0 -207
  201. package/template/server/.tsc-aliasrc.json +0 -13
  202. package/template/server/IMPORT_FIX_CHECKLIST.md +0 -98
  203. package/template/server/IMPORT_FIX_COMPLETE.md +0 -89
  204. package/template/server/README.md +0 -183
  205. package/template/server/REMAINING_IMPORT_FIXES.md +0 -150
  206. package/template/server/SECURITY.md +0 -190
  207. package/template/server/Tigra-API.postman_collection.json +0 -733
  208. package/template/server/biome.json +0 -42
  209. package/template/server/scripts/fix-all-imports.ps1 +0 -52
  210. package/template/server/scripts/fix-imports-reference.ps1 +0 -16
  211. package/template/server/scripts/fix-imports.mjs +0 -55
  212. package/template/server/scripts/setup-env.js +0 -50
  213. package/template/server/scripts/wait-for-db.js +0 -60
  214. package/template/server/src/hooks/request-timing.hook.ts +0 -26
  215. package/template/server/src/libs/auth/authenticate.middleware.ts +0 -22
  216. package/template/server/src/libs/auth/rbac.middleware.test.ts +0 -134
  217. package/template/server/src/libs/auth/rbac.middleware.ts +0 -147
  218. package/template/server/src/libs/db.ts +0 -76
  219. package/template/server/src/libs/error-handler.ts +0 -89
  220. package/template/server/src/libs/queue.ts +0 -79
  221. package/template/server/src/modules/admin/admin.controller.ts +0 -122
  222. package/template/server/src/modules/admin/admin.routes.ts +0 -62
  223. package/template/server/src/modules/admin/admin.schemas.ts +0 -35
  224. package/template/server/src/modules/admin/admin.service.ts +0 -167
  225. package/template/server/src/modules/auth/auth.integration.test.ts +0 -150
  226. package/template/server/src/modules/auth/auth.service.test.ts +0 -119
  227. package/template/server/src/modules/auth/auth.types.ts +0 -97
  228. package/template/server/src/modules/resources/resources.controller.ts +0 -218
  229. package/template/server/src/modules/resources/resources.repo.ts +0 -253
  230. package/template/server/src/modules/resources/resources.routes.ts +0 -116
  231. package/template/server/src/modules/resources/resources.schemas.ts +0 -146
  232. package/template/server/src/modules/resources/resources.service.ts +0 -218
  233. package/template/server/src/modules/resources/resources.types.ts +0 -73
  234. package/template/server/src/plugins/rate-limit.plugin.ts +0 -21
  235. package/template/server/src/plugins/security.plugin.ts +0 -21
  236. package/template/server/src/routes/health.routes.ts +0 -31
  237. package/template/server/src/types/fastify.d.ts +0 -36
  238. package/template/server/src/utils/errors.ts +0 -108
  239. package/template/server/src/utils/pagination.ts +0 -120
  240. package/template/server/src/utils/response.ts +0 -110
  241. package/template/server/src/workers/file.worker.ts +0 -106
  242. package/template/server/tsconfig.build.json +0 -30
  243. package/template/server/tsconfig.test.json +0 -22
@@ -0,0 +1,383 @@
1
+ # Create Server Project
2
+
3
+ You are scaffolding a new Fastify + TypeScript backend project. The project name is: **$ARGUMENTS**
4
+
5
+ If no project name is provided, ask the user for one before proceeding.
6
+
7
+ ---
8
+
9
+ ## Instructions
10
+
11
+ Create a complete, production-ready Fastify server project following the architecture and rules defined in `.claude/rules/server/`. Read those rules before generating any code.
12
+
13
+ ### Step 1: Project Root Setup
14
+
15
+ Create the project directory named `$ARGUMENTS` with the following root files:
16
+
17
+ #### `package.json`
18
+ ```json
19
+ {
20
+ "name": "$ARGUMENTS",
21
+ "version": "1.0.0",
22
+ "description": "",
23
+ "main": "dist/server.js",
24
+ "scripts": {
25
+ "dev": "tsx watch src/server.ts",
26
+ "build": "tsc && tsc-alias",
27
+ "start": "node dist/server.js",
28
+ "prisma:generate": "prisma generate",
29
+ "prisma:migrate:dev": "prisma migrate dev",
30
+ "prisma:migrate:deploy": "prisma migrate deploy",
31
+ "prisma:reset": "prisma migrate reset",
32
+ "prisma:seed": "prisma db seed",
33
+ "prisma:studio": "prisma studio",
34
+ "lint": "eslint src/",
35
+ "docker:up": "docker compose up -d",
36
+ "docker:down": "docker compose down",
37
+ "docker:logs": "docker compose logs -f"
38
+ },
39
+ "prisma": {
40
+ "seed": "tsx prisma/seed.ts"
41
+ }
42
+ }
43
+ ```
44
+
45
+ Install these dependencies (use npm):
46
+ ```
47
+ # Dependencies
48
+ npm install fastify @fastify/cors @fastify/helmet @fastify/rate-limit @fastify/cookie @fastify/jwt
49
+ npm install @prisma/client zod dotenv pino pino-pretty ioredis bcryptjs uuid
50
+
51
+ # Dev dependencies
52
+ npm install -D typescript tsx tsc-alias prisma @types/node @types/bcryptjs @types/uuid eslint @eslint/js typescript-eslint
53
+ ```
54
+
55
+ #### `tsconfig.json`
56
+ ```json
57
+ {
58
+ "compilerOptions": {
59
+ "target": "ES2020",
60
+ "module": "NodeNext",
61
+ "moduleResolution": "NodeNext",
62
+ "strict": true,
63
+ "esModuleInterop": true,
64
+ "skipLibCheck": true,
65
+ "forceConsistentCasingInFileNames": true,
66
+ "resolveJsonModule": true,
67
+ "declaration": true,
68
+ "declarationMap": true,
69
+ "sourceMap": true,
70
+ "outDir": "dist",
71
+ "rootDir": "src",
72
+ "baseUrl": ".",
73
+ "paths": {
74
+ "@/*": ["./src/*"],
75
+ "@modules/*": ["./src/modules/*"],
76
+ "@libs/*": ["./src/libs/*"],
77
+ "@config/*": ["./src/config/*"],
78
+ "@shared/*": ["./src/shared/*"]
79
+ }
80
+ },
81
+ "include": ["src/**/*"],
82
+ "exclude": ["node_modules", "dist"]
83
+ }
84
+ ```
85
+
86
+ > **Note**: The `tsc-alias` package resolves path aliases at build time. `tsx` handles paths natively in development.
87
+
88
+ #### `eslint.config.mjs`
89
+ ```js
90
+ import eslint from '@eslint/js';
91
+ import tseslint from 'typescript-eslint';
92
+
93
+ export default tseslint.config(
94
+ eslint.configs.recommended,
95
+ ...tseslint.configs.recommended,
96
+ {
97
+ rules: {
98
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
99
+ '@typescript-eslint/explicit-function-return-type': 'warn',
100
+ '@typescript-eslint/no-explicit-any': 'error',
101
+ },
102
+ },
103
+ {
104
+ ignores: ['dist/', 'node_modules/', 'prisma/'],
105
+ }
106
+ );
107
+ ```
108
+
109
+ #### `.env` and `.env.example`
110
+ ```env
111
+ # App
112
+ NODE_ENV=development
113
+ PORT=3000
114
+ HOST=0.0.0.0
115
+
116
+ # Database
117
+ DATABASE_URL="mysql://root:rootpassword@localhost:3306/$ARGUMENTS"
118
+
119
+ # Redis
120
+ REDIS_URL="redis://localhost:6379"
121
+
122
+ # JWT
123
+ JWT_SECRET="change-this-to-a-secure-random-string"
124
+ JWT_ACCESS_EXPIRY="15m"
125
+ JWT_REFRESH_EXPIRY="7d"
126
+
127
+ # CORS
128
+ CORS_ORIGIN="http://localhost:3001"
129
+ ```
130
+
131
+ #### `.gitignore`
132
+ Include: node_modules, dist, .env, .env.local, .env*.local, *.log, .prisma
133
+
134
+ #### `docker-compose.yml`
135
+ Create a Docker Compose file with these services:
136
+ 1. **mysql** - MySQL 8.0, port 3306, database name = `$ARGUMENTS`, root password = `rootpassword`, volume for data persistence, healthcheck
137
+ 2. **phpmyadmin** - Latest, port 8080, linked to mysql
138
+ 3. **redis** - Redis 7 Alpine, port 6379, volume for data persistence, healthcheck
139
+ 4. **redis-commander** - Redis Commander UI, port 8081, linked to redis
140
+
141
+ Use a named network for all services. Add restart policies.
142
+
143
+ ---
144
+
145
+ ### Step 2: Source Code Structure
146
+
147
+ Create the following directory structure under `src/`:
148
+
149
+ ```
150
+ src/
151
+ ├── app.ts # Fastify instance, plugin registration
152
+ ├── server.ts # listen() call only
153
+ ├── config/
154
+ │ └── env.ts # Zod-validated environment variables
155
+ ├── libs/
156
+ │ ├── prisma.ts # Prisma client singleton
157
+ │ ├── redis.ts # Redis client singleton
158
+ │ ├── logger.ts # Pino logger
159
+ │ └── auth.ts # JWT helpers (sign, verify, middleware)
160
+ ├── shared/
161
+ │ ├── errors/
162
+ │ │ ├── AppError.ts # Base error class
163
+ │ │ └── errors.ts # All typed error subclasses
164
+ │ ├── responses/
165
+ │ │ ├── successResponse.ts
166
+ │ │ └── paginatedResponse.ts
167
+ │ ├── schemas/
168
+ │ │ └── pagination.schema.ts # Shared Zod pagination schema
169
+ │ └── types/
170
+ │ └── index.ts # Shared TypeScript types
171
+ └── modules/
172
+ └── auth/ # Auth module
173
+ ├── auth.routes.ts
174
+ ├── auth.controller.ts
175
+ ├── auth.service.ts
176
+ ├── auth.repo.ts
177
+ └── auth.schemas.ts
178
+ ```
179
+
180
+ ---
181
+
182
+ ### Step 3: Core Files Implementation
183
+
184
+ #### `src/config/env.ts`
185
+ - Use Zod to validate ALL environment variables at startup
186
+ - Export typed `env` object
187
+ - Crash immediately with clear message if validation fails
188
+
189
+ #### `src/libs/logger.ts`
190
+ - Use Pino logger
191
+ - Pretty print in development, JSON in production
192
+ - Export singleton `logger`
193
+
194
+ #### `src/libs/prisma.ts`
195
+ - Singleton Prisma client
196
+ - Handle graceful shutdown (disconnect on process exit)
197
+
198
+ #### `src/libs/redis.ts`
199
+ - Singleton ioredis client
200
+ - Configure from `REDIS_URL` env
201
+ - Handle connection errors with logger
202
+ - Handle graceful shutdown
203
+
204
+ #### `src/libs/auth.ts`
205
+ - JWT sign/verify using @fastify/jwt
206
+ - Fastify `authenticate` preHandler decorator
207
+ - Fastify `optionalAuth` preHandler decorator
208
+ - Role-based `authorize(...roles)` preHandler
209
+
210
+ #### `src/shared/errors/AppError.ts`
211
+ - Base `AppError` class extending `Error` with: `code`, `statusCode`, `message`
212
+
213
+ #### `src/shared/errors/errors.ts`
214
+ - Export all subclasses: `BadRequestError`, `ValidationError`, `UnauthorizedError`, `ForbiddenError`, `NotFoundError`, `ConflictError`, `InternalError`
215
+ - Each with appropriate default status code and code string
216
+
217
+ #### `src/shared/responses/successResponse.ts`
218
+ ```typescript
219
+ export function successResponse<T>(message: string, data: T) {
220
+ return { success: true as const, message, data };
221
+ }
222
+ ```
223
+
224
+ #### `src/shared/responses/paginatedResponse.ts`
225
+ ```typescript
226
+ export function paginatedResponse<T>(
227
+ message: string,
228
+ items: T[],
229
+ page: number,
230
+ limit: number,
231
+ totalItems: number
232
+ ) {
233
+ const totalPages = Math.ceil(totalItems / limit);
234
+ return {
235
+ success: true as const,
236
+ message,
237
+ data: {
238
+ items,
239
+ pagination: {
240
+ page,
241
+ limit,
242
+ totalItems,
243
+ totalPages,
244
+ hasNextPage: page < totalPages,
245
+ hasPreviousPage: page > 1,
246
+ },
247
+ },
248
+ };
249
+ }
250
+ ```
251
+
252
+ #### `src/shared/schemas/pagination.schema.ts`
253
+ ```typescript
254
+ import { z } from 'zod';
255
+
256
+ export const PaginationSchema = z.object({
257
+ page: z.coerce.number().int().min(1).default(1),
258
+ limit: z.coerce.number().int().min(1).max(100).default(10),
259
+ });
260
+
261
+ export type PaginationInput = z.infer<typeof PaginationSchema>;
262
+ ```
263
+
264
+ #### `src/app.ts`
265
+ - Create and configure Fastify instance
266
+ - Register plugins: cors, helmet, rate-limit, cookie, jwt
267
+ - Register health check route: `GET /api/v1/health` — returns `successResponse('Server is healthy', { status: 'ok', timestamp: new Date().toISOString() })`
268
+ - Register global error handler that maps `AppError` → proper response format
269
+ - Register routes with `/api/v1` prefix
270
+ - Export the app instance
271
+
272
+ The global error handler MUST:
273
+ - Check if error is `AppError` → use its code, message, statusCode
274
+ - Check if error is Zod validation error → 422 with validation details
275
+ - Check if error is Fastify validation error → 400
276
+ - Default to 500 Internal Server Error
277
+ - Log internal errors with logger
278
+ - NEVER expose stack traces or internal details to client
279
+
280
+ #### `src/server.ts`
281
+ - Import app from `app.ts`
282
+ - Import env config
283
+ - Call `app.listen({ port, host })`
284
+ - Log startup message with port and environment
285
+ - Handle graceful shutdown (SIGINT, SIGTERM) — close Fastify, disconnect Prisma, disconnect Redis
286
+
287
+ ---
288
+
289
+ ### Step 4: Auth Module
290
+
291
+ Create a working auth module with these endpoints:
292
+ - `POST /api/v1/auth/register` - Register new user
293
+ - `POST /api/v1/auth/login` - Login with email/password
294
+ - `POST /api/v1/auth/logout` - Logout (invalidate refresh token)
295
+ - `POST /api/v1/auth/refresh` - Refresh access token
296
+ - `GET /api/v1/auth/me` - Get current user (protected)
297
+
298
+ Follow the layered architecture:
299
+ - **auth.schemas.ts** - Zod schemas for register, login, refresh input
300
+ - **auth.controller.ts** - Validate input, call service, return `successResponse()`
301
+ - **auth.service.ts** - Business logic, bcrypt hashing, JWT token generation, throw typed errors
302
+ - **auth.repo.ts** - Prisma queries for users and refresh tokens
303
+ - **auth.routes.ts** - Fastify plugin registering routes with appropriate preHandlers
304
+
305
+ ---
306
+
307
+ ### Step 5: Prisma Setup
308
+
309
+ #### `prisma/schema.prisma`
310
+ ```prisma
311
+ generator client {
312
+ provider = "prisma-client-js"
313
+ }
314
+
315
+ datasource db {
316
+ provider = "mysql"
317
+ url = env("DATABASE_URL")
318
+ }
319
+
320
+ model User {
321
+ id String @id @default(uuid())
322
+ email String @unique
323
+ password String
324
+ firstName String
325
+ lastName String
326
+ role String @default("USER")
327
+ isActive Boolean @default(true)
328
+ emailVerified Boolean @default(false)
329
+ deletedAt DateTime?
330
+ createdAt DateTime @default(now())
331
+ updatedAt DateTime @updatedAt
332
+
333
+ refreshTokens RefreshToken[]
334
+
335
+ @@map("users")
336
+ }
337
+
338
+ model RefreshToken {
339
+ id String @id @default(uuid())
340
+ token String @unique @db.VarChar(500)
341
+ userId String
342
+ expiresAt DateTime
343
+ createdAt DateTime @default(now())
344
+
345
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
346
+
347
+ @@index([userId])
348
+ @@index([token])
349
+ @@map("refresh_tokens")
350
+ }
351
+ ```
352
+
353
+ #### `prisma/seed.ts`
354
+ - Create a basic seed file that creates an admin user and a test user
355
+ - Use bcrypt to hash passwords
356
+ - Wrap in try/catch with proper logging
357
+
358
+ ---
359
+
360
+ ### Step 6: Final Verification
361
+
362
+ After creating all files:
363
+ 1. Run `npm install` to install dependencies
364
+ 2. Run `docker compose up -d` to start services (if Docker is available, otherwise remind the user)
365
+ 3. Wait for MySQL to be healthy, then run `npx prisma migrate dev --name init`
366
+ 4. Run `npx prisma generate`
367
+ 5. Run `npx prisma db seed`
368
+ 6. Verify the project starts with `npm run dev`
369
+ 7. Test health check: `curl http://localhost:3000/api/v1/health`
370
+
371
+ If Docker is not running, inform the user they need to run `docker compose up -d` before running migrations.
372
+
373
+ ---
374
+
375
+ ## IMPORTANT RULES
376
+
377
+ - Follow ALL rules from `.claude/rules/server/` and `.claude/rules/global/`
378
+ - Use the EXACT response format from `response-handling.md` (includes pagination contract)
379
+ - All routes prefixed with `/api/v1`
380
+ - TypeScript strict mode
381
+ - No `console.log` — use logger
382
+ - No raw `Error` throws — use AppError subclasses
383
+ - Named exports everywhere except `app.ts`
@@ -0,0 +1,133 @@
1
+ > **SCOPE**: These rules apply specifically to the **client** directory (Next.js App Router).
2
+
3
+ # Project Structure
4
+
5
+ ## Folder Structure
6
+
7
+ ```
8
+ src/
9
+ ├── app/ # Next.js App Router
10
+ │ ├── layout.tsx # Root layout
11
+ │ ├── page.tsx # Home page
12
+ │ ├── providers.tsx # Client providers (Redux, React Query)
13
+ │ ├── globals.css # Global styles
14
+ │ ├── (auth)/ # Auth route group
15
+ │ │ ├── login/page.tsx
16
+ │ │ ├── register/page.tsx
17
+ │ │ └── layout.tsx
18
+ │ ├── (main)/ # Main route group
19
+ │ │ ├── layout.tsx # Header/Footer layout
20
+ │ │ └── <domain>/ # Domain-specific routes
21
+ │ ├── dashboard/ # Protected routes
22
+ │ └── admin/ # Admin routes
23
+ ├── components/
24
+ │ ├── ui/ # shadcn/ui components
25
+ │ ├── layout/ # Header, Footer, Sidebar, MainLayout
26
+ │ └── common/ # LoadingSpinner, ErrorBoundary, Pagination, EmptyState
27
+ ├── features/ # Feature modules (domain-driven)
28
+ │ └── <domain>/
29
+ │ ├── components/
30
+ │ ├── hooks/
31
+ │ ├── services/ # <domain>.service.ts
32
+ │ ├── store/ # <domain>Slice.ts (if needed)
33
+ │ ├── types/ # <domain>.types.ts
34
+ │ └── actions/ # <domain>.actions.ts (Server Actions)
35
+ ├── hooks/ # Global hooks (useDebounce, useLocalStorage, useMediaQuery)
36
+ ├── lib/
37
+ │ ├── api/ # axios.config.ts, api.types.ts
38
+ │ ├── constants/ # routes.ts, api-endpoints.ts, app.constants.ts
39
+ │ └── utils/ # format.ts, validation.ts, error.ts, cn() helper
40
+ ├── store/ # Redux store (index.ts, hooks.ts)
41
+ ├── types/ # Global types
42
+ └── middleware.ts # Auth route protection
43
+ ```
44
+
45
+ ## File Naming
46
+
47
+ | Type | Pattern | Example |
48
+ |---|---|---|
49
+ | Component | `PascalCase.tsx` | `ProductCard.tsx` |
50
+ | Page | `folder/page.tsx` | `products/page.tsx` |
51
+ | Hook | `use<Name>.ts` | `useAuth.ts` |
52
+ | Service | `<domain>.service.ts` | `product.service.ts` |
53
+ | Types | `<domain>.types.ts` | `product.types.ts` |
54
+ | Redux slice | `<domain>Slice.ts` | `authSlice.ts` |
55
+ | Server Action | `<domain>.actions.ts` | `product.actions.ts` |
56
+ | Page exports | `default export` | Required by Next.js |
57
+ | Everything else | Named exports | `export const ProductCard` |
58
+
59
+ ## Import Order
60
+
61
+ 1. React / Next.js (`useState`, `useRouter`, `Image`, `Link`)
62
+ 2. Third-party (`@tanstack/react-query`, `sonner`)
63
+ 3. UI components (`@/components/ui/*`)
64
+ 4. Local components
65
+ 5. Hooks
66
+ 6. Services
67
+ 7. Types (always `import type`)
68
+ 8. Utils (`cn`, `formatDate`)
69
+
70
+ ## Constants
71
+
72
+ ```typescript
73
+ // lib/constants/api-endpoints.ts
74
+ export const API_ENDPOINTS = {
75
+ AUTH: {
76
+ REGISTER: '/auth/register',
77
+ LOGIN: '/auth/login',
78
+ LOGOUT: '/auth/logout',
79
+ REFRESH: '/auth/refresh',
80
+ ME: '/auth/me',
81
+ VERIFY_EMAIL: '/auth/verify-email',
82
+ RESEND_VERIFICATION: '/auth/resend-verification',
83
+ REQUEST_PASSWORD_RESET: '/auth/request-password-reset',
84
+ RESET_PASSWORD: '/auth/reset-password',
85
+ },
86
+ USERS: {
87
+ ME: '/users/me',
88
+ UPDATE_ME: '/users/me',
89
+ DELETE_ME: '/users/me',
90
+ },
91
+ // Add domain-specific endpoints following this pattern:
92
+ // <DOMAIN>: {
93
+ // LIST: '/<domain>',
94
+ // CREATE: '/<domain>',
95
+ // GET: (id: string) => `/<domain>/${id}`,
96
+ // UPDATE: (id: string) => `/<domain>/${id}`,
97
+ // DELETE: (id: string) => `/<domain>/${id}`,
98
+ // },
99
+ } as const;
100
+
101
+ // lib/constants/routes.ts
102
+ export const ROUTES = {
103
+ HOME: '/',
104
+ LOGIN: '/login',
105
+ REGISTER: '/register',
106
+ VERIFY_EMAIL: '/verify-email',
107
+ RESET_PASSWORD: '/reset-password',
108
+ DASHBOARD: '/dashboard',
109
+ PROFILE: '/profile',
110
+ // Add domain-specific routes following this pattern:
111
+ // <DOMAIN>: {
112
+ // LIST: '/<domain>',
113
+ // DETAILS: (id: string) => `/<domain>/${id}`,
114
+ // CREATE: '/<domain>/create',
115
+ // EDIT: (id: string) => `/<domain>/${id}/edit`,
116
+ // },
117
+ } as const;
118
+
119
+ // lib/constants/app.constants.ts
120
+ export const APP_NAME = 'My App';
121
+ export const PAGINATION = { DEFAULT_PAGE: 1, DEFAULT_LIMIT: 10, MAX_LIMIT: 100 } as const;
122
+ export const USER_ROLES = { USER: 'USER', ADMIN: 'ADMIN' } as const;
123
+ export const CURRENCIES = { USD: 'USD', EUR: 'EUR' } as const;
124
+ ```
125
+
126
+ ## App Providers
127
+
128
+ `app/providers.tsx` wraps the app with: **ReduxProvider** (store) → **QueryClientProvider** (React Query) → **Toaster** (sonner, position: top-right).
129
+
130
+ ## Middleware
131
+
132
+ Protected paths: `/dashboard`, `/profile`, `/admin` — redirect to `/login` if no token.
133
+ Auth paths: `/login`, `/register` — redirect to `/dashboard` if already authenticated.
@@ -0,0 +1,146 @@
1
+ > **SCOPE**: These rules apply specifically to the **client** directory (Next.js App Router).
2
+
3
+ # Components & Types
4
+
5
+ ## Component Rules
6
+
7
+ - **Server Components by default.** Only add `'use client'` for hooks, state, or event handlers.
8
+ - **Max 250 lines** per component. Split if exceeded.
9
+ - **Max 5 props.** Group related props into an object if more are needed.
10
+ - **Max 3 levels** of JSX nesting. Extract sub-components if deeper.
11
+ - **Internal ordering**: hooks → event handlers → effects → early returns → render.
12
+ - **Handler naming**: `handle<Event>` for internal handlers, `on<Event>` for callback props.
13
+ - **Wrap handlers in `useCallback`** when passed to child components (Client Components only).
14
+ - **Use `useMemo`** for expensive computations in Client Components.
15
+
16
+ ### Anti-patterns
17
+
18
+ - Do NOT add `'use client'` to components that have no interactivity — keep them as Server Components.
19
+ - Do NOT fetch data in Client Components when a Server Component can fetch it and pass as props.
20
+ - Do NOT use inline styles. Use Tailwind + `cn()` for conditional classes.
21
+
22
+ ---
23
+
24
+ ## TypeScript Rules
25
+
26
+ - **Strict mode ON.** No `any` — use `unknown` if the type is truly unknown.
27
+ - **Explicit return types** on all functions.
28
+ - **`interface`** for component props and object shapes. **`type`** for unions, intersections, utilities.
29
+ - **Prefer string unions** over enums: `type UserRole = 'USER' | 'ADMIN'`
30
+ - **Infer form types from Zod**: `type FormData = z.infer<typeof formSchema>`
31
+ - **Always use `import type`** for type-only imports.
32
+
33
+ ---
34
+
35
+ ## API Response Types
36
+
37
+ ```typescript
38
+ // lib/api/api.types.ts
39
+
40
+ export interface ApiResponse<T> {
41
+ success: boolean;
42
+ message: string;
43
+ data: T;
44
+ }
45
+
46
+ export interface PaginatedApiResponse<T> {
47
+ success: boolean;
48
+ message: string;
49
+ data: {
50
+ items: T[];
51
+ pagination: {
52
+ page: number;
53
+ limit: number;
54
+ totalItems: number;
55
+ totalPages: number;
56
+ hasNextPage: boolean;
57
+ hasPreviousPage: boolean;
58
+ };
59
+ };
60
+ }
61
+
62
+ export interface ApiError {
63
+ success: false;
64
+ error: {
65
+ code: string;
66
+ message: string;
67
+ };
68
+ }
69
+
70
+ export interface PaginationParams {
71
+ page?: number;
72
+ limit?: number;
73
+ }
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Domain Types
79
+
80
+ ```typescript
81
+ // features/auth/types/auth.types.ts
82
+
83
+ export interface IUser {
84
+ id: string;
85
+ email: string;
86
+ firstName: string;
87
+ lastName: string;
88
+ role: UserRole;
89
+ isActive: boolean;
90
+ avatarUrl: string | null;
91
+ createdAt: string;
92
+ updatedAt: string;
93
+ }
94
+
95
+ export type UserRole = 'USER' | 'ADMIN';
96
+
97
+ export interface ILoginRequest {
98
+ email: string;
99
+ password: string;
100
+ }
101
+
102
+ export interface IRegisterRequest {
103
+ email: string;
104
+ password: string;
105
+ firstName: string;
106
+ lastName: string;
107
+ }
108
+
109
+ // No IAuthTokens — tokens are stored in httpOnly cookies, never exposed to JS.
110
+
111
+ export interface IAuthState {
112
+ user: IUser | null;
113
+ isAuthenticated: boolean;
114
+ isInitializing: boolean; // true until first getMe() resolves
115
+ isLoggingOut: boolean; // true during logout API call
116
+ }
117
+ ```
118
+
119
+ ```typescript
120
+ // features/<domain>/types/<domain>.types.ts — example pattern
121
+
122
+ export interface Item {
123
+ id: string;
124
+ ownerId: string;
125
+ title: string;
126
+ description: string | null;
127
+ isActive: boolean;
128
+ createdAt: string;
129
+ updatedAt: string;
130
+ }
131
+
132
+ export interface CreateItemRequest {
133
+ title: string;
134
+ description?: string;
135
+ }
136
+
137
+ export interface UpdateItemRequest {
138
+ title?: string;
139
+ description?: string;
140
+ }
141
+
142
+ export interface ItemFilters {
143
+ search?: string;
144
+ sortBy?: 'createdAt' | 'title';
145
+ }
146
+ ```