Skip to content

Instantly share code, notes, and snippets.

@vigosan
Created September 5, 2025 11:41
Show Gist options
  • Save vigosan/5e1ed4bafb2b1475e63f3f933081e3a8 to your computer and use it in GitHub Desktop.
Save vigosan/5e1ed4bafb2b1475e63f3f933081e3a8 to your computer and use it in GitHub Desktop.
CLAUDE.md

Development Guidelines

Philosophy

Core Beliefs

  • Incremental progress over big bangs - Small changes that compile and pass tests
  • Learning from existing code - Study and plan before implementing
  • Pragmatic over dogmatic - Adapt to project reality
  • Clear intent over clever code - Be boring and obvious

Simplicity Means

  • Single responsibility per function/class
  • Avoid premature abstractions
  • No clever tricks - choose the boring solution
  • If you need to explain it, it's too complex

Process

1. Tracer Bullets - Incremental Development

Always start with "tracer bullets" - minimal, end-to-end implementations that prove the core concept works:

  • Build the thinnest possible vertical slice that demonstrates the main functionality
  • Deploy and test early - Get feedback on the core concept before adding features
  • Iterate in small, working increments - Each commit should add one small, complete piece
  • Avoid big rewrites - Refactor continuously in tiny steps

2. Planning & Staging

Break complex work into 3-5 stages. Document in IMPLEMENTATION_PLAN.md using checkbox format:

## Stage N: [Name]
**Goal**: [Specific deliverable]
**Status**: [ ] Not Started | [X] Complete

### Tasks
- [X] Completed task
- [ ] Pending task
- [ ] Another pending task

IMPORTANT: Always check IMPLEMENTATION_PLAN.md before starting work:

  • Follow the checkbox tasks in order
  • Mark tasks as [X] when completed
  • Use /reset between stages to save tokens
  • Update status and current focus section

3. Implementation Flow

  1. Understand - Study existing patterns in codebase
  2. Test - Write test first (red)
  3. Implement - Minimal code to pass (green)
  4. Refactor - Clean up with tests passing
  5. Commit - With clear message linking to plan

4. When Stuck (After 3 Attempts)

CRITICAL: Maximum 3 attempts per issue, then STOP.

  1. Document what failed:

    • What you tried
    • Specific error messages
    • Why you think it failed
  2. Research alternatives:

    • Find 2-3 similar implementations
    • Note different approaches used
  3. Question fundamentals:

    • Is this the right abstraction level?
    • Can this be split into smaller problems?
    • Is there a simpler approach entirely?
  4. Try different angle:

    • Different library/framework feature?
    • Different architectural pattern?
    • Remove abstraction instead of adding?

Technical Standards

Architecture Principles

  • Composition over inheritance - Use dependency injection
  • Interfaces over singletons - Enable testing and flexibility
  • Explicit over implicit - Clear data flow and dependencies
  • Test-driven when possible - Never disable tests, fix them

Code Quality

  • Every commit must:

    • Compile successfully
    • Pass all existing tests
    • Include tests for new functionality
    • Follow project formatting/linting
  • Before committing:

    • Run formatters/linters
    • Self-review changes
    • Use descriptive commit titles only (no body/description)

Error Handling

  • Fail fast with descriptive messages
  • Include context for debugging
  • Handle errors at appropriate level
  • Never silently swallow exceptions

Decision Framework

When multiple valid approaches exist, choose based on:

  1. Testability - Can I easily test this?
  2. Readability - Will someone understand this in 6 months?
  3. Consistency - Does this match project patterns?
  4. Simplicity - Is this the simplest solution that works?
  5. Reversibility - How hard to change later?

Project Integration

Learning the Codebase

  • Find 3 similar features/components
  • Identify common patterns and conventions
  • Use same libraries/utilities when possible
  • Follow existing test patterns

Tooling

  • Use project's existing build system
  • Use project's test framework
  • Use project's formatter/linter settings
  • Don't introduce new tools without strong justification

Quality Gates

Definition of Done

  • Tests written and passing
  • Code follows project conventions
  • No linter/formatter warnings
  • Commit messages are clear
  • Implementation matches plan
  • No TODOs without issue numbers
  • Code is self-documenting with ZERO comments or explanations

Test Guidelines

  • Test behavior, not implementation
  • One assertion per test when possible
  • Clear test names describing scenario
  • Use existing test utilities/helpers
  • Tests should be deterministic
  • Element Selection: Always use data-testid attributes, never CSS classes
  • Selector Priority: data-testid > semantic selectors > text content > CSS classes (avoid)

Important Reminders

NEVER:

  • Use --no-verify to bypass commit hooks
  • Disable tests instead of fixing them
  • Commit code that doesn't compile
  • Make assumptions - verify with existing code
  • Add comments or explanations in code - code must be self-documenting
  • Use CSS classes for element selection - always prefer data-testid attributes

ALWAYS:

  • Commit working code incrementally
  • Update plan documentation as you go
  • Learn from existing implementations
  • Stop after 3 failed attempts and reassess

Node.js 2025 Patterns

Core Principles

  • Use ES Modules (ESM) as primary module system
  • Use node: prefix for built-in modules to prevent conflicts
  • Leverage top-level await for cleaner module initialization
  • Embrace async/await with comprehensive error handling
  • Use Promise.all() for parallel asynchronous operations

Performance & Concurrency

  • Use Worker Threads for CPU-intensive background processing
  • Implement performance monitoring with built-in performance hooks
  • Utilize Web Streams for interoperable stream processing

Error Handling & Security

  • Create structured, contextual error classes
  • Include rich error metadata (timestamp, context, status codes)
  • Leverage Node.js permission model to restrict application access
  • Use built-in APIs instead of external dependencies when possible

Development Workflow

  • Use --watch mode for automatic reloading
  • Utilize --env-file for environment management
  • Use built-in Node.js test runner
  • Implement dynamic module imports for conditional feature loading

React 2025 Patterns

Optimistic UI with useOptimistic

  • Assume success - Update UI immediately, let server catch up
  • Combine with startTransition for smooth state updates
  • Keep update functions pure - No side effects in optimistic updaters
  • Use sparingly - Only for high-confidence actions
  • Visual feedback - Gray out or mark optimistic items
  • Handle failures - Provide fallback mechanisms

Dependency Inversion & Testing

  • High-level modules should not depend on low-level modules - Both should depend on abstractions
  • Decouple data fetching from rendering - Separate concerns between retrieval and presentation
  • Design for testability - Components should work without direct dependencies
  • Create clear interfaces - Define contracts for all external dependencies
  • Inject through props or context - Avoid direct imports of concrete implementations
  • Keep interfaces minimal - Single responsibility for each abstraction

Repository Pattern

Core Benefits

  • Independent Development - No waiting for backend services
  • Rapid Iterations - Instant responses without network latency
  • Scenario Simulation - Test error states and edge cases easily
  • Predictable Testing - Consistent, repeatable test environments

Interface-First Design

  • Define contracts first - Clear interfaces before implementation
  • Consistent methods - Same signatures across implementations
  • Mock parity - Mock behavior matches real API
  • Type safety - Full TypeScript coverage

Component Patterns

  • Container/Presenter - Separate data logic from UI rendering
  • Dependency Injection - Inject repositories via props or context
  • Environment switching - Easy toggle between mock and real APIs

Testing Strategy

  • Unit tests with mocks - Test component behavior with predictable data
  • Integration tests - Verify real API compatibility
  • Error scenarios - Test network failures and edge cases
  • Performance testing - Simulate slow responses and timeouts

Repository Guidelines

  • Interface first - Define clear contracts before implementation
  • Consistent methods - Same signatures across implementations
  • Error handling - Mock should throw similar errors as real API
  • Type safety - Full TypeScript coverage
  • Single responsibility - One repository per domain/entity

Single Responsibility Principle

  • One reason to change - Each component should have exactly one responsibility
  • Separate concerns - Break down complex components into focused units
  • Composition over complexity - Build features from simple, reusable parts
  • Extract custom hooks - Move data logic to hooks
  • Pure presentation - Components that only render UI
  • Container pattern - Components that orchestrate but don't render much

SRP Violation Signals

  • "And" in description - Component does multiple things
  • Multiple reasons to change - UI, API, and business logic changes all affect same component
  • Large prop interfaces - Components accepting too many unrelated props
  • Mixed concerns - Data fetching, state management, and rendering together

Component Composition Patterns

Compound Components

  • Multiple components work together - Share state through context
  • Flexible API surface - Consumers arrange components as needed
  • Clear relationships - Explicit parent-child relationships

Context-Based Composition

  • Granular contexts - Break complex state into focused contexts
  • Custom hooks for access - Provide convenient hooks for each context
  • Separation of concerns - Each context handles specific domain

Render Props

  • Inversion of control - Component exposes data/behavior to consumers
  • Maximum flexibility - Consumers control rendering completely

Component Injection

  • Polymorphic components - Accept different component types through props
  • Flexible rendering - Same logic with different presentations
  • Customizable primitives - Override default components

Layered Architecture

  • Base layer - Design tokens, constants, utilities
  • Primitive layer - Low-level, unstyled components
  • Shared library - Styled, reusable components
  • Product-specific - Domain-specific adaptations
  • Specialized - Complex, feature-specific components

Composition Guidelines

  • Single Responsibility - Each component handles one clear concern
  • Inversion of Control - Empower consumers to extend and customize
  • Context for coordination - Share state between related components
  • Hooks for reusability - Extract common logic into custom hooks
  • Flexible APIs - Provide sensible defaults with customization options

Preferred Frontend Stack

Testing Stack

  • Test Runner: Vitest (not Jest) - Modern, fast, native TypeScript support
  • Testing Library: React Testing Library + @testing-library/jest-dom
  • User Interactions: @testing-library/user-event for realistic user simulation
  • Test Utilities: Custom renderWithProviders() wrapper with QueryClient and context
  • Mocking Strategy: Vitest's vi.mock() for module and hook mocking

Styling Approach

  • CSS Framework: Tailwind CSS v4+ (not plain CSS)
  • Plugin: @tailwindcss/vite for modern Vite integration
  • Utility Composition: tailwind-merge for class conflict resolution
  • Design System: Consistent design tokens via Tailwind configuration

Data Fetching Stack

  • HTTP Client: TanStack Query v5 (not raw fetch)
  • Query Management: Custom hooks wrapping useQuery/useMutation
  • Cache Strategy: Strategic invalidation and background refetching
  • Error Handling: Consistent error boundaries and toast notifications

Service Layer Architecture

  • API Client: Class-based HTTP client with methods
  • Authentication: Automatic bearer token injection
  • Error Handling: Custom ApiError class with status codes
  • Type Safety: Full TypeScript coverage for all API interactions

Context and State Management

  • Domain-Specific Contexts: Separate contexts for Auth, Toast, etc.
  • Custom Hooks: Each context exports a typed hook for access
  • Error Boundaries: Proper error handling for context usage
  • Provider Composition: Layered provider architecture

Architecture Organization

src/
├── components/     # Reusable UI components
├── contexts/       # React context providers  
├── hooks/          # Custom hooks (data fetching, logic)
├── services/       # API clients and external services
├── types/          # TypeScript type definitions
├── utils/          # Pure utility functions
├── pages/          # Page-level components
├── test/           # Test utilities and setup
└── locales/        # i18n translation files

Integration Patterns

  • Provider Composition: Layered providers (QueryClient → Auth → Toast → Router)
  • Type Safety: Comprehensive TypeScript throughout the stack
  • Modern React: React 19 with concurrent features and modern patterns
  • Performance: Bundle optimization, lazy loading, and efficient re-renders
  • Accessibility: Semantic HTML, ARIA attributes, keyboard navigation

Docker Requirements

Service Containerization

MANDATORY: All services (frontend, backend, database, etc.) MUST have their own Dockerfile.

  • Individual Dockerfiles - Each service maintains its own optimized Dockerfile
  • Multi-stage builds - Use multi-stage builds for production optimization
  • Security practices - Non-root users, minimal base images, vulnerability scanning
  • Environment configuration - All environment variables configurable via Docker

Orchestration & Build Integration

  • docker-compose.yml - Complete stack orchestration
  • Development environment - Local development with hot reload
  • Makefile integration - make dev, make build, make deploy use Docker
  • Testing in containers - All tests run in containerized environment
  • CI/CD ready - Docker images built and tagged for deployment

Container Best Practices

  • Layered caching - Optimize layer order for build speed
  • Health checks - All services include health check endpoints
  • Graceful shutdown - Proper signal handling for clean shutdowns
  • Resource limits - CPU and memory limits defined
  • Security scanning - Container images scanned for vulnerabilities
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment