general

  • Keep it clear and simple.
  • Prefer long-term fixes over short-term patches.
  • Prefer boring, maintainable structure over clever abstractions.
  • Keep changes focused. Every changed line should trace to the request, a test, or cleanup caused by the change.
  • State assumptions and tradeoffs before editing when scope or behavior is ambiguous.
  • For multi-step work, use concrete success criteria and verify them.

code style

  • Prefer standard-library built-ins over hand-rolled equivalents.
  • Do not use TypeScript any. Use unknown with explicit parsing, narrow unions, or well-defined interfaces.
  • Use runtime schemas to validate untrusted inputs and API boundaries.
  • Trust the type system. Do not add runtime guards or re-parse values the types already guarantee.
  • Use interface for component props and shared object shapes. Use type for unions, function aliases, mapped types, and utility-composed shapes.
  • Delete unreachable branches, redundant guards, unused values, and unnecessary wrappers.
  • Do not add lint, format, or type suppressions.
  • Prefer arrow functions for components, helpers, and callbacks.
  • Avoid single-use indirection unless a name improves clarity or prevents a maintenance hazard.
  • Keep code comment-free unless a comment prevents a real maintenance hazard.
  • Extract long conditions and multi-branch render logic into named helpers or booleans.
  • Inside async functions, prefer await with try/catch over chained promises. Handle a rejection once, in the function that owns the work.

architecture and state

  • Prefer shared state over passing the same props through many layers.
  • Prefer composite components over deep prop chains.
  • Extract helpers used in more than one file into a shared domain folder.
  • Read environment variables through a central module.
  • Model loading state with explicit discriminated unions.
  • Keep external content extraction bounded with explicit time, size, and count limits.
  • Design for portability, permissions, and lazy loading from the start.

react and preact

  • Use effects to synchronize with external systems. Do not use effects for derived state.
  • For async state tied to an id, store the loaded value with its key and derive stale or loading states during rendering.
  • Clean up every timer, animation frame, listener, watcher, subscription, and observer.
  • Avoid duplicate polling. Batch frequent visual updates with animation frames and throttle non-visual updates.
  • Extract involved effect setup, data fetching, and subscriptions into named hooks.
  • Render JSX inline or extract a named component. Do not store elements in variables.
  • Pass handlers directly when they already handle their errors. Do not add another error-handling wrapper.

styling and interaction

  • Use descriptive theme names.
  • Prefer styling utilities over custom CSS and named utilities over arbitrary values.
  • Do not add theme tokens that duplicate defaults.
  • Keep utility classes inline. When styling repeats, extract a component.
  • Build controls on established UI primitives.
  • Use toggles for binary settings and a consistent accent for selected states.
  • Keep small controls visually stable and expand their hit areas when needed.
  • Avoid flicker and unnecessary renders. Memoize only when it helps.
  • Animate opacity and transform for high-frequency UI.
  • Keep layouts stable while content loads. Prefer cached content with a background refresh.
  • Keep primary content direct. Put diagnostics, metadata, and supporting output behind collapsed details.
  • Keep copy short and plain. Do not use em dashes.
  • Use system UI fonts.

naming and files

  • Keep names minimal, precise, and contextual. Do not repeat the component or domain name in its props.
  • Use camelCase for variables, functions, hooks, and constants; PascalCase for types and components; kebab-case for files, folders, CSS custom properties, and storage keys.
  • Namespace persisted storage keys and name their constants with a StorageKey suffix.
  • Split component files before they approach 300 lines.
  • Group related files by domain. Keep filenames short and avoid repeating the parent folder name.
  • Group related declarations and separate groups with a blank line.
  • Sort sortable code by line length when it does not hurt readability or break framework conventions.

investigation and dependencies

  • Check the code first when answering behavior questions.
  • Use documentation, tests, help output, or a running application when the code does not answer the question.
  • Distinguish current code, observed behavior, and planned design.
  • Use maintained tools and packages. Check current documentation before choosing versions or security-sensitive dependencies.
  • Prefer secure defaults. Do not knowingly introduce vulnerable packages.
  • Verify review feedback against current code before acting. Resolve outstanding findings before merging.

git and documentation

  • Start non-trivial work from the latest main branch.
  • Keep the primary checkout clean. Use temporary worktrees for branch work when practical.
  • Remove temporary worktrees and remote branches after merging. Do not leave generated or scratch files behind.
  • Keep commits, issue titles, and pull request titles lowercase, simple, and precise.
  • Use conventional prefixes such as fix:, feat:, chore:, or docs: when useful.
  • Keep pull request descriptions concise. Leave out machine paths and setup details unless they matter to the product.
  • Include the goal, scope, and completion criteria in issues.
  • Update documentation when behavior, configuration, or file layouts change.
  • Keep architecture diagrams aligned with the implementation.

validation

  • Add or update focused tests for behavior changes. Extract pure logic when needed to test it.
  • Keep mocks faithful to real runtime behavior. Fix inaccurate mocks instead of changing production code to satisfy them.
  • Add or update benchmarks for performance-sensitive changes.
  • Run focused checks first, then broader validation before merging.
  • Run dependency and security checks for security-sensitive changes.
  • Keep code warning-free and error-free. Run the required project checks before reporting completion.