BikeControl (SwiftControl)
Use Zwift Click, Zwift Play, Shimano Di2, or any Bluetooth controller with MyWhoosh, Rouvy, Zwift, and more. Free to try on iOS, Android, Windows, and macOS.
翻訳待ち
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A real-time sport science dashboard for the University of Florida Football Strength & Conditioning staff, tracking GPS load (Catapult), force plate/strength testing (VALD), and derived metrics (ACWR, load ramp-up, leaderboards, session comparisons, period/drill breakdowns) for the full roster.
Note: An earlier version of this README described a different, planned architecture (Supabase Storage hosting, R "go-live" import scripts, role-based auth). That plan was superseded by what's documented below — this file now reflects the system as it actually runs in production.
main on every pushpages/dashboard.htmlpages/athlete.html| Layer | Technology |
|---|---|
| Frontend | Single-file vanilla HTML/CSS/JS per page, no build step |
| Charts | Chart.js 4.4 via CDN |
| Hosting | Vercel, auto-deploy from GitHub main branch |
| Database | Supabase Postgres |
| Backend logic | Supabase Edge Functions (Deno/TypeScript) + pg_cron scheduling |
| GPS pipeline | Catapult OpenField → webhook → Supabase Edge Function |
| Force/strength pipeline | VALD ForceDecks/NordBord → nightly R script via GitHub Actions |
| Auth | Username-based login via Supabase (not Supabase's role-based auth system) |
LoadMonitoring/
├── pages/
│ ├── dashboard.html ← Main staff dashboard (single large file: HTML+CSS+JS)
│ └── athlete.html ← Athlete-facing login/view
├── scripts/
│ ├── vald_sync.R ← Nightly VALD sync (runs via GitHub Actions)
│ ├── vald_backfill_metrics.R ← One-off historical VALD metric backfill
│ └── create_athletes.mjs ← Admin script for creating athlete accounts
├── .github/workflows/
│ └── vald-sync.yml ← Nightly cron trigger for vald_sync.R
└── README.md ← This file
Note: Supabase Edge Functions (the Catapult integration) live in the Supabase dashboard under Edge Functions — they are not stored in this GitHub repo. See "Supabase Edge Functions" below for what exists and what each one does.
These are managed directly in the Supabase dashboard (Project → Edge Functions), not in Git.
| Function | Purpose | Trigger |
|---|---|---|
catapult-webhook | Core GPS sync. Fires on every Catapult activity update. Writes to catapult_sessions and catapult_period_stats. Captures participation tags. Filters out Catapult's auto-created junk activities (named Activity <digits>). | Catapult webhook subscription |
catapult-athlete-profiles-sync | Pulls each athlete's profile max velocity from Catapult /athletes, writes to athletes.max_velocity_mph and athletes.catapult_athlete_id. | pg_cron, nightly |
catapult-diagnostic | Debug/inspection tool for testing Catapult API responses directly. Not part of the live pipeline. | Manual only |
catapult-sessions-recheck | Re-pulls fresh stats for existing activities into a separate comparison table (catapult_sessions_recheck), used to catch/diagnose sessions that synced with incomplete data. | Manual only |
catapult-period-backfill | One-time historical backfill of catapult_period_stats. Already run. | Manual only |
catapult-tag-backfill | One-time historical backfill of catapult_sessions.participation_tag. Already run. | Manual only |
To check pg_cron job status/history:
select * from cron.job;
select * from cron.job_run_details order by start_time desc limit 10;
| Table | Contents |
|---|---|
athletes | Roster. Includes catapult_athlete_id, max_velocity_mph (synced nightly) |
catapult_sessions | GPS session totals per athlete per activity. Includes participation_tag (e.g. 'Full', 'Rehab') |
catapult_period_stats | Per-athlete, per-drill/period breakdown within each practice session |
cmj_tests | VALD ForceDecks CMJ jump testing data |
nordbord_tests | VALD NordBord hamstring testing data |
catapult_sessions_recheck | One-time comparison table, not used by the live dashboard |
Important: session_date is stored as text (MM/DD/YYYY), not a real date
column. Any SQL sorting/filtering by date must use to_date(session_date, 'MM/DD/YYYY')
or it will sort alphabetically instead of chronologically.
Secrets live in two separate places and must be kept in sync manually — there is no automatic sharing between them:
vald-sync.yml| Secret | Used by | Notes |
|---|---|---|
CATAPULT_BASE_URL | Edge Functions | e.g. https://connect-us.catapultsports.com/api/v6 |
CATAPULT_API_TOKEN | Edge Functions | Generated in OpenField Cloud → Settings → API Tokens. Must have full scope (Summary Data, Sensor Data, Activities, Athletes, Tags, etc.) |
VALD_CLIENT_ID / VALD_CLIENT_PASSWORD / VALD_DUENDE_ID | GitHub Actions (vald_sync.R) | OAuth client credentials for VALD's API |
SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEY | Edge Functions | Server-side Supabase access |
SUPABASE_URL / SUPABASE_SERVICE_KEY | GitHub Actions | Same purpose, different secret store |
Secret values cannot be viewed again once saved — only rotated. If a token needs regenerating, it must be recreated from scratch with the provider (Catapult/VALD) and updated in both places above.
This is the beginning of the README. Read the rest at the original. Read the full README ↗