TrackTales: Parse, analyze, and visualize your Apple Health workout data with an interactive NiceGUI interface.
Project description
🏃♂️ TrackTales
A modern, interactive tool to parse, analyze, and visualize your Apple Health workout data. Built with NiceGUI, TrackTales transforms your fitness journey into rich interactive charts, segment analysis, and personalized insights. This is a personal project, but contributions are welcome!
👩💻 For Contributors
If you are contributing or maintaining the project, see MAINTAINERS.md.
✨ Features
- ZIP Parsing: Directly select and parse your
export.zipfile from Apple Health. - Workout Extraction: Focused on running workouts with detailed metrics (distance, duration, METs, heart rate, power, etc.).
- Visual Statistics: Real-time summary of total activities, distance, duration, elevation, and calories with interactive charts (pie/rose charts for activity breakdown, bar charts with trend lines for time-based analysis).
- Interactive Charts: Every chart supports zoom and pan (mouse scroll, pinch, or trackpad gesture). Click the ⛶ fullscreen button on any chart to open it in a maximized view with a range-slider for precise zoom control. Tooltips are rich HTML with bold labels and value+unit on each axis hover.
- Health Data Insights: Health Data tab combines workout activity timing (day/hour heat map) with period-based trends for resting heart rate, body mass, VO2 max, Critical Power (CP), and W'. Fast metrics load immediately and CP/W' fill in progressively in the background.
- Best Segments Tab: Computes and displays best running segments from 100m to 100km with expandable runner-up rows, formatted durations, localized labels, and segment power confidence.
- Robust Segment Distance Model: Segment search uses GPX speed integration with safeguards for export edge cases (window clipping, final unpaired pause trimming, strict reversal-only trace splits, and realistic workout-level distance normalization).
- Activity Filtering: Filter your workout data by activity type (Running, Cycling, Walking, etc.).
- Workout Detail Modal: Open per-workout details from the Activities table. The wider modal now includes six tabs: Overview, Activity, Route (Leaflet map with start/end markers for each route part), Profile (elevation + pace dual-axis chart with speed/heart-rate tooltip metrics when available), Intervals, and Comparisons (historical same-route ranking with rank and time gap). The Profile chart uses non-zero-based axes, centered axis titles, and top legend placement for readability. Type-specific Activity metrics vary by sport — Running: pace, cadence, stride length, vertical oscillation, ground contact time, step count; Walking: pace, cadence, step length, step count; Hiking: elevation gain, pace, cadence, step length, step count; Cycling: speed, cadence, power, functional threshold power; Swimming: pool/open-water location, lap length, total stroke count. Activity/route-dependent tabs are disabled when required data is unavailable.
- Date Range Filtering: Analyze specific time periods using the date range picker to focus on your desired date ranges.
- Trends Period Aggregation: Switch the Trends tab aggregation between week, month, quarter, or year.
- Gap-Aware Time Series: Missing periods are preserved in health-data charts, so the x-axis remains continuous and missing measurements are explicit (not coerced to zero). For line charts, inferred bridge segments are visually distinct from measured segments.
- Route Parts Handling: Workouts with multiple GPX route files are preserved as independent route parts for segment analysis and also exposed as a merged compatibility route.
- Multilingual UI (EN/FR): gettext-based translations for labels, tabs, date picker locale labels, notifications, and loading/progress status messages.
- Unit System Preference: Switch between Metric (km, kg, m) and Imperial (mi, lbs, ft) from the preferences menu; all stats, charts, and tables update accordingly.
- Data Export: Convert your data into clean CSV or JSON formats for further analysis in Excel, Python, or other tools.
- All processing happens locally on your machine.
- Modern UI: Dark/Light mode support with a responsive layout.
🚀 Installation
Prerequisites
- Python 3.10 or higher.
- An Apple Health export file (
export.zip).
Setup
Clone the repository
git clone https://github.com/NicolasReyrolle/tracktales.git
cd tracktales
Create a virtual environment
# Windows
python -m venv .venv
.\.venv\Scripts\Activate.ps1
# Linux/macOS
python3 -m venv .venv
source .venv/bin/activate
Install the dependencies
pip install -r requirements.txt
🖥️ Usage
Start the application using the following command:
python -m nicegui src.tracktales
- Open your browser to
http://localhost:8080. - Click Browse to select your Apple Health
export.zip. - Click Load to parse the data.
- View the statistics in the Overview tab.
- Explore your data in the Activities tab (pie/rose charts grouped by activity type), Trends tab (weekly/monthly/quarterly/yearly bar charts with moving average trend lines), Health Data tab (workout heat map plus line charts for resting heart rate, body mass, VO2 max, CP, and W'), and Running tab (distance/elevation pace analysis with best segments).
- In the Activities table, click the Details action to open the workout modal (Overview, Activity, Route map, Profile elevation/pace chart, Intervals, and Comparisons).
- Use the Activity filter in the left drawer to focus on specific workout types.
- Use the Date range picker to analyze specific time periods.
- Use the Aggregate by selector in the left drawer to change the aggregation period.
- Use the Preferences menu (tune icon in the header) to switch language (EN/FR) or unit system (Metric/Imperial).
- Export your data using the Export data menu to download CSV or JSON files.
Tip: You can set a permanent storage secret for sessions by using an environment variable:
set STORAGE_SECRET=your_custom_secret(Windows)
📱 How to Get Your Export File
To analyze your data, you first need to export it from your iPhone:
- Open the Health app on your iPhone.
- Tap your Profile Picture or icon in the top-right corner.
- Scroll to the bottom and tap Export All Health Data.
- Tap Export to confirm. This process may take a few minutes depending on the amount of data.
- Once the export is ready, share the
export.zipfile to your computer (via AirDrop, iCloud Drive, OneDrive, GoogleDrive or any other mean). - Use this file in the TrackTales app.
🛠️ Development & Testing
Maintainer and contributor documentation is centralized in MAINTAINERS.md.
For development setup, quality checks, release workflow, packaging validation, and architecture notes, use MAINTAINERS.md as the single source of truth.
🔒 Security
This application uses streaming XML parsing (iterparse) to remain memory-efficient even with large exports (GBs of data) and defusedxml.ElementTree to mitigate risks associated with untrusted XML data.
📄 License
This project is licensed under the GPL-3.0 License. See the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tracktales-2026.5.1.tar.gz.
File metadata
- Download URL: tracktales-2026.5.1.tar.gz
- Upload date:
- Size: 138.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e53ac54239ccf487d0c0ea0b583a555215dbbae4a734b591f81b04b1bbc1f666
|
|
| MD5 |
49938461bc166b00a36a42472f4fd63f
|
|
| BLAKE2b-256 |
8a79804fcd309bfcc560c7fe06494fbb8f49b191b275f9bf7540a5905d40ed8f
|
Provenance
The following attestation bundles were made for tracktales-2026.5.1.tar.gz:
Publisher:
release.yml on NicolasReyrolle/TrackTales
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tracktales-2026.5.1.tar.gz -
Subject digest:
e53ac54239ccf487d0c0ea0b583a555215dbbae4a734b591f81b04b1bbc1f666 - Sigstore transparency entry: 1592056059
- Sigstore integration time:
-
Permalink:
NicolasReyrolle/TrackTales@cba7b21d959054d81933c3594d796dfc2b36ed38 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/NicolasReyrolle
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cba7b21d959054d81933c3594d796dfc2b36ed38 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file tracktales-2026.5.1-py3-none-any.whl.
File metadata
- Download URL: tracktales-2026.5.1-py3-none-any.whl
- Upload date:
- Size: 138.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7802fc47ce2b0e19839411b9af865434eeea35f6447dafcdff5b40808e6f8a1f
|
|
| MD5 |
880c4ecfb05ccaeed8aed730e4089060
|
|
| BLAKE2b-256 |
5878f2265388eb050d92b57eaf0dc06aa017fc130e5e33e4202dc4925145532e
|
Provenance
The following attestation bundles were made for tracktales-2026.5.1-py3-none-any.whl:
Publisher:
release.yml on NicolasReyrolle/TrackTales
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tracktales-2026.5.1-py3-none-any.whl -
Subject digest:
7802fc47ce2b0e19839411b9af865434eeea35f6447dafcdff5b40808e6f8a1f - Sigstore transparency entry: 1592056077
- Sigstore integration time:
-
Permalink:
NicolasReyrolle/TrackTales@cba7b21d959054d81933c3594d796dfc2b36ed38 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/NicolasReyrolle
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cba7b21d959054d81933c3594d796dfc2b36ed38 -
Trigger Event:
workflow_dispatch
-
Statement type: