← Lab

Lab project

Bonvo Ski Maps
Native appiOS · Tourism2024 — 2026

Native iOS / macOS / watchOS ski mapping and navigation.
SwiftUI ski-resort mapping app across iOS, macOS and watchOS targets. 120 personal commits, MapKit / Mapbox-integrated rendering and offline routing for backcountry navigation.
Architecture
How it's built
A SwiftUI codebase that ships three targets — iOS, macOS and watchOS — from one shared core. SwiftData persists user state on the device; Supabase REST keeps profiles, saves and follows in sync across platforms; MapKit renders the primary UI while Mapbox carries the vector tiles and offline routing for backcountry slopes. RevenueCat gates the paid surfaces and Firebase + Microsoft Clarity provide the feature flags and session replay.
Data flow
- 01App launches — Firebase + Clarity initialise, RevenueCat checks the cached entitlement, Supabase session is restored.
- 02User authenticates — the bonvoski:// deep link returns from Supabase OAuth and SwiftData stores the refresh token.
- 03Map opens — MapKit lays down the base, Mapbox loads cached vector tiles, Core Location resolves the nearest resort.
- 04User saves a slope — the row is written locally (SwiftData) and queued for Supabase; the UI never waits on the network.
- 05Going offline — backcountry routing runs against the downloaded Mapbox tiles + Overpass slope data already on disk.
- 06User crosses a paywall — RevenueCatUI presents the sheet; on a successful purchase the entitlement is refreshed within 5 seconds.
Design decisions
- Dual mapping pipeline — MapKit for native look and feel, Mapbox for vector data and offline tile downloads — chosen so backcountry sessions work without signal.
- Three Apple targets share Core services through SwiftUI's Environment so the watch app is not a port, it is the same code with a smaller surface.
- SwiftData is the offline canonical store; Supabase rows are reconciled on reconnect — the app never blocks on the network.
- RevenueCat is polled every 5s while authenticated so an entitlement change (refund, churn) propagates without a relaunch.
- Deep links via bonvoski:// route directly to resort / slope / lift screens — sharing a slope is a single tap.
External integrations
Supabase RESTMapKitMapbox SDKRevenueCatFirebase (Remote Config)Microsoft ClarityOverpass API