Files
gridpilot.gg/docs/TECH.md
2025-12-15 13:46:07 +01:00

12 KiB

Technology Stack

This document outlines GridPilot's technology choices and their rationale. For architectural patterns and layer organization, see ARCHITECTURE.md.

1. Language & Runtime

TypeScript (Strict Mode)

  • Version: Latest stable (5.x+)
  • Configuration: strict: true, no any types permitted
  • Rationale: Type safety catches errors at compile time, improves IDE support, and serves as living documentation. Strict mode eliminates common type-related bugs and enforces explicit handling of null/undefined.

Node.js LTS

  • Version: >=20.0.0
  • Rationale: Long-term support ensures stability and security patches. Modern features (fetch API, native test runner) reduce dependency overhead. Version 20+ provides performance improvements critical for real-time race monitoring.

2. Backend Framework

Current Status: Under Evaluation

Three candidates align with Clean Architecture principles:

Option A: Express

  • Pros: Mature ecosystem, extensive middleware, proven at scale
  • Cons: Slower than modern alternatives, callback-heavy patterns
  • Use Case: Best if stability and middleware availability are priorities

Option B: Fastify

  • Pros: High performance, schema-based validation, modern async/await
  • Cons: Smaller ecosystem than Express
  • Use Case: Best for performance-critical endpoints (real-time race data)

Option C: Hono

  • Pros: Ultra-lightweight, edge-ready, excellent TypeScript support
  • Cons: Newest option, smaller community
  • Use Case: Best for modern deployment targets (Cloudflare Workers, edge functions)

Requirements (All Options):

  • HTTP server with middleware support
  • OpenAPI/Swagger compatibility
  • JSON schema validation
  • WebSocket support (for real-time features)

Decision Timeline: Deferred to implementation phase based on deployment target selection.

3. Frontend Framework

Current Status: Under Evaluation

Two candidates meet accessibility and performance requirements:

Option A: React 18+ with Vite

  • Pros: Maximum flexibility, fast HMR, lightweight bundle
  • Cons: Manual SEO optimization, client-side routing complexity
  • Use Case: Best for dashboard-heavy, interactive UI (primary use case)

Option B: Next.js 14+

  • Pros: Built-in SSR/SSG, file-based routing, image optimization
  • Cons: Larger bundle, more opinionated
  • Use Case: Best if public league pages require SEO

Shared Dependencies:

  • State Management:
    • TanStack Query: Server state (caching, optimistic updates, real-time sync)
    • Zustand: Client state (UI preferences, form state)
    • Rationale: Separation of concerns prevents state management spaghetti
  • UI Library:
    • Tailwind CSS: Utility-first styling, design system consistency
    • shadcn/ui: Accessible components (WCAG 2.1 AA), copy-paste philosophy
    • Radix UI primitives: Unstyled, accessible foundations
    • Rationale: Rapid development without sacrificing accessibility or customization
  • Forms: React Hook Form + Zod schemas (type-safe validation)
  • Routing: React Router (Option A) or Next.js file-based routing (Option B)

Decision Timeline: Deferred to implementation phase. Leaning toward Option A (React + Vite) given dashboard-centric use case.

4. Database

PostgreSQL 15+

  • Rationale:
    • Complex relationships (leagues → seasons → races → drivers → teams) require relational integrity
    • JSONB columns handle flexible metadata (iRacing session results, custom league rules)
    • Full-text search for driver/team lookups
    • Battle-tested at scale, excellent TypeScript ORM support
  • Features Used:
    • Foreign keys with cascading deletes
    • Check constraints (business rule validation)
    • Indexes on frequently queried fields (league_id, race_date)
    • Row-level security (multi-tenant data isolation)

ORM: Under Evaluation

Option A: Prisma

  • Pros: Type-safe queries, automatic migrations, excellent DX
  • Cons: Additional build step, limited raw SQL for complex queries
  • Use Case: Best for rapid development, type safety priority

Option B: TypeORM

  • Pros: Decorators, Active Record pattern, SQL flexibility
  • Cons: Older API design, less type-safe than Prisma
  • Use Case: Best if complex SQL queries are frequent

Decision Timeline: Deferred to implementation phase. Both integrate cleanly with Clean Architecture (repository pattern at infrastructure layer).

5. Authentication

iRacing OAuth Flow

  • Provider: iRacing official OAuth 2.0
  • Rationale: Official integration ensures compliance with iRacing Terms of Service. Users trust official credentials over third-party passwords.
  • Flow: Authorization Code with PKCE (Proof Key for Code Exchange)

Session Management

  • JWT: Stateless tokens for API authentication
  • Storage: HTTP-only cookies (XSS protection), encrypted at rest
  • Refresh Strategy: Short-lived access tokens (15 min), long-lived refresh tokens (7 days)

Implementation

  • Passport.js: OAuth strategy handling, pluggable architecture
  • bcrypt: Fallback password hashing (if local accounts added later)
  • Rationale: Passport's strategy pattern aligns with Clean Architecture (adapter layer). Well-tested, extensive documentation.

6. Automation (Companion App)

Electron

  • Version: Latest stable (28.x+)
  • Rationale: Cross-platform desktop framework (Windows, macOS, Linux). Native OS integration (system tray, notifications, auto-start).
  • Security: Isolated renderer processes, context bridge for IPC

Playwright (Browser Automation)

  • Purpose: Automate the iRacing website (members.iracing.com) via DOM manipulation
  • Rationale: Standard browser automation for the iRacing web interface. The iRacing website is a standard HTML/DOM application that can be automated with Playwright. This is 100% legal and the only approach GridPilot uses.
  • Key Features:
    • Cross-browser support (Chromium, Firefox, WebKit)
    • Auto-wait for elements (eliminates flaky tests)
    • Network interception for testing
    • Screenshot/video capture for debugging

Important: iRacing Automation Rules

  • Allowed: Browser automation of members.iracing.com (standard web application)
  • Forbidden: DOM automation inside the iRacing Electron desktop app (TOS violation)
  • Forbidden: Script injection or client modification (like iRefined)

Electron IPC

  • Main ↔ Renderer: Type-safe message passing via preload scripts
  • Rationale: Security (no direct Node.js access in renderer), type safety (Zod schemas for IPC contracts)

Auto-Updates

  • electron-updater: Handles signed updates, delta downloads
  • Rationale: Critical for security patches, seamless user experience

Why This Approach:

  • Assistant-style automation (user-initiated), not gameplay bots
  • Complements web app (handles tasks iRacing API doesn't expose)
  • Desktop integration (notifications for upcoming races, quick access via system tray)
  • Browser automation is reliable and testable

7. Testing Tools

Unit & Integration: Vitest

  • Rationale: Native TypeScript support, fast execution (ESM, watch mode), compatible with Vite ecosystem
  • Coverage: Built-in coverage reports (Istanbul), enforces 80% threshold

E2E: Playwright

  • Rationale: Reliable browser automation, cross-browser testing (Chromium, Firefox, WebKit), built-in wait strategies
  • Features: Screenshot/video on failure, network mocking, parallel execution

Test Containers (Docker)

  • Purpose: Isolated test databases, Redis instances
  • Rationale: Prevents test pollution, matches production environment, automatic cleanup
  • Services: PostgreSQL, Redis, S3 (MinIO)

Testing Strategy:

  • Unit tests: Core domain logic (pure functions, business rules)
  • Integration tests: Repository implementations, API endpoints
  • E2E tests: Critical user flows (create league, register for race, view results)

8. DevOps & Infrastructure

Docker & Docker Compose

  • Purpose: Local development, E2E testing, consistent environments
  • Services:
    • PostgreSQL (primary database)
    • Redis (caching, rate limiting, job queue)
    • MinIO (S3-compatible storage for local dev)
  • Rationale: Developers get production-like environment instantly

Redis

  • Use Cases:
    • Caching (league standings, frequently accessed driver stats)
    • Rate limiting (API throttling, abuse prevention)
    • Bull queue (background jobs: race result processing, email notifications)
  • Rationale: Proven performance, simple key-value model, pub/sub for real-time features

Object Storage

  • Production: AWS S3 (logos, exported reports)
  • Development: MinIO (S3-compatible, Docker-based)
  • Rationale: Cost-effective, scalable, CDN integration

Bull Queue (Redis-backed)

  • Jobs: Process race results, send notifications, generate reports
  • Rationale: Offloads heavy tasks from HTTP requests, retry logic, job prioritization

CI/CD: Placeholder

  • Options: GitHub Actions, GitLab CI
  • Rationale: TBD based on hosting choice (GitHub vs. self-hosted GitLab)

9. Monorepo Tooling

npm Workspaces

  • Rationale: Built-in, zero configuration, dependency hoisting
  • Structure: /src/apps/*, /src/core/*, /tests/*

Build Orchestration: Under Evaluation

Option A: Turborepo

  • Pros: Fast incremental builds, remote caching, simple config
  • Cons: Vercel-owned (vendor lock-in risk)

Option B: Nx

  • Pros: Advanced dependency graph, affected commands, plugins
  • Cons: Steeper learning curve, more complex config

Decision Timeline: Start with npm workspaces alone. Evaluate Turborepo/Nx if build times become bottleneck (unlikely at current scale).

10. Development Tools

Code Quality

  • ESLint: Enforce coding standards, catch common mistakes
  • Prettier: Consistent formatting (no debates on tabs vs. spaces)
  • Rationale: Automated code reviews reduce friction, onboarding time

Pre-Commit Hooks

  • Husky: Git hook management
  • lint-staged: Run linters only on changed files
  • Rationale: Fast feedback loop, prevents broken commits reaching CI

TypeScript Configuration

  • Strict Mode: All strict flags enabled
  • No Implicit Any: Forces explicit types
  • Rationale: Type safety as first-class citizen, not opt-in feature

Runtime Validation

  • Zod: Schema definition, runtime validation, type inference
  • Use Cases:
    • API request/response validation
    • Environment variable parsing
    • Form validation (shared between frontend/backend)
  • Rationale: Single source of truth for data shapes, generates TypeScript types automatically

Decision Status Summary

Finalized:

  • Language: TypeScript (strict mode)
  • Runtime: Node.js 20+
  • Database: PostgreSQL 15+
  • Auth: iRacing OAuth + JWT
  • Companion: Electron + Playwright (browser automation only)
  • Testing: Vitest + Playwright + Test Containers
  • Infra: Docker + Redis + S3/MinIO
  • Monorepo: npm workspaces
  • Dev Tools: ESLint + Prettier + Husky + Zod

Under Evaluation (Deferred to Implementation):

  • Backend framework: Express vs. Fastify vs. Hono
  • Frontend framework: React + Vite vs. Next.js
  • ORM: Prisma vs. TypeORM
  • Build orchestration: Turborepo vs. Nx (if needed)
  • CI/CD: GitHub Actions vs. GitLab CI

Deferred Decisions Rationale:

  • Backend/frontend frameworks: Choice depends on deployment target (cloud vs. edge vs. self-hosted)
  • ORM: Both options integrate cleanly with Clean Architecture; decision based on team preference during implementation
  • Build tools: Optimize when proven bottleneck (YAGNI principle)

Cross-References

  • Architecture Patterns: See ARCHITECTURE.md for how these technologies map to Clean Architecture layers
  • Project Overview: See CONCEPT.md for business context driving technology choices
  • Setup Instructions: See README.md for installation and getting started

Last Updated: 2025-11-23