Raccoon Rocket Lab Architecture¶
This document describes the technical architecture of the Raccoon Rocket Lab sandbox application, a full-stack TypeScript project demonstrating modern development patterns with comprehensive testing and analysis tooling.
Overview¶
Raccoon Rocket Lab is a rocket flight simulator where users design rockets, launch them, and compete for high scores on a leaderboard. The application showcases patterns suitable for agentic software engineering workflows.
flowchart TB
subgraph Client["Client (React 19)"]
UI[UI Components]
Hooks[Custom Hooks]
Query[TanStack Query]
Physics[Physics Simulation]
end
subgraph Server["Server (Hono)"]
Routes[API Routes]
Store[Store Layer]
Validation[Zod Validation]
end
subgraph Database["SQLite"]
Rockets[(rockets)]
Flights[(flights)]
end
subgraph Shared["Shared Package"]
Types[TypeScript Types]
Schemas[Zod Schemas]
end
Client -->|HTTP /api/*| Server
Server --> Database
Client --> Shared
Server --> Shared
Technology Stack¶
| Layer | Technology | Version | Purpose |
|---|---|---|---|
| Runtime | Bun | 1.3.7 | Package manager, runtime, bundler |
| Frontend | React | 19.2.4 | UI framework |
| Build Tool | Vite | 7.3.1 | Dev server, production bundler |
| Data Fetching | TanStack Query | 5.90.20 | Server state management |
| Backend | Hono | 4.11.7 | Web framework |
| Validation | Zod | 4.3.6 | Schema validation |
| Database | SQLite | Native | Persistent storage |
| Unit Testing | Vitest | 4.0.18 | Test runner |
| E2E Testing | Playwright | 1.58.0 | Browser automation |
| Mutation Testing | Stryker | 9.4.0 | Test quality analysis |
| Linting | Biome | 2.3.13 | Formatting and linting |
| Dead Code | Knip | 5.82.1 | Unused code detection |
| Orchestration | Turborepo | 2.7.6 | Monorepo task runner |
Additional Runtime Dependencies¶
| Package | Version | Purpose |
|---|---|---|
| @hono/zod-validator | ^0.7.6 | Hono middleware for Zod schema validation |
| @tanstack/react-query-devtools | ^5.91.2 | Query debugging and inspection tools |
| @testing-library/react | - | React component testing utilities |
| @testing-library/dom | - | DOM testing utilities |
Monorepo Structure¶
The project uses Turborepo with Bun workspaces for monorepo management.
flowchart TB
subgraph Root["raccoon-rocket-lab/"]
pkg[package.json]
turbo[turbo.json]
tsconfig[tsconfig.base.json]
end
subgraph Apps["apps/"]
client["client/"]
server["server/"]
end
subgraph Packages["packages/"]
shared["shared/"]
end
Root --> Apps
Root --> Packages
client -->|workspace:*| shared
server -->|workspace:*| shared
Directory Layout¶
sandbox/raccoon-rocket-lab/
├── apps/
│ ├── client/ # React frontend
│ │ ├── src/
│ │ │ ├── components/ # UI components
│ │ │ ├── hooks/ # State management
│ │ │ ├── lib/ # Utilities
│ │ │ ├── queries/ # TanStack Query configs
│ │ │ └── styles/ # CSS and styling
│ │ └── tests/
│ │ ├── e2e/ # End-to-end tests
│ │ ├── unit/ # Unit tests
│ │ └── infrastructure/ # Client infrastructure tests
│ └── server/ # Hono backend
│ └── src/
│ └── routes/ # API endpoints
├── packages/
│ └── shared/ # Shared types and schemas
├── specs/ # Requirements and feature specifications
│ ├── requirements/ # Project requirements
│ └── features/ # Feature specifications
├── tests/ # Root-level infrastructure tests
│ └── infrastructure/
│ ├── biome/ # Linting infrastructure tests
│ ├── deadcode/ # Dead code analysis tests
│ └── integration/ # Cross-package integration tests
├── turbo.json # Build pipeline config
├── biome.json # Linting config
├── knip.json # Dead code config
└── Makefile # Development commands
Client Architecture¶
Component Hierarchy¶
The application has three main component groups:
flowchart TD
App["App.tsx"]
App --> RD["RocketDesigner"]
App --> MC["MissionControl"]
App --> LB["Leaderboard"]
RD --> RP["RocketPreview"]
RD --> SI["StabilityIndicator"]
MC --> FV["FlightView"]
MC --> SB["Scoreboard"]
Design Phase Components:
| Component | Purpose |
|---|---|
| RocketDesigner | Main design interface with parameter controls |
| RocketPreview | Visual rocket rendering |
| StabilityIndicator | Shows stability rating |
| ParameterSlider | Adjusts numeric values |
| ToggleButton | Selects nose cone type |
Flight Phase Components:
| Component | Purpose |
|---|---|
| MissionControl | Flight observation container |
| ObservationWindow | Viewport for flight animation |
| RaccoonCharacter | Animated mascot |
| LaunchPad | Countdown display |
| FlightView | Flight trajectory visualization |
| Scoreboard | Final score display |
Unified View Pattern:
The UnifiedRocketView.tsx component consolidates both design and mission views into a single component, managing the transition between rocket design and flight observation phases. This pattern reduces code duplication and provides a consistent user experience across application states.
State Management¶
The client uses a combination of local React state and TanStack Query:
- Local State - Rocket design parameters, flight simulation state
- Server State - Leaderboard data via TanStack Query
Custom hooks encapsulate state logic:
| Hook | Purpose |
|---|---|
useRocketDesign |
Manages rocket parameter state |
useFlight |
Controls flight simulation lifecycle |
Key Libraries¶
src/lib/
├── api.ts # Fetch-based API client
├── queryClient.ts # TanStack Query configuration
├── physics.ts # Flight physics simulation
├── trajectory.ts # Animation frame interpolation
├── stability.ts # Stability calculations
└── scoring.ts # Score computation
Server Architecture¶
API Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/health |
Server health check |
| POST | /api/rockets |
Create rocket design |
| GET | /api/rockets/:id |
Get specific rocket |
| GET | /api/rockets |
List recent rockets |
| POST | /api/flights |
Record flight result |
| GET | /api/flights |
List recent flights |
| GET | /api/leaderboard |
Get top scores |
Database Schema¶
erDiagram
rockets {
text id PK "UUID"
text name "nullable"
real finSize
integer finCount
real fuelAmount
text noseCone "pointed|rounded|blunt"
real bodyDiameter
real parachuteSize
text createdAt "ISO timestamp"
text updatedAt "ISO timestamp"
}
flights {
text id PK "UUID"
text rocketId FK
text launchDate "ISO timestamp"
real maxAltitude
real maxVelocity
real flightDuration
text phases "JSON array"
integer success "0|1"
text notes "nullable"
real score "nullable"
}
rockets ||--o{ flights : "has"
Store Layer¶
The store layer (src/store.ts) provides data access functions:
- Pure functions for CRUD operations
- SQLite prepared statements with parameter binding
- Date serialization as ISO strings
- JSON serialization for nested data (flight phases)
Shared Package¶
The shared package (packages/shared/) defines the contract between client and server.
Types¶
type NoseCone = "pointed" | "rounded" | "blunt"
type FlightPhase =
| "pre-launch" | "ignition" | "powered-ascent"
| "coast" | "apogee" | "descent" | "recovery"
interface RocketDesignInput {
name?: string
finSize: number
finCount: number
fuelAmount: number
noseCone: NoseCone
bodyDiameter: number
parachuteSize: number
}
interface RocketDesign extends RocketDesignInput {
id: string
createdAt: string
updatedAt: string
}
interface FlightResult {
id: string
rocketId: string
launchDate: string
maxAltitude: number
maxVelocity: number
flightDuration: number
phases: FlightPhaseEvent[]
success: boolean
notes?: string
score?: number
}
Zod Schemas¶
Zod schemas mirror the types for runtime validation on both client and server.
Data Flow¶
The client communicates with the server through a Vite proxy that forwards /api/* requests.
flowchart LR
subgraph Browser
Client["React App"]
end
subgraph Backend
Server["Hono API"]
DB[("SQLite")]
end
Client -->|"POST /api/rockets"| Server
Client -->|"POST /api/flights"| Server
Client -->|"GET /api/leaderboard"| Server
Server <--> DB
Request Flow¶
- Design Phase - User adjusts rocket parameters, client calculates stability locally
- Launch Phase - Client runs physics simulation locally, generates flight data
- Save Rocket -
POST /api/rocketswith design parameters, server validates with Zod - Save Flight -
POST /api/flightswith simulation results - Leaderboard -
GET /api/leaderboardfetches top scores via TanStack Query
Vite Proxy Configuration¶
The client proxies API requests to the backend. Environment variables provide flexibility for distributed deployments:
// vite.config.ts
export default defineConfig({
server: {
host: process.env.HOST || '0.0.0.0',
port: parseInt(process.env.PORT || '35806'),
proxy: {
'/api': {
target: process.env.VITE_API_PROXY_TARGET || 'http://localhost:35800',
changeOrigin: true
}
}
}
})
| Environment Variable | Default | Purpose |
|---|---|---|
HOST |
0.0.0.0 |
Dev server bind address |
PORT |
35806 |
Dev server port |
VITE_API_PROXY_TARGET |
http://localhost:35800 |
Backend API URL for proxy |
PLAYWRIGHT_BASE_URL |
http://127.0.0.1:35806 |
E2E test target URL |
Flight Simulation¶
State Machine¶
stateDiagram-v2
[*] --> PreLaunch: Initialize
PreLaunch --> Ignition: Start countdown
Ignition --> PoweredAscent: Engine ignites
PoweredAscent --> Coast: Fuel depleted
Coast --> Apogee: Velocity = 0
Apogee --> Descent: Gravity takes over
Descent --> Recovery: Parachute deploys
Recovery --> [*]: Landing
note right of PoweredAscent: Thrust follows bell curve
note right of Descent: Drag based on nose cone
Physics Engine¶
The physics simulation (src/lib/physics.ts) models:
| Parameter | Formula/Value |
|---|---|
| Gravity | 9.81 m/s^2 |
| Time step | 0.1 seconds |
| Thrust curve | Bell-shaped (sine wave) |
| Drag coefficient | Pointed: 0.3, Rounded: 0.5, Blunt: 0.8 |
Stability Calculation¶
| Range | Rating |
|---|---|
| < 1.0 | Unstable |
| 1.0 - 2.0 | Stable |
| > 2.0 | Overstable |
Scoring System¶
| Category | Points | Criteria |
|---|---|---|
| Altitude | 0-50 | Normalized to 2000m reference |
| Stability | 0-25 | Stable: 25, Overstable: 15, Unstable: 0 |
| Landing | 0-25 | Penalty for high landing speed |
| Total | 0-100 |
Testing Infrastructure¶
Unit Tests (Vitest)¶
Configuration in vitest.config.ts:
- Environment: jsdom
- Test patterns:
src/**/*.{test,spec}.ts(x),tests/**/*.{test,spec}.ts(x) - Global assertions enabled
- Setup file:
tests/setup.ts - Infrastructure tests included from
tests/infrastructure/
Infrastructure Tests¶
Root-level infrastructure tests validate tooling and cross-package integration:
| Category | Location | Purpose |
|---|---|---|
| Biome | tests/infrastructure/biome/ |
Linting configuration validation |
| Dead Code | tests/infrastructure/deadcode/ |
Knip configuration validation |
| Integration | tests/infrastructure/integration/ |
Cross-package dependency checks |
E2E Tests (Playwright)¶
Configuration in playwright.config.ts:
- Browser: Chromium
- Test directory:
tests/e2e - Base URL:
http://127.0.0.1:35806(configurable viaPLAYWRIGHT_BASE_URL) - Automatic dev server startup (CI-aware with
reuseExistingServer) - Trace retention on test failure for debugging
Mutation Testing (Stryker)¶
Configuration in stryker.config.mjs:
- Mutates:
src/lib/*.ts,src/hooks/useFlight.ts - Test runner: Vitest
- Thresholds: High 80%, Low 60%, Break 64%
Reports generated at reports/mutation/mutation.html.
Static Analysis¶
Biome¶
Configuration in biome.json:
| Setting | Value |
|---|---|
| Indent | 2 spaces |
| Line width | 100 characters |
| Quotes | Double |
| Semicolons | Always |
| Trailing commas | Yes |
Knip¶
Configuration in knip.json:
Detects unused:
- Imports and exports
- Dependencies
- Files
Build System¶
Turborepo Pipeline¶
flowchart LR
subgraph Build["build"]
SB[shared:build]
CB[client:build]
SVB[server:build]
end
subgraph Test["test"]
CT[client:test]
SVT[server:test]
end
subgraph Lint["lint"]
L[All workspaces]
end
SB --> CB
SB --> SVB
SB --> CT
SB --> SVT
SB --> L
Task definitions in turbo.json:
| Task | Dependencies | Cache |
|---|---|---|
| build | ^build | Yes |
| dev | - | No (persistent) |
| test | ^build | Yes |
| lint | ^build | Yes |
| test:mutation | ^build | Yes |
| deadcode | - | Yes |
Outputs¶
Build artifacts:
dist/**- Compiled JavaScript- TypeScript declarations (
.d.ts) - Source maps
Docker Configuration¶
Development Containers¶
| Service | Port | Image |
|---|---|---|
| client | 35806 | oven/bun:1.3 |
| server | 35800 | oven/bun:1.3 |
| playwright | - | mcr.microsoft.com/playwright |
Health Checks¶
Services include health check configurations for orchestration reliability:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:35800/api/health"]
interval: 5s
timeout: 3s
retries: 5
Test Environment¶
The docker-compose.test.yml orchestrates E2E testing:
- Server starts and exposes health endpoint
- Client waits for server health check (using
depends_onwith condition) - Playwright container runs tests against client
Development Commands¶
From Repository Root¶
| Command | Description |
|---|---|
make web |
Start client and server |
make web-down |
Stop servers |
make web-status |
Check if running |
make test |
Run all tests |
make mutation |
Run Stryker |
make deadcode |
Run Knip |
From sandbox/raccoon-rocket-lab/¶
| Command | Description |
|---|---|
bun run dev |
Start dev servers |
bun run build |
Build all packages |
bun run test |
Run Vitest |
bun run lint |
Run Biome |
bun run test:e2e |
Run Playwright |