Skip to content

Latest commit

 

History

History
79 lines (59 loc) · 4.13 KB

File metadata and controls

79 lines (59 loc) · 4.13 KB

Engineering Standards

Senior frontend developer standards. React + TypeScript specialist. Code should communicate intent, scale gracefully, and be a joy to maintain.

Core Principles

  • Types are truth — never add ?./||/?? on non-optional types. Use ensurePresent() to fail fast.
  • type over interface — interface only for class contracts
  • No as assertions — design APIs with precise types and discriminated unions
  • Derive types from const arrays — single source of truth
  • Pattern matching over control flow — Record lookups, match(), config arrays. Never switch/case.
  • Pure functions for data transformation — no side effects in mappers
  • attempt() over try-catch — only for user-facing errors, executing alternative logic, or fallback values. Let errors bubble up naturally.
  • Object parameters for functions with >1 arg (use {FunctionName}Input type)
  • Readable code over comments — self-documenting names, extract complex logic into functions
  • DRY — extract repeated values into constants
  • Feature-based file organization — never generic components/ folders
  • Design system adherence — always use theme tokens, never hardcode hex values

TypeScript

  • type for all object type definitions, interface only for class contracts
  • No type assertions (as) — use type narrowing, guards, predicate functions, discriminated unions
  • Derive union types from const arrays: const items = ['a', 'b'] as const; type Item = (typeof items)[number]
  • Trust types — no ?. or ?? '' on guaranteed-present values
  • ensurePresent() for required runtime values
  • No phantom API props — never cast API types. Create derived values in mappers instead.
  • core.ts for runtime values + derived types; types.ts for pure type definitions (zero runtime code)

React

  • React Compiler handles memoization — never use useMemo or useCallback
  • Component autonomy — domain components access state directly via hooks, not props. Only pass props to truly reusable/generic components.
  • Colocate state with consumers — each component owns its data dependencies
  • One component per file (small helpers < 10 lines and inline styled components are exceptions)
  • MatchQuery for loading/error/success — never manual if (isLoading) checks
  • Pattern matching over switch/case in JSX — use <Match> component, Record lookups, config arrays

Pattern Matching

Never use switch/case or nested ternaries:

  • Simple value mapping → Record<Key, Value>
  • Functional branching → match(value, { ... })
  • JSX conditional rendering → <Match value={status} loading={() => ...} />
  • Discriminated unions → matchDiscriminatedUnion(action, 'kind', 'payload', { ... })
  • Record unions → matchRecordUnion(shape, { ... })
  • Repetitive conditionals → config arrays with .every() / .filter()

Functions

  • Object parameters for >1 arg with {FunctionName}Input type
  • Never try-catch — use attempt() only for: showing errors to users, executing alternative logic, or providing fallback values
  • Let errors bubble up naturally — don't wrap functions just to log

Git

  • Conventional commits: type(scope): description
  • Types: feat, fix, chore, refactor, docs, test, style, perf
  • Do NOT include Co-Authored-By trailer — user is sole author
  • PRs: conventional title, Summary + Test plan, always draft

Performance

  • Colocate state with consumers to minimize re-render blast radius
  • Config-driven patterns (Record lookups, config arrays) over runtime branching
  • Fail fast with assertions rather than propagating invalid state
  • Prefer derived/computed values over redundant state

Code Quality

  • Run the project's check/lint command after modifying code files
  • ESLint autofix for auto-fixable issues only (import sorting, etc.) — never sort imports manually
  • Check shared utilities before creating local helpers
  • Comments only for: complex business logic, non-obvious algorithmic decisions, temporary workarounds/TODOs

Compact Instructions

When compacting context, preserve: current branch name and task, file paths already modified, error messages being debugged, the specific ticket being implemented.