High-performance GPS route analysis and 3D visualization tool. Process large GPX files with interactive elevation profiles and real-time section analytics. Supports live location sharing between runners and followers via WebSocket relay.
Web App: React + Vite frontend with React Three Fiber for 3D visualization Web Workers: Background GPS processing to maintain responsive UI Zig WASM: High-performance route calculations with optimized algorithms
- Interactive 3D Elevation Profiles: Geographic positioning with real-time camera controls
- Multiple Visualization Modes:
- Section-based coloring for route segments
- Slope gradient coloring (5 difficulty levels)
- Section Analytics: Distance, elevation gain/loss, slope percentages, difficulty rating
- Stage Analytics: Per-stage details including distance, elevation, estimated/max time, cutoff time, difficulty, and slowest required pace
- Pace Profile: Smooth chart of the slowest allowed pace (km/h) over distance, with tightest-cutoff and current-section stats
- Live Trail Progression: Real-time progress bar with cumulative distance percentage, elevation gain and loss based on runner position
- ETA Estimation: Arrival time prediction per section based on difficulty
- Peak Detection: Automatic identification and visualization of peaks
- Climb Pro: Automatic climb segment detection (AMPD valley detection + Garmin climb qualification) with a carousel card showing distance, elevation gain, and gradient per climb
- Checkpoint Markers: Location labels along the route with distance-based visibility
- Off-Course Detection: Automatic detection with visual scene alert and 3D label
- Runner / Follower Modes: First-run wizard for role selection — runners broadcast their position, followers track it on the 3D trail
- Live GPS Tracking: Real-time position updates on the 3D trail
- Live Location Sharing: Broadcast your position to followers in real time
- Dark/Light Theme: Toggle between dark and light modes
- Frontend: React 19, Vite, Zustand (state management with DevTools/persist)
- 3D Graphics: React Three Fiber, Three.js, Drei helpers
- Performance: Zig 0.15.2 → WASM via Zigar bindings with zero-copy optimization
- Real-time: PartyKit WebSocket relay for live location sharing
- Styling: Styled-components with glass morphism theme
- Node.js: v18+ (recommended v20+)
- Zig: v0.15.2 for WASM compilation
- npm: Latest version
Install Zig from ziglang.org
npm install
npm run devThe app will be available at http://localhost:5173 (or next available port)
To test live GPS tracking features without a physical device, use the included script to simulate movement along the VVX XGTV 2026 route in the iOS Simulator:
node scripts/simulate-location.js # default: 2m/s, 70 points, update every 100m
node scripts/simulate-location.js 5 # 5m/s walking/running pace
node scripts/simulate-location.js 5 100 50 # 5m/s, 100 waypoints, update every 50mThe script samples evenly-spaced points from the GPX track and feeds them to the iOS Simulator via xcrun simctl. Make sure a Simulator is booted before running. Press Ctrl+C to stop the simulation, or clear it with:
xcrun simctl location booted clearTo replay a GPX route as live position updates broadcast to a PartyKit room (useful for testing the follower view without a physical runner):
# Usage
node scripts/simulate-partykit.js <gpx-file> <room-id> <race-id> [speed_m_per_s] [update_every_m]
# Examples
node scripts/simulate-partykit.js public/vvx-xgtv-2026.gpx ABC123 vvx-xgtv-2026 # 2 m/s, update every 100 m
node scripts/simulate-partykit.js public/vvx-xgtv-2026.gpx ABC123 vvx-xgtv-2026 500 500 # 500 m/s, 1 update/sec (fast replay)By default the script targets localhost:1999. Set PARTYKIT_HOST to target a deployed instance:
PARTYKIT_HOST=<your-partykit-host> node scripts/simulate-partykit.js public/vvx-xgtv-2026.gpx ABC123 vvx-xgtv-2026Open the app as a follower and join room ABC123 to watch the position move in real time.
This project uses structured CLAUDE.md instruction files for Claude Code:
CLAUDE.md: Global project guidance, architecture, and commandssrc/CLAUDE.md: Frontend conventions and patternszig/CLAUDE.md: Zig/WASM conventions and memory model
Claude Code automatically applies the right context based on file type.
Vite automatically compiles Zig to WASM during the build process. No manual compilation needed.
npm run buildRun JavaScript/React tests:
npm test # Run Vitest tests (watch mode)Run Zig unit tests:
npm run test:zig # All Zig tests
npm run test:all # Run both Zig and JavaScript testssrc/
components/ # React components for UI and 3D visualization
store/
slices/ # Zustand state management slices
helpers/ # Utility functions (colors, buffers, throttling)
utils/ # Coordinate transformations
gpxWorker.js # Web Worker for background GPS processing
party/
server.js # PartyKit WebSocket relay server for live location sharing
zig/
gpx.zig # GPX file parsing
gpxdata.zig # GPX data structures
trace.zig # Core GPS algorithms (distance, elevation)
simplify.zig # Douglas-Peucker simplification
peaks.zig # Peak detection algorithms
climbs.zig # Climb segment detection (AMPD + Garmin qualification)
gpspoint.zig # Haversine distance calculations
time.zig # Time/duration calculations
waypoint.zig # Waypoint data structure
section.zig # Section statistics structure
leg.zig # Leg data structure (stage sub-segments)
stage.zig # Stage data structure and analytics
main.zig # WASM entry point and bindings
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes and test thoroughly
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request