Skip to content

v3.0.0

Choose a tag to compare

@github-actions github-actions released this 09 Sep 21:17
· 310 commits to master since this release
eec1cd5

API-backed React dashboard, deployed to Vercel (API mode) and GitHub Pages
(static mode) from the same source.

Added

  • Deployment: vercel.json, requirements.txt and scripts/vercel-build.sh
    run the export at build time and serve the React app in API mode with
    api/graphql.py as a Python serverless function; the GitHub Pages
    workflow now builds the React app in static mode under /<repo>/ with a
    404.html fallback for deep links.
  • React views: Overview (KPIs, daily-distance heatmap, monthly distance and
    pace, recent runs, personal bests, training load, weight vs distance,
    temperature vs pace, weather strip), Activity (pace-coloured Canvas route
    with playback, scrubbing and hover, synced elevation / pace / cadence /
    temperature charts, previous / next navigation, keyboard shortcuts) and
    Activities (filter, sort, CSV export), Year in Review (infographic with
    hours-per-month stairs, diamond-per-day grid, weight summary),
    Performance (KPIs, pace trend, distance histogram, weekday and
    time-of-day pace, cadence vs pace, monthly table), Weight (KPIs, daily and
    7-day average, monthly change, weekday change, weekly km vs change,
    up/down table), Weather Impact (KPIs, HKO range, sky conditions,
    temperature bands, humidity vs pace, warning and extremes tables),
    Training Load (CTL/ATL/TSB, weekly distance with 4-week average and week
    drill-down, weekday distance, biggest weeks) and Settings (preferences
    form, data summary). All nine v2 views now have React equivalents. HKO
    warning icons and the v2 preferences store (localStorage) are ported.
  • frontend/: Vite + React 19 + TypeScript scaffold for the v3 dashboard
    with a DataSource abstraction (GraphQL via graphql-request + Codegen,
    or static JSON), TanStack Query hooks, a TypeScript port of the year
    statistics, Tailwind CSS 4 theme tokens from v2, the nine-view shell and
    the Overview KPI row; 35 Vitest tests; CI job for lint, typecheck, tests
    and both builds.
  • run365-schema: prints the GraphQL SDL; CI checks
    frontend/schema.graphql is current.
  • run365days.api: Flask application factory with a Strawberry GraphQL
    schema (meta, activities, activity, weight, weather,
    warnings, year aggregates) served at /api/graphql, reading the
    exported SQLite database read-only; api/graphql.py is the Vercel entry.
  • run365days.dashboard.stats: pure year aggregations (totals, monthly,
    weekly, daily distance, training load, personal bests).
  • run365days.export: one intermediate record set written two ways by
    run365-export, a SQLite database (SQLAlchemy 2.0 models) for the API
    and split JSON files for the static dashboard build.
  • run365days.cli console scripts: run365-activities, run365-weather,
    run365-dashboard, run365-export.
  • RUN365_DATA_DIR environment variable to relocate the data directory.
  • Google-style docstrings on every public module, class and function,
    enforced by ruff's pydocstyle rules.
  • .pre-commit-config.yaml running ruff lint and format.
  • A lint-and-test job in GitHub Actions that gates the Pages deployment and
    also runs on pull requests.
  • Garmin activity summaries, daily wellness summaries and sleep data for the
    challenge period under data/raw/garmin/.
  • MIT licence with a personal-data exclusion for data/.
  • docs/ with architecture, data-pipeline, deployment, changelog and
    roadmap pages.
  • "Tag release" workflow (workflow_dispatch) that creates an annotated
    tag and a GitHub Release with notes taken from this changelog.

Changed

  • Package moved to src/ at the repository root (with tests/ and
    pyproject.toml beside it) and reorganised by feature
    (activities, weather, weight, dashboard, common, cli) instead
    of by layer (models, parsers, collectors, analysis, export).
  • Raw data moved under data/raw/{garmin,weather,weight}/ with snake_case
    file names; generated files go to git-ignored data/processed/.
  • The dashboard page now lives at src/dashboard/static/index.html
    and GitHub Pages publishes that folder.
  • Code formatted with ruff (line length 100, modern typing syntax).
  • README rewritten as a full engineering guide.

Removed

  • The v2 static page (src/dashboard/static/index.html), the
    run365-dashboard CLI and the data.js payload functions
    (build_payload, payload_to_js, write_data_js, inline_data); the
    React app has reached parity with all nine views.
  • The original Garmin account export folder (profile, consent history,
    social data, golf, Connect IQ, pre-2021 records, raw FIT bundle). Earlier
    tags still contain it; see the privacy note in the README.
  • Generated JSON that had been committed (run365_*_data.json,
    DailyWeightExtract.json).
  • The empty run365days.viz package.

Fixed

  • Vercel deployment: invalid runtime key, PEP 668 pip refusal (uv venv),
    export anchored to the checkout via RUN365_DATA_DIR, function bundle
    size (venv under /tmp, excludeFiles), Flask missing at runtime
    (extras are not installed, so Flask and Strawberry became core
    dependencies) and the module-level app assignment Vercel's function
    detection requires. See docs/deployment.md.
  • run365-activities failed with TypeError: Object of type int64 is not JSON serializable because the coordinate-distance helper returns a numpy
    integer segment count.

Deprecated

  • The v1 scripts are parked in legacy/ for reference and will be deleted
    once develop reaches feature parity.