Skip to content

Local Storage

All user data is stored locally on Windows under %LocalAppData%\ApexLab\. Nothing is deleted automatically — the user controls their own data.

4. Local Storage — Session Catalog (SQLite)

File: %LocalAppData%\ApexLab\sessions.db

Why it exists: CSV files contain all data but reading them is slow. The catalog caches key metadata so the session list UI loads instantly without re-parsing every file.

sessions table

Column Type Why it exists How it's set When it changes
id INTEGER PK AUTOINCREMENT Stable local key for settings (LastSessionCatalogId) Auto-assigned on insert Never
track TEXT UI display; search filter From TelemetrySessionMetadata.TrackName on import On UpdateSessionSnapshot() if metadata improves
vehicle TEXT UI display; search filter From TelemetrySessionMetadata.VehicleName On snapshot update
file_path TEXT UNIQUE Locates the CSV file for loading Set at RegisterFile() time; unique constraint prevents duplicates Never (file moves break the link)
imported_at TEXT Sort order; "catalogued" timestamp in UI DateTime.UtcNow at RegisterFile() Never
notes TEXT User-authored session notes Set on import dialog; editable from session detail On user edit
game TEXT Game filter in session library From GameSourceId.ToString() On snapshot update
is_favorite INTEGER (0/1) ★ filtering and display Set via ToggleFavorite() command On user toggle
tags TEXT Future tag-based filtering (V2) Not yet populated Reserved
lap_count INTEGER Shown in session list without reading CSV From SessionData.Laps.Count on import On snapshot update
metadata_json TEXT Full TelemetrySessionMetadata for dashboard subtitle and weather display JSON-serialized on import On snapshot update
best_lap_seconds REAL Personal best comparison; shown as subtitle From SessionData.BestValidLap.LapTimeSeconds On snapshot update
synced_at TEXT Indicates whether session has been uploaded to cloud Set by SyncService.MarkSynced() after successful API upload Once, on first successful sync
cloud_session_id TEXT Required to submit this session to the leaderboard Returned by POST /v1/sessions; stored by MarkSynced() Once, on sync

5. Local Storage — Session Files (CSV)

Location: %LocalAppData%\ApexLab\Sessions\sess_{guid}.csv

Why it exists: Full telemetry cannot be reconstructed from summaries. The CSV is the ground truth for all analysis and playback.

Comment header (metadata lines before the column header)

Header Example Why it's written
# Track: Spa-Francorchamps Human readability; re-read by CsvTelemetryReader to populate TelemetrySessionMetadata
# TrackLayout: Full Distinguishes circuit variants
# Vehicle: Ferrari 499P Session context for coaching
# Recorded: 2026-04-19T20:00:00Z Session timestamp
# Source: ApexLab 1.0 App version that wrote the file (audit)
# GameSource: LmuRf2 Which connector produced this data
# WeatherAmbientC: 18.5 Ambient temperature (°C)
# WeatherTrackC: 32.1 Track surface temperature (°C)

Data columns

Column Type Required? Why it exists
Time float (seconds) Yes Lap time derivation; cumulative time for delta
Distance float (metres) Yes Primary alignment axis for lap comparison
Speed float (km/h) Yes Core performance metric
Throttle float (0–1) Yes Driver input analysis
Brake float (0–1) Yes Driver input analysis
Steering float (degrees) Yes Corner detection
Gear int Yes Vehicle context
X float Yes Track map rendering; centerline fusion
Y float Yes Track map rendering; centerline fusion
Lap int Yes Lap boundary detection (changes = new lap)
OfficialLapTime float (seconds) Optional Best-quality lap time source; preferred over time-delta method
NumPenalties int Optional Uploaded to API as lap quality context
NumPitstops int Optional Flags pit stops within the lap
InPits int (0/1) Optional Marks pit laps; sets CountsForSessionTiming = false

6. Local Storage — Track Profiles (SQLite)

File: %LocalAppData%\ApexLab\track_profiles.db

track_profiles table

Column Why it exists
slug (PK) URL-safe identifier for the track (e.g. spa-lmu-complete); used as SVG cache key
game Which game the profile came from
layout_label Track variant label
geometry_hash Hash of the track centerline; changing it invalidates the SVG cache
track_name_hint Original game name for display
created_at_utc Audit
notes Admin notes

Why this is separate from sessions.db: Track profiles represent canonical track geometry, not user sessions. They are shared across all sessions on the same track.


7. Local Storage — User Settings (JSON)

File: %LocalAppData%\ApexLab\settings.json

Why it exists: Persists user preferences across app restarts without a database.

Setting Default Why it exists
ApiBaseUrl https://simcopilot-production.up.railway.app Allows switching to a staging or local API
SentryDsn null Optional crash reporting; null = disabled
AcUdpHost / AcUdpPort 127.0.0.1:9996 Assetto Corsa UDP listener address
F1UdpPort 20777 F1 Codemasters/EA UDP port
ForzaUdpPort 5300 Forza Data Out UDP port
LiveAutoCaptureLmu true Start LMU recording automatically when SHM provides data
LiveAutoListenAcUdp true Start AC UDP listener at app launch
MinimizeToTray true Minimize to system tray icon instead of taskbar
HideLiveDeltaMapOverlay false Hide Δ overlay on track map during recording
HideLiveDeltaStatusBar false Hide Δ/prediction in status bar
HideLiveDeltaInMainWhenHudOpen false Suppress main-window Δ when HUD window is open (avoid triple display)
LastSessionCatalogId null Restore last-opened session on next launch
MainWindow* null Window position/size restoration
HudWindow* null HUD overlay position restoration
LapPlaybackSpeedMultiplier 1.0 Playback speed (0.5×, 1×, 2×)
LapPlaybackLoop false Auto-loop lap playback
LapPlaybackMapFollow false Pan map to track cursor during playback
StartWithWindows false Windows Run registry key
UiLanguage null (= system) Force "fr" or "en"
HasSeenOnboarding false Skip onboarding screen after first run
Analysis* null Override default AnalysisOptions values (brake margin, throttle margin, etc.)
SectorBoundariesByTrackKey null Custom mini-sector boundaries per track (track key → list of distance bounds in metres)

Read at: app startup. Written at: any settings change; window close (position/size).


8. Local Storage — Auth Tokens (encrypted file)

File: %LocalAppData%\ApexLab\auth.dat

Why it exists: JWT tokens must survive app restarts so the user does not need to log in every session.

Field stored Why
AccessToken JWT Bearer token sent with every authenticated API request
RefreshToken Long-lived token (30 days) used to obtain a new access token without re-login
ExpiresAt Expiry of the access token; checked before each API call to decide whether to refresh
DisplayName Shown in the UI header without an API round-trip
AvatarUrl Shown in the UI header without an API round-trip

Encryption: The file is protected using the Windows Data Protection API (DPAPI) — encrypted to the current Windows user account. The raw token values are never stored in plaintext.

Lifecycle: Written on successful login or token refresh. Cleared on Logout(). If missing or unreadable at startup, the user is treated as not authenticated.