Skip to content

Repository files navigation

Activity Explorer

Version .NET 10 Blazor Web App License: MIT

Activity Explorer is a local, open-source Blazor application for exploring your cycling, running, and walking history. It works from files you own - Garmin account exports, Strava bulk exports, and individual FIT, GPX, TCX, GZ, or ZIP files - without API credentials, web scraping, or automated access to Garmin or Strava.

Version 0.1.0 is deliberately local-first and has no login system. It binds to localhost by default and stores the database, imported originals, and logs outside the repository.

What it does

  • Imports official Garmin and Strava account exports and individual activity files.
  • Provides official-history ZIP, bounded multi-file, and local-inbox workflows without accepting provider credentials.
  • Keeps immutable copies of every distinct imported original.
  • Deduplicates exact files and equivalent activities across formats while retaining provenance.
  • Shows dashboards, searchable activities, synchronized gap-aware sensor/respiration charts, rich FIT summaries, laps, records, routes, segments, and a combined world map.
  • Deletes one activity, selected activities, or an exact snapshot of the current filtered results with an inline permanent-deletion confirmation.
  • Supports separate local owner profiles and an "All profiles" aggregate view.
  • Calculates an ordered catalog of cycling, running, and walking distance bests, 5-second through 2-hour power bests, and directional local segment efforts.
  • Uses locally vendored MapLibre with a blank basemap by default; OpenFreeMap is a persistent, explicit global opt-in.
  • Watches optional local folders without moving or deleting the files in them.

Activity Explorer does not use the Strava API, Garmin Connect API, OAuth credentials, provider passwords, automated Connect access, or proprietary Strava segments. Automatic phone-to-app synchronization is not available in 0.1.0.

Quick start

Prerequisites:

  • .NET SDK 10.0.302, pinned exactly by global.json.
  • An official account export or one or more FIT/GPX/TCX files.

Run:

dotnet restore ActivityExplorer.slnx --locked-mode
dotnet run --project src/ActivityExplorer.Web

Open http://localhost:8342, create a profile, and open Imports. Choose Complete Garmin history, Recent files, or Local inbox. Work continues in a durable background queue, and reports remain available after completion.

On Bash shells, the same dotnet commands work unchanged.

Docker Compose

Docker is optional:

docker compose up --build

The compose configuration publishes only 127.0.0.1:8342 and stores application data in the activity-explorer-data volume. Stop it with docker compose down. Do not add -v unless you intentionally want Docker to delete the volume and all imported data.

Data location

By default the application uses the operating system's local application-data folder:

  • Windows: %LOCALAPPDATA%\Activity Explorer
  • Linux: normally ~/.local/share/Activity Explorer
  • macOS: the platform local application-data location returned by .NET

Set ACTIVITY_EXPLORER_DATA to use a different absolute location:

$env:ACTIVITY_EXPLORER_DATA = "D:\ActivityExplorerData"
dotnet run --project src/ActivityExplorer.Web

The directory contains:

  • activity-explorer.db: SQLite metadata and summaries.
  • originals/: immutable, content-addressed activity files grouped by profile.
  • staging/: temporary imports; interrupted work is retained for restart recovery.
  • logs/: bounded rolling diagnostics.
  • quarantine/: profile directories or unreferenced activity originals awaiting durable cleanup after database deletion.
  • keys/: persistent ASP.NET Core data-protection keys; include them in a complete backup.

Back up the whole application-data directory while Activity Explorer is stopped. See Data storage and privacy.

Supported imports

Input Support
Garmin account-export ZIP Documented uploaded-files layouts, nested archives, and irrelevant-wellness filtering
Strava bulk-export ZIP Original files enriched from activities.csv
FIT Official SDK parsing for timing, laps, track, sensors, respiration, temperature, calories, and training fields when recorded
GPX / TCX Hardened streaming XML readers
GZ / ZIP Safely expanded with traversal, symlink, nesting, count, and size limits

Only cycling, running, and walking activities are imported. Indoor and virtual variants map to their base sport. Other sport files are reported and skipped.

See Importing data and Legal and export guides.

Maps and privacy

MapLibre renders local activity, route, and segment geometry on a blank basemap by default. In this mode every map makes zero requests to external map hosts. You can explicitly enable OpenFreeMap for all maps under Settings; the choice persists locally. Online style and tile requests reveal the viewed area to the configured provider, but do not upload stored activity files or tracks.

OpenStreetMap attribution remains visible whenever the online basemap is active. Route and other map queries are viewport-bounded, including viewports that cross the antimeridian. See Maps.

Security boundary

This is a no-login personal application. Localhost binding is intentional.

Do not expose it to a LAN, reverse proxy, tunnel, or the public internet. Anyone who can reach the application can view location and health data, download imported originals, edit activities, and permanently delete activities or profiles.

Activity deletion uses an inline confirmation that names the affected activity or exact selected/filtered count. Profile deletion requires entering DELETE followed by the profile name. Both are destructive. A profile JSON export describes the local records, but it is not a full backup of original files.

Repository layout

src/
  ActivityExplorer.Core/            Domain models, DTOs, and contracts
  ActivityExplorer.Infrastructure/  SQLite, imports, calculations, background work
  ActivityExplorer.Web/             Blazor Interactive Server host and UI
tests/
  ActivityExplorer.Tests/           Unit and SQLite integration tests
docs/                               User, architecture, privacy, and legal guides

The design keeps EF entities out of Razor components and exposes testable services such as IActivityImporter, IActivityQueryService, ISegmentMatcher, IRouteService, and IStatisticsService.

Development

dotnet restore ActivityExplorer.slnx --locked-mode
dotnet format ActivityExplorer.slnx --verify-no-changes --no-restore
dotnet build ActivityExplorer.slnx --configuration Release --no-restore -m:1 -p:BuildInParallel=false
dotnet test tests/ActivityExplorer.Tests/ActivityExplorer.Tests.csproj --configuration Release --no-build --no-restore -m:1 -p:BuildInParallel=false

For a release candidate, also run the coverage gates, package advisory/deprecation check, isolated Playwright regressions, and loopback-only Docker smoke test documented in Testing.

No default test performs a live Garmin or Strava request. Test data is synthetic and fictional.

Legal

The Activity Explorer source code is MIT licensed. Dependencies retain their own licenses. In particular, Garmin's official FIT SDK uses Garmin's separate FIT Protocol License and is restored from NuGet rather than redistributed in this repository; review that license before building or distributing the application. See Dependency and license inventory.

Activity Explorer is an unofficial product and is not affiliated with, endorsed by, or sponsored by Garmin, Strava, OpenFreeMap, or OpenStreetMap. Product names are used only to identify compatible user-supplied export formats. No third-party logos, credentials, or tokens belong in this repository.

About

Local-first Blazor web app for exploring cycling, running, and walking history from Garmin/Strava exports and individual FIT, GPX, or TCX files.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages