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, noanytypes 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/packages/*,/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