- All exports must be named exports. Default exports are forbidden except for Next.js page components in
/pagesand/appdirectories. - Export statements must appear at the end of the file, never inline with declarations.
- Re-export barrels in
index.tsfiles must useexport { NamedExport } from './module'syntax only.
- React components must be PascalCase:
UserProfile.tsx, neveruserProfile.tsxoruser-profile.tsx. - Utility functions must be camelCase:
formatDate.ts,validateEmail.ts. - Hook files must start with
use:useAuth.ts,useFetchUser.ts. - Test files must be colocated with source and named
ComponentName.test.tsxorfunctionName.test.ts. - Store all components in
/src/components, organized by feature subdirectories:/src/components/auth/LoginForm.tsx, never flat. - Store all hooks in
/src/hooks, never nested in component directories. - Store all utilities in
/src/utils, organized by domain:/src/utils/api/,/src/utils/validation/. - Store all types in
/src/types, with files named by domain:user.ts,api.ts, never a singletypes.ts.
- Never use
anytype. If shape is unknown, useunknownand narrow with type guards or Zod validation. - Never use
astype assertions outside of.test.tsfiles. Use type guards,satisfies, or Zod.parse()instead. - All function parameters must have explicit types. No implicit
any. - All function return types must be explicit. No implicit inference for exported functions.
- Object shapes must be defined as interfaces or types before use, never inline in function signatures.
- Use
Record<string, T>for object maps, never{ [key: string]: T }. - Use
readonlyfor immutable arrays and objects in type definitions.
- All components must be functional components with hooks. Class components are forbidden.
- Component files must export exactly one component. Helper components must be in separate files.
- Props interfaces must be named
{ComponentName}Propsand defined above the component. - Props must be destructured in the function signature, never accessed via
props.x. - All components must have explicit return type:
React.ReactNode,JSX.Element, ornull. - Never use
React.FCorReact.FunctionComponent. Use function declaration with explicit return type.
- State updates must never mutate directly. Always use spread operator or immutable patterns.
- For object state:
setState({ ...state, field: newValue }). - For array state:
setState([...array, newItem])orsetState(array.map(...)), neverarray.push(). - Use
useCallbackfor any function passed to child components or used in dependency arrays. - Use
useMemoonly when computation is expensive (>1ms) or dependency array prevents re-renders. Never use for simple values.
- Every
useEffectmust have an explicit dependency array. Never omit it. - Data fetching must use
useEffectwith cleanup: abort controller or cleanup function that cancels pending requests. - Never call async functions directly in
useEffect. Wrap in an inner async function or use a library likereact-query. - If
useEffectsets state, it must have a cleanup function that cancels or ignores results:isMountedflag or AbortController. - Multiple related state updates in
useEffectmust be batched withflushSyncif order matters, otherwise React batches automatically.
- All async functions must have try/catch blocks. Never let promises reject unhandled.
- Caught errors must be typed:
catch (err) { if (err instanceof SpecificError) ... }, nevercatch (e: any)or barecatch. - Create an
AppErrorclass in/src/utils/errors.tswithcode,message, andstatusCodeproperties. Throw onlyAppErrorinstances from business logic. - HTTP errors must be caught and converted to
AppErrorwith appropriate status codes before returning to components. - Components must display error states: render error message from state, never console.log errors.
- Error boundaries must wrap feature sections in
/src/components/ErrorBoundary.tsx. Never leave error boundaries unimplemented.
- All API calls must go through
/src/utils/api/client.ts, a centralized fetch wrapper that handles auth headers and error conversion. - API response types must be defined in
/src/types/api.tswith request and response shapes separated:GetUserRequest,GetUserResponse. - Validate all API responses with Zod schemas in
/src/utils/validation/schemas.tsbefore using in components. - Loading and error states must always be tracked:
{ data, loading, error }or equivalent, never assume success. - Never hardcode API URLs. Use environment variables:
process.env.REACT_APP_API_URL, validated at app startup in/src/config.ts.
- All user inputs must be validated at the component boundary before sending to API or state.
- Use Zod for validation:
const schema = z.object({ email: z.string().email() }); schema.parse(input). - Form validation must happen on blur and submit, never on every keystroke.
- Display validation errors inline next to form fields, never in console or alerts.
- Never trust data from URL params or query strings. Parse and validate with Zod before use.
- Never commit secrets, API keys, or tokens to git. Use
.env.local(gitignored) for local development. - All environment variables must be prefixed with
REACT_APP_to be accessible in browser code. - Validate and sanitize all data from external sources (API, URL params, localStorage) before rendering or using in logic.
- Never use
dangerouslySetInnerHTML. If HTML rendering is required, use a sanitization library likeDOMPurify. - CSRF tokens must be included in all state-changing requests (POST, PUT, DELETE). Retrieve from response headers or meta tags, never hardcode.
- Every component must have a
.test.tsxfile with at least one test. Untested components block PR merge. - Every utility function must have a
.test.tsfile. Pure functions must have >80% branch coverage. - Tests must use React Testing Library, never Enzyme or shallow rendering.
- Test user interactions, not implementation:
userEvent.click(screen.getByRole('button', { name: /submit/i })), neverwrapper.find('.submit-btn').simulate('click'). - Mock API calls with
msw(Mock Service Worker) in/src/mocks/handlers.ts, never mock fetch directly. - Async tests must use
await screen.findBy*()orwaitFor(), neversetTimeout. - Test error states explicitly: render component with error prop, verify error message displays.
- Boolean variables and functions must start with
is,has,can, orshould:isLoading,hasError,canSubmit. - Event handlers must be named
handle{Event}:handleClick,handleSubmit,handleInputChange. - Callback props must be named
on{Event}:onClick,onSubmit,onInputChange. - API functions must be named
fetch{Resource}orget{Resource}:fetchUser,getUserById, never justgetUserif it takes parameters. - Constants must be UPPER_SNAKE_CASE:
MAX_RETRIES,API_TIMEOUT_MS.
- Never use
.then()chains. Always use async/await for readability. - All async functions must have explicit
Promise<ReturnType>return type. - Promise.all() must be used for parallel operations, never sequential awaits.
- Timeouts must be explicit: wrap with
Promise.race([operation, timeout(ms)])or use library utilities, never rely on implicit timeouts.
Source: Codelibrium — the marketplace for AI behaviour files. Browse multiple rulesets at codelibrium.com or install via CLI:
npx codelibrium-cli install <ruleset-name>