This is a Next.js App Router project using React, TypeScript, and server-side rendering as the default pattern. All code must assume server components are the first choice, client components are opt-in via 'use client', and API routes are in app/api/. TypeScript strict mode is enforced everywhere.
- All exports must be named exports. Never use default exports except for Next.js page.tsx and layout.tsx files.
- Import statements must use absolute paths from tsconfig.json baseUrl, never relative paths with ../../../.
- Group imports in this order: React/Next.js, third-party packages, @/ absolute imports, then types (import type { ... } from).
- Never import from node_modules directly; always use the package name.
- File names must be lowercase with hyphens: user-profile.tsx, fetch-user-data.ts, not UserProfile.tsx or fetchUserData.ts.
- React component files must end in .tsx, utility files in .ts, never mix.
- Component names must match their file name in PascalCase: file user-profile.tsx exports component UserProfile.
- Hook files must start with use-: use-auth.ts, use-form-validation.ts.
- Utility function files must be descriptive: format-date.ts, validate-email.ts, not utils.ts or helpers.ts.
- Constants files must be UPPER_SNAKE_CASE: API_ENDPOINTS.ts, ERROR_MESSAGES.ts.
- Type definition files must end in .types.ts: user.types.ts, api-response.types.ts.
- Never use any type. If the shape is unknown, use unknown and narrow it with type guards or Zod validation.
- Never use as type assertions outside of test files. Use type guards, Zod .parse(), or satisfies operator instead.
- All function parameters and return types must be explicitly typed. No implicit any.
- All object literals must have explicit type annotations or be validated with Zod at runtime boundaries.
- Use const assertions for literal types: const ROLE = 'admin' as const, not const ROLE = 'admin'.
- Use 2-space indentation, never tabs.
- Line length maximum 100 characters. Break long lines at logical boundaries.
- Use single quotes for strings, never double quotes.
- Trailing commas required in multi-line objects, arrays, and function parameters.
- No semicolons at end of statements.
- app/ — Next.js App Router pages, layouts, and API routes only.
- src/ — All application code: components, hooks, utils, types, services.
- public/ — Static assets only, never code.
- tests/ — All test files, mirroring src/ structure exactly.
- src/components/ — React components only, organized by feature or domain.
- src/hooks/ — Custom React hooks only.
- src/utils/ — Pure utility functions, no side effects.
- src/services/ — API clients, database clients, external service integrations.
- src/types/ — Shared TypeScript types and interfaces.
- src/constants/ — Constants, configuration, enums.
- src/middleware/ — Next.js middleware.ts at root level, not in src/.
- Each component must have its own directory: src/components/user-card/user-card.tsx.
- Component directory must contain: component file, .types.ts file if needed, index.ts for exports.
- Never put multiple components in one file.
- Shared component styles go in src/components/shared/ subdirectory.
- API routes must be in app/api/ following Next.js conventions: app/api/users/route.ts.
- Each route file must export only the HTTP methods it handles: export { GET, POST }.
- Request/response types must be in src/types/api/ with file name matching route: src/types/api/users.types.ts.
- Default to server components. Only add 'use client' when component uses hooks, event handlers, or browser APIs.
- Data fetching must happen in server components using async/await directly, never in useEffect.
- Never fetch data in useEffect. Use server components or Next.js data fetching patterns instead.
- Client components that need data must receive it as props from server component parents.
- Create a dedicated service file for each external API: src/services/user-service.ts, src/services/payment-service.ts.
- All service functions must return typed responses using Zod validation: const response = UserSchema.parse(data).
- Never create database or API clients inline. Import the singleton from src/services/db.ts or src/services/api-client.ts.
- All fetch calls must include explicit error handling with typed catch blocks.
- Create src/types/errors.types.ts with AppError class extending Error with code and statusCode properties.
- Every async function must have try/catch. Caught errors must be typed: catch (err) { if (err instanceof AppError) ... }.
- Never catch (e: any) or catch (e). Always type the error: catch (err: unknown).
- API routes must return error responses with consistent shape: { error: string, code: string, statusCode: number }.
- Client-side errors must be caught and logged to error tracking service, never silently ignored.
- Every async server component must have loading.tsx and error.tsx siblings in the same directory.
- Async components must render Suspense boundaries with fallback UI for each async operation.
- Client components using async data must render loading state, error state, and empty state explicitly.
- Never render undefined or null without checking; use conditional rendering or fallback UI.
- All form inputs must be validated with Zod schemas defined in src/types/ directory.
- Form submission must use server actions (async functions marked with 'use server') in separate files.
- Client-side form components must use React Hook Form with Zod resolver.
- Never submit form data without validation on both client and server.
- Use React Context only for theme, auth, or global UI state. Never for business logic or data.
- Use server components and props for data flow. Never lift data to Context unnecessarily.
- If state is complex, use a custom hook with useState/useReducer, not Context.
- All environment variables must be defined in .env.local, .env.development, .env.production.
- Client-side env vars must be prefixed with NEXT_PUBLIC_. Server-side vars have no prefix.
- Never hardcode API keys, database URLs, or secrets anywhere in code.
- Never log environment variables or secrets to console, even in development.
- Import env vars from a single src/config/env.ts file that validates them at startup with Zod.
- Database clients must be created once in src/services/db.ts and exported as singleton.
- API clients must be created once in src/services/api-client.ts and exported as singleton.
- Never create new client instances inline. Always import the singleton.
- Test files must be in tests/ directory mirroring src/ structure exactly.
- Test file name must match source file with .test.ts or .test.tsx suffix: src/utils/format-date.ts → tests/utils/format-date.test.ts.
- Never put test files in src/ directory or co-locate with source files.
- All utility functions must have unit tests covering happy path and error cases.
- All Zod schemas must have tests validating valid input, invalid input, and edge cases.
- All API routes must have integration tests for each HTTP method they export.
- All custom hooks must have tests using @testing-library/react renderHook.
- All error handling paths must be tested explicitly, not just happy paths.
- Use Vitest as test runner, Jest as test framework syntax.
- Each test file must have describe() block matching the source file name.
- Each test must have descriptive name: test('should return formatted date when given valid timestamp').
- Never use test.skip() or test.only() in committed code.
- Mock external services with vi.mock() at top of test file, never inline.
- Use @testing-library/react for component testing, never shallow rendering.
- Mock API calls with MSW (Mock Service Worker) in tests/setup.ts, not vi.mock().
- Never mock internal utility functions; test them directly.
- Assert on user-visible behavior, not implementation details.
Source: Codelibrium — the marketplace for AI behaviour files. Browse multiple rulesets at codelibrium.com or install via CLI:
npx codelibrium-cli install <ruleset-name>