Architecture & Infrastructure — Client vs. Server, Desktop Packaging & Pre-Calculated Data

# Architecture & Infrastructure — Client vs. Server, Desktop Packaging & Pre-Calculated Data

> **Parent note:** [Sim Racing Telemetry Analysis Platform — Project Plan](joplin://6c0dcb2a567348fd9796f50c790082e4)
> **Date:** 2026-06-06
> **Context:** Where should number crunching happen? Standalone app or web site? What pre-calculated data can we sell? How do we package for distribution?

---

## 1. The Core Architecture Constraint

Telemetry data MUST be captured locally. A browser cannot:
- Listen on UDP ports (browser security model)
- Bind to `0.0.0.0:9996` or `0.0.0.1:10101`
- Write files to the local filesystem at 60 Hz
- Access shared memory or memory-mapped files
- Run with deterministic sub-millisecond latency

**There is no way around a local component.** Every sim racing telemetry product has one:
- Track Titan: local capture agent → cloud analysis
- MoTeC i2: desktop app → local files
- SimRacingSetup: F1 sends UDP to their server (only works because F1 supports remote targets)
- SimulatorController: local Java app → local files

So the question is never "app or website?" — it's always "what runs locally, what runs in the cloud, and what does the UI look like?"

---

## 2. Three Architecture Options

### Option A: Local Backend + Browser UI (Current)

```
┌─────────────────────────────┐
│  LOCAL (sim PC)              │
│                               │
│  rusty-telemetry (Rust CLI)   │
│  - UDP listener               │
│  - Binary parsers             │
│  - Recording manager          │
│  - Analysis engine            │
│  - REST API on localhost:8080 │
│                               │
│  Browser tab (racecraft)      │
│  - Vue 3 SPA on :8080         │
│  - Charts, track maps, UI     │
└─────────────────────────────┘
```

| Pro | Con |
|---|---|
| Simplest to build and debug | User must start CLI manually (feels "hacky") |
| Cross-platform UI via browser | No system tray, no auto-start |
| Hot-reload during development | No auto-update mechanism |
| Zero packaging effort | Two things to start (CLI + browser) |
| Works on any OS with a browser | `localhost:8080` URL is an extra step |

**Verdict:** Fine for development and personal use. Not a product.

### Option B: Tauri Desktop App (Recommended)

```
┌──────────────────────────────────────┐
│  RACECRAFT DESKTOP APP (Tauri)        │
│                                        │
│  ┌──────────────────────────────────┐ │
│  │  Rust backend (Tauri core)       │ │
│  │  - Same rusty-telemetry code     │ │
│  │  - UDP listener, parsers         │ │
│  │  - Analysis engine               │ │
│  │  - Local SQLite database         │ │
│  │  - System tray integration       │ │
│  │  - Auto-start with OS            │ │
│  │  - Auto-update via Tauri         │ │
│  └──────────────┬───────────────────┘ │
│                 │                      │
│  ┌──────────────▼───────────────────┐ │
│  │  Vue 3 frontend (Tauri webview)  │ │
│  │  - Same racecraft code           │ │
│  │  - Native window on 2nd monitor  │ │
│  │  - OR open in external browser   │ │
│  └──────────────────────────────────┘ │
│                                        │
│  One installer: .exe / .deb / .dmg    │
│  Lives in system tray                  │
│  Auto-updates silently                 │
└──────────────────────────────────────┘
```

| Pro | Con |
|---|---|
| One-click install, feels like a real product | Need to build per-platform (Win/Mac/Linux) |
| System tray: start/stop recording from tray | Tauri adds a dependency to build pipeline |
| Auto-start with OS | Slightly more complex packaging |
| Auto-updates built into Tauri | |
| Native window (no Chrome needed) | |
| Still uses web tech for UI — no UI rewrite | |
| Tauri's Rust backend IS our Rust backend | |
| Can still open `localhost:8080` for debugging | |

**Why Tauri over Electron:**
- Tauri's backend IS Rust — our existing `rusty-telemetry` code plugs directly in
- Bundle size: ~5 MB (Tauri) vs ~150 MB (Electron)
- Memory: ~30 MB (Tauri) vs ~200 MB (Electron) — important when running alongside a game
- Tauri uses the OS webview, not a bundled Chromium
- Auto-update, system tray, file system access all built in

**Why this is the right answer:** The sim racer's PC is already running the game + multiple tools. A lightweight system-tray app that doesn't steal CPU cycles from the sim is the professional experience. Track Titan uses a similar approach (local agent + web UI).

### Option C: Pure Cloud / Web Platform

```
┌──────────────┐         ┌──────────────────┐
│  Game (sim)   │─ UDP ──▶│  Cloud server     │
│  sends to     │         │  - Parse telemetry│
│  remote IP    │         │  - Store data      │
│               │         │  - Run analysis    │
│               │         │  - Serve web UI    │
└──────────────┘         └──────────────────┘
```

| Pro | Con |
|---|---|
| Zero install — works on any device | Only works for games supporting remote UDP targets |
| Instant access from phone/tablet | Latency: 20–100ms to cloud vs. <1ms local |
| Easiest distribution | Requires internet during sessions |
| Centralized data for community features | Privacy: all telemetry data leaves the user's machine |
| | Can't capture AC KSUDP (requires local handshake) |
| | Server costs scale with users |
| | esports teams won't upload competitive data |

**Verdict:** Viable as a supplement (SimRacingSetup does this for F1), but NOT as the primary architecture. Too many games require local capture. Privacy-conscious users and esports teams won't upload data.

---

## 3. Recommended Architecture: Local-First Hybrid

The winning architecture combines local processing with optional cloud sync:

```
┌─────────────────────────────────────────────────────────┐
│                 RACECRAFT DESKTOP (Tauri)                 │
│                                                           │
│  ┌─────────────────────────────────────────────────────┐ │
│  │  LOCAL — Always available, works offline             │ │
│  │                                                     │ │
│  │  ┌───────────────┐  ┌────────────────────────────┐ │ │
│  │  │ Data Capture  │  │ Analysis Engine (Rust)      │ │ │
│  │  │ - UDP listen  │  │ - Lap detection             │ │ │
│  │  │ - Binary parse│  │ - Track model building      │ │ │
│  │  │ - Ring buffers│  │ - Corner analysis            │ │ │
│  │  │ - Recording   │  │ - Grip envelope              │ │ │
│  │  └───────────────┘  │ - Theoretical best lap       │ │ │
│  │                     │ - Time loss attribution       │ │ │
│  │  ┌───────────────┐  │ - Shift point analysis       │ │ │
│  │  │ Local Storage │  │ - (All analysis runs local)  │ │ │
│  │  │ - SQLite DB   │  └────────────────────────────┘ │ │
│  │  │ - JSONL files │                                  │ │
│  │  │ - Track models│  ┌────────────────────────────┐ │ │
│  │  └───────────────┘  │ UI (Vue 3 webview)          │ │ │
│  │                     │ - Dashboard, charts          │ │ │
│  │                     │ - Track maps, overlays       │ │ │
│  │                     │ - Coaching output            │ │ │
│  │                     └────────────────────────────┘ │ │
│  └─────────────────────────────────────────────────────┘ │
│                          │                                │
│                          │ Optional sync (when online)    │
│                          ▼                                │
│  ┌─────────────────────────────────────────────────────┐ │
│  │  CLOUD SERVICE (optional)                            │ │
│  │                                                     │ │
│  │  ┌─────────────────┐  ┌──────────────────────────┐ │ │
│  │  │ Data Library    │  │ Community                 │ │ │
│  │  │ - Track maps    │  │ - Leaderboards            │ │ │
│  │  │ - Car profiles  │  │ - Lap sharing             │ │ │
│  │  │ - Shift points  │  │ - Setup sharing           │ │ │
│  │  │ - Grip envelopes│  │ - Driver profiles         │ │ │
│  │  │ - Reference laps│  │ - Coaching marketplace    │ │ │
│  │  └─────────────────┘  └──────────────────────────┘ │ │
│  │                                                     │ │
│  │  ┌─────────────────┐  ┌──────────────────────────┐ │ │
│  │  │ User Accounts   │  │ AI Services (future)      │ │ │
│  │  │ - Auth          │  │ - Heavy ML coaching       │ │ │
│  │  │ - Cloud backup  │  │ - Anonymized aggregation  │ │ │
│  │  │ - Cross-device  │  │ - Natural language coach   │ │ │
│  │  └─────────────────┘  └──────────────────────────┘ │ │
│  └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
```

---

## 4. Where Should Number Crunching Happen?

### The Analysis

Every analysis operation we've defined falls into one of three categories:

#### A. MUST run locally (real-time, during sessions)

| Operation | Why Local | Data Size | Processing Time (Rust) |
|---|---|---|---|
| UDP capture & parsing | Hardware access (ports) | 3600 frames/min | <1ms per frame |
| Lap detection | Real-time, needs frame-by-frame | All frames in session | <1ms |
| Live dashboard updates | WebSocket to UI, sub-50ms latency | Current frame | <1ms |
| Recording management | Local filesystem (ring buffers, JSONL) | All frames | <1ms per write |

**These cannot move to a server.** The game is sending UDP packets to localhost. Nobody would tolerate 50ms+ latency on their live telemetry display.

#### B. SHOULD run locally (fast, per-session, privacy)

| Operation | Why Local | Data Size | Processing Time (Rust) |
|---|---|---|---|
| Track model building | ~2000 position points | ~60 KB | <10ms |
| Corner detection | ~1000 curvature samples | ~12 KB | <5ms |
| Per-corner analysis | ~3600 frames per lap × 20 laps | ~2 MB total | <50ms |
| Grip envelope calculation | ~72K frames binned by speed | ~8 MB | <100ms |
| Theoretical best lap | ~20 laps × sectors | ~8 MB | <20ms |
| Time loss attribution | ~20 laps × ~15 corners | ~8 MB | <100ms |
| Shift point analysis | ~72K frames | ~8 MB | <50ms |
| Optimal racing line (future) | Track model + grip envelope | ~100 KB | <500ms |

**Total processing for a full 20-lap session: <1 second in Rust.**

This is the key insight: **Rust is fast enough to make "send to server" pointless for all per-session analysis.** The datasets are small (a 20-lap session is ~10 MB of frames). The algorithms are O(n) or O(n log n). A modern CPU processes this in milliseconds.

Why would we send this to a server?
- **Network latency alone** (20–100ms round trip) exceeds the local processing time
- **Upload bandwidth** for 10 MB per session on a home connection
- **Privacy** — esports teams consider their telemetry data competitive intelligence
- **Reliability** — what happens when the server is down during a session?
- **Cost** — server compute for every user's every session adds up

**The only reason to run these on a server is if you're using Python and it's too slow.** We're using Rust. It's not too slow.

#### C. SHOULD run on a server (aggregation, community, heavy ML)

| Operation | Why Server | Data Size |
|---|---|---|
| Community track map aggregation | Needs data from many users | Cumulative |
| "Best known" grip envelope per car/track | Aggregation across all users' laps | Per car-track combo |
| Reference lap curation & ranking | Community-wide comparison | All uploaded laps |
| Heavy ML coaching models (future) | GPU required, model is large | User's full session |
| Natural language coaching (future LLM) | LLM inference is expensive | User's analysis results |
| Anonymized data aggregation for insights | Statistical analysis across population | Millions of sessions |

### Decision Matrix

| Analysis | Local | Cloud | Rationale |
|---|---|---|---|
| UDP capture + parsing | ✅ | ❌ | Hardware requirement |
| Lap detection | ✅ | ❌ | Real-time, trivial compute |
| Track model building | ✅ | ❌ | <10ms, local data |
| Corner detection | ✅ | ❌ | <5ms, local data |
| Per-corner analysis | ✅ | ❌ | <50ms for full session |
| Grip envelope | ✅ | ❌ | <100ms for full session |
| Theoretical best lap | ✅ | ❌ | <20ms, local data |
| Time loss attribution | ✅ | ❌ | <100ms, local data |
| Shift point analysis | ✅ | ❌ | <50ms, local data |
| Pre-calculated data serving | ❌ | ✅ | Aggregation from many users |
| Community track maps | ❌ | ✅ | Needs many users' contributions |
| Reference lap hosting | ❌ | ✅ | Community-wide ranking |
| ML coaching models (future) | ⚠️ | ✅ | GPU-heavy, but could run local with Vulkan |
| LLM coaching (future) | ⚠️ | ✅ | Can use local small LLM or cloud API |

**Rule of thumb: Crunch locally. Sync results to cloud for community features and pre-calculated data.**

---

## 5. The Pre-Calculated Data Library — The Real Product

This is the key insight: **the analysis algorithms are worth nothing without data to feed them.** But once you have a community contributing data, the accumulated library becomes more valuable than the software itself.

### What We Can Pre-Calculate and Offer

| Data Asset | Source | Value to User | Build Effort | Update Frequency |
|---|---|---|---|---|
| **Track Maps** | One boundary-recording session per track | Auto-detected corners, sectors, track width. User doesn't need to map anything — just download and go. | Low (community-contributed, 10 min per track) | When new tracks released |
| **Shift Points per Car** | One shifting analysis session per car | "Shift at 6,200 RPM in 1st, 6,400 in 2nd..." — instant setup guidance for any car. | Very Low (already implemented) | Per car, once |
| **Grip Envelopes per Car** | 10+ laps per car-track combo | "This car can do 1.4g lateral at 120 km/h" — baseline for coaching, grip utilization %. | Medium | Per car-track combo |
| **Corner Behavior Profiles** | Analysis of optimal line through each corner | "Turn 3 is a late-apex right — brake at 100m board, trail to apex, early throttle" | Medium | Per car-track combo |
| **Reference Laps** | Fast drivers' actual laps (pro/esports) | The "gold standard" lap to compare against. THE killer feature that makes Track Titan sticky. | Low (import from fast drivers) | Continuous (new laps uploaded) |
| **Setup Impact Maps** | Before/after analysis of setup changes | "Adding 2 clicks front wing adds 0.15g in high-speed corners but costs 3 km/h top speed" | High | Per car-track-setup combo |
| **Tyre Degradation Models** | Long-run data (15+ laps) | "Soft tyres fall off at lap 8, medium at lap 14" — strategy coaching | Medium | Per car-track-tyre combo |

### The Data Flywheel

```
Users drive & record → System generates analysis results →
Users contribute to data library → Library grows →
New users get instant value (download pre-made track maps, car profiles) →
More users → More contributions → Better library → ...
```

This is a **data network effect.** Each user's data makes the product better for everyone:
- The 1st user maps Vallelunga → all future Vallelunga users get corners for free
- The 100th user contributes laps → the grip envelope gets more accurate
- An esports driver uploads a reference lap → everyone can compare against it

### Contribution Model

| Contributor Type | What They Contribute | What They Get |
|---|---|---|
| **Free user** | Can use pre-calculated data | Basic telemetry + downloaded track maps |
| **Community mapper** | Track boundary recordings, car profiles | Pro tier free for 30 days per contribution |
| **Pro subscriber** | Can upload reference laps | Full analysis + AI coaching + all data |
| **Esports / Pro driver** | Reference laps, setup data | Verified "Pro" badge, revenue share on popular laps |

### Pricing With Data Library

| Tier | Price | Local Features | Cloud / Data Library Features |
|---|---|---|---|
| **Free** | £0 | Live telemetry, recording, local analysis, your own lap data | Browse track list (no downloads), basic shift points |
| **Pro** | £6/mo | All free features | Full data library: track maps, car profiles, grip envelopes, corner profiles for all supported cars/tracks |
| **Pro+** | £12/mo | All Pro features | Reference laps, time loss coaching, theoretical best lap vs. reference, AI coaching |
| **Team** | £25/mo per seat | All Pro+ features | Team dashboard, multi-driver comparison, shared setups, priority data |

---

## 6. Self-Hosting Option

For privacy-conscious users, esports teams, and racing academies:

### What Self-Hosting Means

The entire cloud service (data library, user accounts, community features) can be deployed on the user's own infrastructure:

```
docker compose up -d

# Starts:
# - racecraft-server (Rust, same codebase)
# - PostgreSQL (data library, user accounts)
# - MinIO (object storage for recordings, reference laps)
# - (optional) Ollama (local LLM for AI coaching)
```

### Why Self-Hosting Matters

| Audience | Why They Need Self-Hosted | Revenue Model |
|---|---|---|
| **Esports teams** | Don't want competitors seeing their data | £50/mo per team for the Docker image + support |
| **Racing academies** | Run on-premises for students | £100/mo per academy |
| **Privacy enthusiasts** | Don't trust cloud services | One-time £99 license for self-hosted edition |
| **Enterprise / OEM** | White-label for their own product | Custom pricing |

### Technical Requirements for Self-Hosted

- Docker + Docker Compose
- 2 GB RAM minimum (4 GB recommended for LLM coaching)
- 10 GB disk for data library
- No outbound internet required (works air-gapped)

---

## 7. Technology Stack Summary

### Local (Tauri Desktop App)

| Component | Technology | Notes |
|---|---|---|
| Desktop wrapper | **Tauri v2** | Rust backend, system tray, auto-update, native window |
| Telemetry engine | **Rust** (rusty-telemetry) | Same codebase, compiles into Tauri binary |
| Local database | **SQLite** via rusqlite | Track models, recordings, sessions, analysis results |
| Frontend | **Vue 3 + Vite** (racecraft) | Same codebase, rendered in Tauri webview or external browser |
| Charts | **Chart.js** or **ECharts** | Track maps, speed traces, G-force plots, overlays |
| Real-time comms | **WebSocket** (axum) | Live telemetry streaming to UI |

### Cloud Service (Optional Sync)

| Component | Technology | Notes |
|---|---|---|
| API server | **Rust** (axum) | Same codebase as local, extended with auth + sync endpoints |
| Database | **PostgreSQL** | Users, track models, car profiles, reference laps, community data |
| Object storage | **S3-compatible** (MinIO for self-hosted) | Recording archives, reference lap data |
| Auth | **JWT + OAuth2** | Email/password + Discord/Steam login |
| ML serving (future) | **ONNX Runtime** or **candle** | Run ML models in Rust without Python |
| LLM (future) | **Ollama** (self-hosted) or **cloud API** | Natural language coaching |

### Build & Distribution

| Platform | Format | Auto-Update |
|---|---|---|
| Windows | `.msi` installer + portable `.exe` | Tauri updater (checks GitHub Releases) |
| Linux | `.deb` + `.AppImage` | Tauri updater |
| macOS | `.dmg` | Tauri updater |

---

## 8. Migration Path from Current Architecture

### Phase 1: Keep Current Architecture, Build Features (Now → Month 3)

- rusty-telemetry stays as a CLI + local REST API
- racecraft stays as a Vue app served from localhost:8080
- Focus on features: lap detection, track mapping, corner analysis
- **No architecture changes needed yet**

### Phase 2: Add SQLite, Package as Tauri App (Month 3–4)

- Replace JSONL + JSON manifests with SQLite database
- Wrap rusty-telemetry + racecraft in Tauri
- Add system tray, auto-start, auto-update
- Ship as `.exe` / `.deb`
- **User experience transforms from "dev tool" to "product"**

### Phase 3: Add Cloud Sync + Data Library (Month 5–8)

- Build cloud API server (Rust/axum, same codebase)
- User accounts, data library, community features
- Pre-calculated data starts accumulating
- Self-hosted Docker option available from day one

### Phase 4: AI Coaching (Month 8+)

- Rule-based coaching (local, no ML needed)
- Optional cloud ML models for advanced coaching
- Optional local LLM via Ollama for privacy mode

---

## 9. Decision Summary

| Decision | Choice | Rationale |
|---|---|---|
| **Desktop app or website?** | Desktop app (Tauri) with web UI | UDP capture requires local component; Tauri gives professional UX |
| **Local or cloud analysis?** | **All analysis runs locally** | Rust processes a 20-lap session in <1 second; no reason to use a server |
| **Cloud role?** | Data library + community + optional heavy ML | Pre-calculated data, reference laps, aggregation across users |
| **Self-hostable?** | Yes, from day one of cloud phase | Docker Compose, same Rust codebase, works offline |
| **Pre-calculated data?** | Track maps, car profiles, shift points, reference laps | This IS the product — the software is the delivery mechanism |
| **Data format** | SQLite locally, PostgreSQL in cloud | Structured queries, transactions, proven at scale |
| **Frontend** | Vue 3 in Tauri webview or external browser | Same codebase for both modes |
| **Auto-update** | Tauri built-in updater | Checks GitHub Releases, downloads in background |
| **Monetization** | Freemium SaaS with data library as the value | Free: local analysis. Paid: pre-calculated data + community + AI |

---

*Last updated: 2026-06-06*
*Parent: [Sim Racing Telemetry Analysis Platform — Project Plan](joplin://6c0dcb2a567348fd9796f50c790082e4)*
*Tags: architecture, infrastructure, product-strategy, tauri, cloud, self-hosting*

id: c1c3a7b2055642268ab230b95551f470
parent_id: 0e8e00b432a840628faa4df5bc2068bc
created_time: 2026-06-06T07:42:41.086Z
updated_time: 2026-06-06T07:42:41.086Z
is_conflict: 0
latitude: 0.00000000
longitude: 0.00000000
altitude: 0.0000
author: 
source_url: 
is_todo: 0
todo_due: 0
todo_completed: 0
source: joplin-desktop
source_application: net.cozic.joplin-desktop
application_data: 
order: 1780731761086
user_created_time: 2026-06-06T07:42:41.086Z
user_updated_time: 2026-06-06T07:42:41.086Z
encryption_cipher_text: 
encryption_applied: 0
markup_language: 1
is_shared: 0
share_id: 
conflict_original_id: 
master_key_id: 
user_data: 
deleted_time: 0
type_: 1