Mobile activity tracker: record runs/hikes/bikes on iOS/Android + new recorded-routes sync API #920

Closed
opened 2026-08-05 22:33:17 +00:00 by spikerj · 1 comment
Owner

The web /tracker (MapLibre map, pitch-slider 2D/3D, GPS recording, distance/duration/avg-speed stats, saved-route recall) has no mobile equivalent — and the web version stores routes ONLY in browser IndexedDB (no server API exists; api/Trails is the curated catalog, api/activity is knowledge analytics).

Scope (3 PRs):

  1. spikersoft-backend — new owner-scoped api/recorded-routes (upload/list/get/update-metadata/delete), RecordedActivityType enum (run/hike/bike/walk/other), two collections (recorded-routes summaries + recorded-route-points write-once JSON), server-recomputed stats, hard deletes, no coordinate logging (minors' location data).
  2. spikersoft-android — MapLibre Native map (web's 6 base maps + hillshade from tiles.spikersoft.com terrain DEM; pitch/bearing 2.5D — native setTerrain not shipped upstream yet), foreground-service background recording (2s/5m sampling), Room local store + WorkManager offline sync, history/detail screens, Home-card entry.
  3. spikersoft-ios — same feature: MapLibre iOS SPM, CLLocationUpdate.liveUpdates + CLBackgroundActivitySession background recording, JSON-file store + sync actor, Home-card entry, first unit-test target for the app.

Follow-ups (separate tickets when reached): migrate the web tracker from IndexedDB to this API; GPX export; elevation-gain stat; gate the unauthenticated /api/directions Google proxy.

The web `/tracker` (MapLibre map, pitch-slider 2D/3D, GPS recording, distance/duration/avg-speed stats, saved-route recall) has no mobile equivalent — and the web version stores routes ONLY in browser IndexedDB (no server API exists; `api/Trails` is the curated catalog, `api/activity` is knowledge analytics). **Scope (3 PRs):** 1. **spikersoft-backend** — new owner-scoped `api/recorded-routes` (upload/list/get/update-metadata/delete), `RecordedActivityType` enum (run/hike/bike/walk/other), two collections (`recorded-routes` summaries + `recorded-route-points` write-once JSON), server-recomputed stats, hard deletes, no coordinate logging (minors' location data). 2. **spikersoft-android** — MapLibre Native map (web's 6 base maps + hillshade from tiles.spikersoft.com terrain DEM; pitch/bearing 2.5D — native `setTerrain` not shipped upstream yet), foreground-service background recording (2s/5m sampling), Room local store + WorkManager offline sync, history/detail screens, Home-card entry. 3. **spikersoft-ios** — same feature: MapLibre iOS SPM, CLLocationUpdate.liveUpdates + CLBackgroundActivitySession background recording, JSON-file store + sync actor, Home-card entry, first unit-test target for the app. Follow-ups (separate tickets when reached): migrate the web tracker from IndexedDB to this API; GPX export; elevation-gain stat; gate the unauthenticated `/api/directions` Google proxy.
Author
Owner

Verified complete 2026-08-07 — closing.

All three scoped PRs merged and the server half is live.

  • Code:
    • spikersoft-backend@9bd75f6a (PR #519, feat/recorded-routes-api) — owner-scoped api/recorded-routes: SpikerSoft.Api/Domain/Map/RecordedRoutes/RecordedRoutesController.cs, SpikerSoft.Data/DTOs/RecordedRouteDtos.cs, SpikerSoft.Data/Mongos/Map/RecordedRoute/RecordedRouteEF.cs, collections wired in SpikerDbContext.cs.
    • spikersoft-android@30b3845 (PR #3) + @7a48fb2 (PR #4 parity fixes) — features/tracker/ (TrackerScreen, RouteHistoryScreen, RouteDetailScreen, TrackerMapView), core/tracking/RecordingService.kt, assets-tracker/tracker_style.json, Room + WorkManager sync.
    • spikersoft-ios@933c375 (PR #4) — Features/Tracker/ (TrackerView, TrackerMapView, RouteHistoryView, RouteDetailView), Resources/TrackerStyle.json, Core/Networking/TrackerDTOs.swift, plus the first SpikerSoftTests target.
  • Live: GET https://api.spikersoft.com/api/recorded-routes → 401 (auth required) while POST /api/recorded-routes/{id}/bogusnothing and /api/zzz-not-a-controller → 404 — so the controller really is deployed, not just merged. Mobile binaries have nothing probeable from here.
  • Shipped by: backend#519, android#3 + #4, ios#4.

The follow-ups named in the body (web IndexedDB→API migration, GPX export, elevation gain, gating /api/directions) were explicitly deferred to separate tickets and are not part of this one. The device-verification checklist is a human smoke test, not outstanding engineering work.

Not migrated: nothing left to do.

— Opus 5 Agent

Verified complete 2026-08-07 — closing. All three scoped PRs merged and the server half is live. - **Code:** - `spikersoft-backend@9bd75f6a` (PR #519, `feat/recorded-routes-api`) — owner-scoped `api/recorded-routes`: `SpikerSoft.Api/Domain/Map/RecordedRoutes/RecordedRoutesController.cs`, `SpikerSoft.Data/DTOs/RecordedRouteDtos.cs`, `SpikerSoft.Data/Mongos/Map/RecordedRoute/RecordedRouteEF.cs`, collections wired in `SpikerDbContext.cs`. - `spikersoft-android@30b3845` (PR #3) + `@7a48fb2` (PR #4 parity fixes) — `features/tracker/` (TrackerScreen, RouteHistoryScreen, RouteDetailScreen, TrackerMapView), `core/tracking/RecordingService.kt`, `assets-tracker/tracker_style.json`, Room + WorkManager sync. - `spikersoft-ios@933c375` (PR #4) — `Features/Tracker/` (TrackerView, TrackerMapView, RouteHistoryView, RouteDetailView), `Resources/TrackerStyle.json`, `Core/Networking/TrackerDTOs.swift`, plus the first `SpikerSoftTests` target. - **Live:** `GET https://api.spikersoft.com/api/recorded-routes` → **401** (auth required) while `POST /api/recorded-routes/{id}/bogusnothing` and `/api/zzz-not-a-controller` → **404** — so the controller really is deployed, not just merged. Mobile binaries have nothing probeable from here. - **Shipped by:** backend#519, android#3 + #4, ios#4. The follow-ups named in the body (web IndexedDB→API migration, GPX export, elevation gain, gating `/api/directions`) were explicitly deferred to separate tickets and are not part of this one. The device-verification checklist is a human smoke test, not outstanding engineering work. Not migrated: nothing left to do. — Opus 5 Agent
Sign in to join this conversation.