-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreact-nextjs-ts.mdc
More file actions
120 lines (90 loc) · 7.21 KB
/
Copy pathreact-nextjs-ts.mdc
File metadata and controls
120 lines (90 loc) · 7.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
---
description: Production rules for React, Next.js App Router, and TypeScript — stops the most common AI mistakes.
globs: ""
alwaysApply: true
---
## Export Style
- All exports must be named exports. Default exports are forbidden except in Next.js page.tsx and layout.tsx files.
- Import statements must use named imports: `import { Button } from '@/components/Button'` not `import Button from '@/components/Button'`
- Re-export barrels must use `export { ComponentA } from './ComponentA'` not `export { default as ComponentA }`
## File Naming and Location
- React components live in `/app/components/` with PascalCase filenames: `Button.tsx`, `UserCard.tsx`
- Server components must have `.server.tsx` suffix: `UserList.server.tsx`
- Client components must have `.client.tsx` suffix: `SearchInput.client.tsx`
- Hooks live in `/app/hooks/` with camelCase filenames prefixed with `use`: `useAuth.ts`, `usePagination.ts`
- Utilities live in `/app/lib/` with camelCase filenames: `formatDate.ts`, `validateEmail.ts`
- API routes live in `/app/api/` following Next.js conventions: `/app/api/users/route.ts`
- Never create files in `/pages/` directory. All routing uses `/app/` with App Router
## TypeScript Types
- Never use `any` type. Use `unknown` with type guards or explicit types instead
- Never use `as` type assertions outside of `.test.ts` and `.spec.ts` files
- All function parameters must have explicit types: `function getName(id: string): string` not `function getName(id)`
- All React component props must be typed with interfaces: `interface ButtonProps { label: string; onClick: () => void }` not inline types
- API response types must be defined in `/app/lib/types/` with `.ts` extension: `user.ts`, `product.ts`
## Data Fetching
- Never use `useEffect` for data fetching in client components. Use server components instead
- Server components must fetch data directly: `const data = await db.query(...)` not `const [data, setData] = useState()`
- Client components that need async data must receive it as props from server component parents
- All fetch calls must include explicit error handling with typed catch blocks
- Never use `fetch()` directly in components. Import from `/app/lib/api/client.ts` or `/app/lib/api/server.ts`
## Database and External Services
- Database clients must be imported from `/app/lib/db.ts` singleton, never instantiated inline
- Supabase client must be imported from `/app/lib/supabase.ts` singleton, never created with `createClient()` in components
- All database queries must be wrapped in try/catch with typed error handling
- Query results must be validated with Zod schemas before use: `const user = userSchema.parse(result)`
## Security
- Environment variables used in client components must be prefixed with `NEXT_PUBLIC_`. All other env vars are forbidden in client code
- API keys, database passwords, and secrets must never appear in component files, only in `/app/lib/` or `.env.local`
- All API route handlers must validate input with Zod: `const params = routeParamsSchema.parse(req.nextUrl.searchParams)`
- User input from forms must be validated server-side in API routes, never trusted from client
- Never log sensitive data (passwords, tokens, API keys) to console or error handlers
## Error Handling
- All async functions must have try/catch blocks. Catch blocks must type the error: `catch (err) { if (err instanceof AppError) ... }`
- Never use bare `catch (e)` or `catch (e: any)`. Always type: `catch (err: unknown)`
- API routes must return structured error responses: `{ error: { code: 'USER_NOT_FOUND', message: '...' } }`
- Client components must display error states: every async operation needs an error boundary or error state variable
- Errors must be propagated up with context: `throw new AppError('Failed to fetch user', { cause: originalError })`
## Loading and Empty States
- Every server component that fetches data must have a corresponding loading skeleton component
- Loading skeleton must be named `{ComponentName}Skeleton.tsx` and live in same directory
- Client components with async operations must have `isLoading` state and display loading UI
- Empty states must be explicit: `if (items.length === 0) return <EmptyState />`
- Suspense boundaries must wrap async components: `<Suspense fallback={<Skeleton />}><AsyncComponent /></Suspense>`
## React Patterns
- All state must use `useState` with explicit types: `const [count, setCount] = useState<number>(0)` not `useState(0)`
- useCallback must be used for all event handlers passed to child components
- useMemo must be used for expensive computations or object/array creation in render
- useRef must have explicit type: `const ref = useRef<HTMLInputElement>(null)`
- Never use `useContext` without a custom hook wrapper in `/app/hooks/`
## Form Handling
- Forms must use React Hook Form with Zod validation: `const { register, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(schema) })`
- Form validation schemas must live in `/app/lib/schemas/` with `.ts` extension: `loginSchema.ts`, `userSchema.ts`
- Never use uncontrolled inputs with `defaultValue`. Use controlled inputs with `value` and `onChange`
- Form submission must be async with error handling and success feedback
## Testing
- Test files must be colocated with source: `Button.tsx` has `Button.test.tsx` in same directory
- Test files must use `.test.ts` or `.test.tsx` suffix, never `.spec.ts`
- All public functions in `/app/lib/` must have corresponding test files
- All custom hooks must have test files in `/app/hooks/__tests__/`
- Tests must use `vitest` and `@testing-library/react`. Never use Jest directly
- Mock external services in `/app/lib/__mocks__/` with matching filenames
## API Routes
- API route handlers must be named `route.ts` inside route-specific directories: `/app/api/users/[id]/route.ts`
- All API handlers must validate HTTP method: `if (req.method !== 'POST') return Response.json({ error: 'Method not allowed' }, { status: 405 })`
- API responses must include proper status codes: 200, 201, 400, 401, 403, 404, 500
- API route handlers must catch errors and return 500 with generic message, never expose internal error details to client
## Naming Conventions
- Boolean variables and functions must start with `is`, `has`, `can`, or `should`: `isLoading`, `hasError`, `canDelete`
- Event handlers must be prefixed with `handle`: `handleClick`, `handleSubmit`, `handleChange`
- Callback props must be prefixed with `on`: `onClick`, `onSubmit`, `onError`
- Constants must be UPPER_SNAKE_CASE: `MAX_RETRIES`, `DEFAULT_TIMEOUT`
- Private functions in modules must be prefixed with underscore: `_formatInternalDate`, `_validateSchema`
## Imports and Dependencies
- Import order must be: React/Next.js → external libraries → internal absolute imports → relative imports
- Absolute imports must use `@/` alias: `import { Button } from '@/components/Button'` not `import { Button } from '../../../components/Button'`
- Never import from `/app/` directly. Always use `@/` alias
- Circular imports are forbidden. Refactor shared code into `/app/lib/`
---
> Source: [Codelibrium](https://codelibrium.com) — the marketplace for AI behaviour files.
> Browse multiple rulesets at [codelibrium.com](https://codelibrium.com) or install via CLI:
> `npx codelibrium-cli install <ruleset-name>`