create-tigra 3.0.5 → 3.1.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 (85) hide show
  1. package/README.md +4 -2
  2. package/bin/create-tigra.js +5 -19
  3. package/modules/email-verification/client/hooks/useVerification.ts +3 -3
  4. package/package.json +1 -1
  5. package/template/.agents/skills/security-audit/AI-AND-LLM.md +83 -0
  6. package/template/.agents/skills/security-audit/ATTACK-CLASSES.md +130 -0
  7. package/template/.agents/skills/security-audit/CLIENT-SIDE.md +83 -0
  8. package/template/.agents/skills/security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
  9. package/template/.agents/skills/security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
  10. package/template/.agents/skills/security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
  11. package/template/.agents/skills/security-audit/HUNTING.md +251 -0
  12. package/template/.agents/skills/security-audit/LICENSE +21 -0
  13. package/template/.agents/skills/security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
  14. package/template/.agents/skills/security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
  15. package/template/.agents/skills/security-audit/RECONNAISSANCE.md +156 -0
  16. package/template/.agents/skills/security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
  17. package/template/.agents/skills/security-audit/SKILL.md +192 -0
  18. package/template/.agents/skills/security-audit/SOURCE.md +5 -0
  19. package/template/.agents/skills/security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
  20. package/template/.agents/skills/security-audit/VALIDATION-AND-REPORTING.md +186 -0
  21. package/template/.agents/skills/security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
  22. package/template/.agents/skills/security-audit/report-schema.json +461 -0
  23. package/template/.agents/skills/security-audit/validate-coverage-ledger.cjs +872 -0
  24. package/template/.agents/skills/security-audit/validate-coverage-ledger.test.cjs +740 -0
  25. package/template/.agents/skills/security-audit/validate-findings.cjs +773 -0
  26. package/template/.agents/skills/security-audit/validate-findings.test.cjs +652 -0
  27. package/template/AGENTS.md +46 -0
  28. package/template/client/AGENTS.md +23 -0
  29. package/template/client/package-lock.json +410 -324
  30. package/template/client/package.json +3 -3
  31. package/template/client/src/app/(auth)/layout.tsx +9 -0
  32. package/template/client/src/app/(auth)/loading.tsx +7 -0
  33. package/template/client/src/app/(main)/layout.tsx +11 -0
  34. package/template/client/src/app/(main)/loading.tsx +7 -0
  35. package/template/client/src/app/globals.css +4 -0
  36. package/template/client/src/app/layout.tsx +9 -2
  37. package/template/client/src/app/loading.tsx +2 -6
  38. package/template/client/src/app/not-found.tsx +2 -3
  39. package/template/client/src/app/providers.tsx +6 -3
  40. package/template/client/src/components/common/AppLink.tsx +84 -0
  41. package/template/client/src/components/common/EmptyState.tsx +2 -2
  42. package/template/client/src/components/common/Pagination.tsx +3 -2
  43. package/template/client/src/components/common/RouteLoadingShell.tsx +21 -0
  44. package/template/client/src/components/common/SmoothNavigationProvider.tsx +151 -0
  45. package/template/client/src/components/layout/Header.tsx +12 -12
  46. package/template/client/src/features/admin/hooks/useAdminSessions.ts +2 -2
  47. package/template/client/src/features/admin/hooks/useAdminUsers.ts +3 -3
  48. package/template/client/src/features/auth/components/AuthInitializer.tsx +3 -2
  49. package/template/client/src/features/auth/components/LoginForm.tsx +3 -3
  50. package/template/client/src/features/auth/components/RegisterForm.tsx +3 -3
  51. package/template/client/src/features/auth/hooks/useAuth.ts +2 -2
  52. package/template/client/src/features/auth/hooks/usePasswordReset.ts +2 -2
  53. package/template/client/src/hooks/useAppRouter.ts +40 -0
  54. package/template/client/src/styles/fonts/inter-jetbrains.css +4 -2
  55. package/template/client/src/styles/themes/default.css +1 -1
  56. package/template/gitignore +0 -6
  57. package/template/server/AGENTS.md +28 -0
  58. package/template/server/package-lock.json +671 -522
  59. package/template/server/package.json +8 -8
  60. package/template/_claude/QUICK_REFERENCE.md +0 -193
  61. package/template/_claude/README.md +0 -53
  62. package/template/_claude/commands/create-client.md +0 -878
  63. package/template/_claude/commands/create-server.md +0 -388
  64. package/template/_claude/hooks/restrict-paths.sh +0 -51
  65. package/template/_claude/rules/client/01-project-structure.md +0 -147
  66. package/template/_claude/rules/client/02-components-and-types.md +0 -146
  67. package/template/_claude/rules/client/03-data-and-state.md +0 -195
  68. package/template/_claude/rules/client/04-design-system.md +0 -408
  69. package/template/_claude/rules/client/05-security.md +0 -55
  70. package/template/_claude/rules/client/06-ux-checklist.md +0 -111
  71. package/template/_claude/rules/client/07-deployment.md +0 -99
  72. package/template/_claude/rules/client/08-lockfile-cross-platform.md +0 -79
  73. package/template/_claude/rules/client/core.md +0 -46
  74. package/template/_claude/rules/global/completion-reports.md +0 -178
  75. package/template/_claude/rules/global/core.md +0 -104
  76. package/template/_claude/rules/global/investigation-before-conclusions.md +0 -57
  77. package/template/_claude/rules/server/core.md +0 -52
  78. package/template/_claude/rules/server/database.md +0 -124
  79. package/template/_claude/rules/server/deployment.md +0 -78
  80. package/template/_claude/rules/server/project-conventions.md +0 -254
  81. package/template/_claude/rules/server/response-handling.md +0 -144
  82. package/template/_claude/settings.json +0 -15
  83. package/template/_claude/skills/clean-ui/SKILL.md +0 -63
  84. package/template/_claude/skills/role/SKILL.md +0 -39
  85. package/template/_claude/skills/theme/SKILL.md +0 -109
@@ -1,388 +0,0 @@
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, behind the `tools` profile
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, behind the `tools` profile
140
-
141
- Use a named network for all services. Add restart policies.
142
-
143
- **Security requirements (dev attack surface):**
144
- - Bind ALL published ports to localhost (`127.0.0.1:<port>:<container-port>`), never `0.0.0.0` — these are dev credentials (root password, unpassworded Redis).
145
- - Put the admin UIs (**phpmyadmin**, **redis-commander**) behind `profiles: ["tools"]` so they do NOT start by default:
146
- - `docker compose up -d` → MySQL + Redis only
147
- - `docker compose --profile tools up -d` → also starts phpMyAdmin + Redis Commander
148
-
149
- ---
150
-
151
- ### Step 2: Source Code Structure
152
-
153
- Create the following directory structure under `src/`:
154
-
155
- ```
156
- src/
157
- ├── app.ts # Fastify instance, plugin registration
158
- ├── server.ts # listen() call only
159
- ├── config/
160
- │ └── env.ts # Zod-validated environment variables
161
- ├── libs/
162
- │ ├── prisma.ts # Prisma client singleton
163
- │ ├── redis.ts # Redis client singleton
164
- │ ├── logger.ts # Pino logger
165
- │ └── auth.ts # JWT helpers (sign, verify, middleware)
166
- ├── shared/
167
- │ ├── errors/
168
- │ │ ├── AppError.ts # Base error class
169
- │ │ └── errors.ts # All typed error subclasses
170
- │ ├── responses/
171
- │ │ ├── successResponse.ts
172
- │ │ └── paginatedResponse.ts
173
- │ ├── schemas/
174
- │ │ └── pagination.schema.ts # Shared Zod pagination schema
175
- │ └── types/
176
- │ └── index.ts # Shared TypeScript types
177
- └── modules/
178
- └── auth/ # Auth module
179
- ├── auth.routes.ts
180
- ├── auth.controller.ts
181
- ├── auth.service.ts
182
- ├── auth.repo.ts
183
- └── auth.schemas.ts
184
- ```
185
-
186
- ---
187
-
188
- ### Step 3: Core Files Implementation
189
-
190
- #### `src/config/env.ts`
191
- - Use Zod to validate ALL environment variables at startup
192
- - Export typed `env` object
193
- - Crash immediately with clear message if validation fails
194
-
195
- #### `src/libs/logger.ts`
196
- - Use Pino logger
197
- - Pretty print in development, JSON in production
198
- - Export singleton `logger`
199
-
200
- #### `src/libs/prisma.ts`
201
- - Singleton Prisma client
202
- - Handle graceful shutdown (disconnect on process exit)
203
-
204
- #### `src/libs/redis.ts`
205
- - Singleton ioredis client
206
- - Configure from `REDIS_URL` env
207
- - Handle connection errors with logger
208
- - Handle graceful shutdown
209
-
210
- #### `src/libs/auth.ts`
211
- - JWT sign/verify using @fastify/jwt
212
- - Fastify `authenticate` preHandler decorator
213
- - Fastify `optionalAuth` preHandler decorator
214
- - Role-based `authorize(...roles)` preHandler
215
-
216
- #### `src/shared/errors/AppError.ts`
217
- - Base `AppError` class extending `Error` with: `code`, `statusCode`, `message`
218
-
219
- #### `src/shared/errors/errors.ts`
220
- - Export all subclasses: `BadRequestError`, `ValidationError`, `UnauthorizedError`, `ForbiddenError`, `NotFoundError`, `ConflictError`, `InternalError`
221
- - Each with appropriate default status code and code string
222
-
223
- #### `src/shared/responses/successResponse.ts`
224
- ```typescript
225
- export function successResponse<T>(message: string, data: T) {
226
- return { success: true as const, message, data };
227
- }
228
- ```
229
-
230
- #### `src/shared/responses/paginatedResponse.ts`
231
- ```typescript
232
- export function paginatedResponse<T>(
233
- message: string,
234
- items: T[],
235
- page: number,
236
- limit: number,
237
- totalItems: number
238
- ) {
239
- const totalPages = Math.ceil(totalItems / limit);
240
- return {
241
- success: true as const,
242
- message,
243
- data: {
244
- items,
245
- pagination: {
246
- page,
247
- limit,
248
- totalItems,
249
- totalPages,
250
- hasNextPage: page < totalPages,
251
- hasPreviousPage: page > 1,
252
- },
253
- },
254
- };
255
- }
256
- ```
257
-
258
- #### `src/shared/schemas/pagination.schema.ts`
259
- ```typescript
260
- import { z } from 'zod';
261
-
262
- export const PaginationSchema = z.object({
263
- page: z.coerce.number().int().min(1).default(1),
264
- limit: z.coerce.number().int().min(1).max(100).default(10),
265
- });
266
-
267
- export type PaginationInput = z.infer<typeof PaginationSchema>;
268
- ```
269
-
270
- #### `src/app.ts`
271
- - Create and configure Fastify instance
272
- - Register plugins: cors, helmet, rate-limit, cookie, jwt
273
- - Register health check route: `GET /api/v1/health` — returns `successResponse('Server is healthy', { status: 'ok', timestamp: new Date().toISOString() })`
274
- - Register global error handler that maps `AppError` → proper response format
275
- - Register routes with `/api/v1` prefix
276
- - Export the app instance
277
-
278
- The global error handler MUST:
279
- - Check if error is `AppError` → use its code, message, statusCode
280
- - Check if error is Zod validation error → 422 with validation details
281
- - Check if error is Fastify validation error → 400
282
- - Default to 500 Internal Server Error
283
- - Log internal errors with logger
284
- - NEVER expose stack traces or internal details to client
285
-
286
- #### `src/server.ts`
287
- - Import app from `app.ts`
288
- - Import env config
289
- - Call `app.listen({ port, host })`
290
- - Log startup message with port and environment
291
- - Handle graceful shutdown (SIGINT, SIGTERM) — close Fastify, disconnect Prisma, disconnect Redis
292
-
293
- ---
294
-
295
- ### Step 4: Auth Module
296
-
297
- Create a working auth module with these endpoints:
298
- - `POST /api/v1/auth/register` - Register new user
299
- - `POST /api/v1/auth/login` - Login with email/password
300
- - `POST /api/v1/auth/logout` - Logout (invalidate refresh token)
301
- - `POST /api/v1/auth/refresh` - Refresh access token
302
- - `GET /api/v1/auth/me` - Get current user (protected)
303
-
304
- Follow the layered architecture:
305
- - **auth.schemas.ts** - Zod schemas for register, login, refresh input
306
- - **auth.controller.ts** - Validate input, call service, return `successResponse()`
307
- - **auth.service.ts** - Business logic, bcrypt hashing, JWT token generation, throw typed errors
308
- - **auth.repo.ts** - Prisma queries for users and refresh tokens
309
- - **auth.routes.ts** - Fastify plugin registering routes with appropriate preHandlers
310
-
311
- ---
312
-
313
- ### Step 5: Prisma Setup
314
-
315
- #### `prisma/schema.prisma`
316
- ```prisma
317
- generator client {
318
- provider = "prisma-client-js"
319
- }
320
-
321
- datasource db {
322
- provider = "mysql"
323
- url = env("DATABASE_URL")
324
- }
325
-
326
- model User {
327
- id String @id @default(uuid())
328
- email String @unique
329
- password String
330
- firstName String
331
- lastName String
332
- role String @default("USER")
333
- isActive Boolean @default(true)
334
- deletedAt DateTime?
335
- createdAt DateTime @default(now())
336
- updatedAt DateTime @updatedAt
337
-
338
- refreshTokens RefreshToken[]
339
-
340
- @@map("users")
341
- }
342
-
343
- model RefreshToken {
344
- id String @id @default(uuid())
345
- token String @unique @db.VarChar(500)
346
- userId String
347
- expiresAt DateTime
348
- createdAt DateTime @default(now())
349
-
350
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
351
-
352
- @@index([userId])
353
- @@index([token])
354
- @@map("refresh_tokens")
355
- }
356
- ```
357
-
358
- #### `prisma/seed.ts`
359
- - Create a basic seed file that creates an admin user and a test user
360
- - Use bcrypt to hash passwords
361
- - Wrap in try/catch with proper logging
362
-
363
- ---
364
-
365
- ### Step 6: Final Verification
366
-
367
- After creating all files:
368
- 1. Run `npm install` to install dependencies
369
- 2. Run `docker compose up -d` to start services (if Docker is available, otherwise remind the user)
370
- 3. Wait for MySQL to be healthy, then run `npx prisma migrate dev --name init`
371
- 4. Run `npx prisma generate`
372
- 5. Run `npx prisma db seed`
373
- 6. Verify the project starts with `npm run dev`
374
- 7. Test health check: `curl http://localhost:3000/api/v1/health`
375
-
376
- If Docker is not running, inform the user they need to run `docker compose up -d` before running migrations.
377
-
378
- ---
379
-
380
- ## IMPORTANT RULES
381
-
382
- - Follow ALL rules from `.claude/rules/server/` and `.claude/rules/global/`
383
- - Use the EXACT response format from `response-handling.md` (includes pagination contract)
384
- - All routes prefixed with `/api/v1`
385
- - TypeScript strict mode
386
- - No `console.log` — use logger
387
- - No raw `Error` throws — use AppError subclasses
388
- - Named exports everywhere except `app.ts`
@@ -1,51 +0,0 @@
1
- #!/bin/bash
2
- # Restrict Claude's WRITE access based on the .developer-role file.
3
- # Claude can always READ any file for full project context.
4
- # Only Edit/Write operations are blocked on the other side's directory.
5
- #
6
- # NOTE: settings.json matcher already filters for Edit|Write only,
7
- # so this script does NOT need to check the tool name.
8
- #
9
- # To switch roles, either:
10
- # 1. Edit .developer-role and type: frontend, backend, or fullstack
11
- # 2. Use /role command in Claude
12
- #
13
- # fullstack (or empty/missing file) = no restrictions
14
-
15
- ROLE_FILE="$CLAUDE_PROJECT_DIR/.developer-role"
16
-
17
- # Read role from first non-comment, non-empty line
18
- if [ -f "$ROLE_FILE" ]; then
19
- ROLE=$(grep -v '^\s*#' "$ROLE_FILE" | grep -v '^\s*$' | head -1 | tr -d '[:space:]')
20
- else
21
- ROLE=""
22
- fi
23
-
24
- # No file, empty, or fullstack = full access
25
- if [ -z "$ROLE" ] || [ "$ROLE" = "fullstack" ]; then
26
- exit 0
27
- fi
28
-
29
- # Read the full JSON input from Claude Code
30
- INPUT=$(cat)
31
-
32
- deny_with_reason() {
33
- cat <<DENY_EOF
34
- {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"$1"}}
35
- DENY_EOF
36
- exit 0
37
- }
38
-
39
- # Simple path check against the raw JSON input.
40
- # No JSON parsing needed — just check if the input contains server/ or client/ paths.
41
- if [ "$ROLE" = "frontend" ]; then
42
- if echo "$INPUT" | grep -qiE "server[/\\\\]"; then
43
- deny_with_reason "BLOCKED: Role is set to frontend. You can read server/ files but cannot modify them. Only the backend developer can edit server/ code."
44
- fi
45
- elif [ "$ROLE" = "backend" ]; then
46
- if echo "$INPUT" | grep -qiE "client[/\\\\]"; then
47
- deny_with_reason "BLOCKED: Role is set to backend. You can read client/ files but cannot modify them. Only the frontend developer can edit client/ code."
48
- fi
49
- fi
50
-
51
- exit 0
@@ -1,147 +0,0 @@
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
- ├── styles/
36
- │ ├── themes/ # Color theme (light/dark mode values)
37
- │ │ └── default.css # Claude-inspired warm palette (HEX)
38
- │ └── fonts/ # Font presets (switch in globals.css import)
39
- │ └── inter-jetbrains.css # Default — Inter + JetBrains Mono
40
- ├── hooks/ # Global hooks (useDebounce, useLocalStorage, useMediaQuery)
41
- ├── lib/
42
- │ ├── api/ # axios.config.ts, api.types.ts
43
- │ ├── constants/ # routes.ts, api-endpoints.ts, app.constants.ts
44
- │ └── utils/ # format.ts, validation.ts, error.ts, cn() helper
45
- ├── store/ # Redux store (index.ts, hooks.ts)
46
- ├── types/ # Global types
47
- └── middleware.ts # Auth route protection
48
- ```
49
-
50
- ## File Naming
51
-
52
- | Type | Pattern | Example |
53
- |---|---|---|
54
- | Component | `PascalCase.tsx` | `ProductCard.tsx` |
55
- | Page | `folder/page.tsx` | `products/page.tsx` |
56
- | Hook | `use<Name>.ts` | `useAuth.ts` |
57
- | Service | `<domain>.service.ts` | `product.service.ts` |
58
- | Types | `<domain>.types.ts` | `product.types.ts` |
59
- | Redux slice | `<domain>Slice.ts` | `authSlice.ts` |
60
- | Server Action | `<domain>.actions.ts` | `product.actions.ts` |
61
- | Page exports | `default export` | Required by Next.js |
62
- | Everything else | Named exports | `export const ProductCard` |
63
-
64
- ## Import Order
65
-
66
- 1. React / Next.js (`useState`, `useRouter`, `Image`, `Link`)
67
- 2. Third-party (`@tanstack/react-query`, `sonner`)
68
- 3. UI components (`@/components/ui/*`)
69
- 4. Local components
70
- 5. Hooks
71
- 6. Services
72
- 7. Types (always `import type`)
73
- 8. Utils (`cn`, `formatDate`)
74
-
75
- ## Constants
76
-
77
- ```typescript
78
- // lib/constants/api-endpoints.ts
79
- export const API_ENDPOINTS = {
80
- AUTH: {
81
- REGISTER: '/auth/register',
82
- LOGIN: '/auth/login',
83
- LOGOUT: '/auth/logout',
84
- REFRESH: '/auth/refresh',
85
- ME: '/auth/me',
86
- REQUEST_PASSWORD_RESET: '/auth/request-password-reset',
87
- RESET_PASSWORD: '/auth/reset-password',
88
- },
89
- USERS: {
90
- ME: '/users/me',
91
- UPDATE_ME: '/users/me',
92
- DELETE_ME: '/users/me',
93
- },
94
- // Add domain-specific endpoints following this pattern:
95
- // <DOMAIN>: {
96
- // LIST: '/<domain>',
97
- // CREATE: '/<domain>',
98
- // GET: (id: string) => `/<domain>/${id}`,
99
- // UPDATE: (id: string) => `/<domain>/${id}`,
100
- // DELETE: (id: string) => `/<domain>/${id}`,
101
- // },
102
- } as const;
103
-
104
- // lib/constants/routes.ts
105
- export const ROUTES = {
106
- HOME: '/',
107
- LOGIN: '/login',
108
- REGISTER: '/register',
109
- RESET_PASSWORD: '/reset-password',
110
- DASHBOARD: '/dashboard',
111
- PROFILE: '/profile',
112
- // Add domain-specific routes following this pattern:
113
- // <DOMAIN>: {
114
- // LIST: '/<domain>',
115
- // DETAILS: (id: string) => `/<domain>/${id}`,
116
- // CREATE: '/<domain>/create',
117
- // EDIT: (id: string) => `/<domain>/${id}/edit`,
118
- // },
119
- } as const;
120
-
121
- // lib/constants/app.constants.ts
122
- export const APP_NAME = 'My App';
123
- export const PAGINATION = { DEFAULT_PAGE: 1, DEFAULT_LIMIT: 10, MAX_LIMIT: 100 } as const;
124
- export const USER_ROLES = { USER: 'USER', ADMIN: 'ADMIN' } as const;
125
- export const CURRENCIES = { USD: 'USD', EUR: 'EUR' } as const;
126
- ```
127
-
128
- ## App Providers
129
-
130
- `app/providers.tsx` wraps the app with: **ReduxProvider** (store) → **QueryClientProvider** (React Query) → **Toaster** (sonner, position: top-right).
131
-
132
- ## Middleware
133
-
134
- Protected paths: `/dashboard`, `/profile`, `/admin` — redirect to `/login` if no token.
135
- Auth paths: `/login`, `/register` — redirect to `/dashboard` if already authenticated.
136
-
137
- When creating a new page, always add it to `protectedPaths` and `config.matcher` in `middleware.ts` if it requires authentication. If you are unsure whether a page should be protected, **ask the user** — do not guess.
138
-
139
- ### Deleting a Route
140
-
141
- When removing a page/route, you MUST update **all three** locations:
142
-
143
- 1. **Delete the page file**: `app/<route>/page.tsx` (and the folder if empty)
144
- 2. **Remove from `routes.ts`**: Delete the entry in `lib/constants/routes.ts`
145
- 3. **Remove from `middleware.ts`**: Delete from `protectedPaths` array AND `config.matcher` array
146
-
147
- Missing any of these leaves dead references or broken middleware matches.