Cursor Rules — TypeScript + React Codebase
A .cursorrules file for TypeScript/React teams: strict typing, React Query for server state, accessibility non-negotiables, and test conventions.
# Cursor rules for this repository
## TypeScript
- `strict: true` semantics always. Never use `any`; use `unknown` and narrow it. Never use non-null assertions (`!`) — handle the null case or fix the type.
- Prefer type inference for locals; explicit types for all exported functions and public APIs.
- Domain types live in `src/types/`. Do not redeclare an existing domain type locally — import it.
- Use discriminated unions over boolean flags: `{ status: 'loading' | 'error' | 'success' }`, never `{ isLoading, isError }` pairs.
## React
- Function components only, hooks only. No class components, no HOCs for new code.
- Server state belongs in React Query (TanStack): no fetching in useEffect. Local UI state in useState/useReducer. Global client state in Zustand — and question whether it's really global.
- Components over 150 lines get split. Extract custom hooks when logic (not JSX) exceeds ~20 lines.
- Every interactive element must be keyboard-accessible with a visible focus state. Images need alt text. Form fields need labels — this is not optional polish.
- Event handlers named `handleX`, props named `onX`.
## Files & structure
- One component per file, named exports (default exports only for route/lazy modules).
- Colocate: `Component.tsx`, `Component.test.tsx`, `useComponentLogic.ts` in the same folder.
- Absolute imports via `@/` alias, never `../../..`.
## Tests
- Vitest + React Testing Library. Query by role/label (what users see), never by test-id unless there is no accessible alternative — and then add a comment explaining why.
- Mock at the network boundary with MSW; do not mock React Query itself.
## When editing
- Fix TypeScript errors properly, never with `@ts-ignore`. If truly unavoidable, use `@ts-expect-error` with a reason comment.
- Do not disable ESLint rules inline without a comment justifying it.
- Match the style of surrounding code even where these rules are silent.
Comments (0)