Skip to content

Latest commit

 

History

History
145 lines (118 loc) · 8.46 KB

File metadata and controls

145 lines (118 loc) · 8.46 KB

Project Overview

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.

Code Style

Exports and Imports

  • 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.

Naming Conventions

  • 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.

TypeScript

  • 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'.

Formatting

  • 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.

File Structure

Root-level directories

  • 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/ subdirectories (mandatory)

  • 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/.

Component organization

  • 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 route organization

  • 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.

Patterns

Server vs Client Components

  • 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.

Data Fetching

  • 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.

Error Handling

  • 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.

Async Components and Loading States

  • 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.

Form Handling

  • 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.

State Management

  • 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.

Environment Variables

  • 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.

Singleton Instances

  • 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.

Testing

Test File Location and Naming

  • 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.

What Must Be Tested

  • 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.

Test Structure

  • 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.

Assertions and Mocking

  • 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>