A structured training log and analytics platform for competitive track & field throwers
Session tracking, progress visualization, competition management, and landing zone analysis — all running locally in the browser.
Throwing events generate structured, repetitive data — distances, attempt sequences, session RPE, landing zones, competition results. Every practice and every meet produces numbers that should compound into insight over a season. In practice, they don't.
Most throwers track marks in the Notes app, a spreadsheet they abandon after two weeks, or not at all. Coaches collect data on paper heat sheets that never get digitized. Competition day means scribbling six attempts in the margins. By the time anyone asks "how has your shot put progressed since October?", the answer is a guess.
ThrowingTracker was built to solve these specific problems.
- Fragmented Training Data: All sessions, marks, RPE, notes, and media are consolidated into one interface. Every throw is searchable and organized chronologically by event type.
- No Progress Visibility: Line charts, bar charts, and RPE overlays reveal trends and plateaus that would otherwise remain hidden.
- Competition Day Is Manual: Meet Day Mode tracks six attempts, fouls, and live bests with a minimal, distraction-free interface and animated PB celebration alerts.
- Landing Zone Patterns Are Invisible: Canvas-based sector diagram plots multi-session scatter to reveal directional tendencies.
- Video Review Requires Expensive Software: Slow-motion playback, frame-stepping, and drawing annotations included — all stored locally in IndexedDB.
- Data Is Locked In or Lost: Export to JSON or CSV anytime. No accounts, no subscriptions, no cloud lock-in.
- Fully Local Architecture: Runs entirely in the browser. PWA-ready and offline-capable.
-
Clone the repository
git clone https://github.com/Waleee7/ThrowingTracker.git
-
Navigate into the project directory
cd ThrowingTracker
-
Install dependencies
npm install
-
Start the development server
npm run dev
-
Open the app in your browser
Visit: http://localhost:3000
Complete the short onboarding flow to set your name and events.
Install on your phone: open in Safari or Chrome → tap "Add to Home Screen" → runs offline in full-screen mode.
Deploy: connect to Vercel or build with npm run build and deploy /out to any static host.
| Dashboard Stats grid, PB cards, streak counter, compact achievement badges. |
Session Logging Event selection, individual throws, RPE, notes, media attachments. |
Meet Day Mode Six attempts, mark/foul entry, live best, animated PB alerts. |
Progress Charts Line charts, weekly volume bars, RPE overlays. |
| Landing Zones Canvas sector map with multi-session scatter analysis. |
Video Analysis Slow-mo 0.25x–1x, frame stepping, annotation overlay. |
Personal Bests Auto-calculated all-time & season PBs, animated alerts. |
Achievements 16 badges across milestone, streak, competition, volume, special. |
| Data Export JSON for backup, CSV for spreadsheets, JSON import merge/replace. |
Dark Mode Full dark theme with proper contrast throughout. |
PWA Offline-ready, installable on phone, optimized manifest & SVGs. |
Onboarding 3-step first-time flow — under 30 seconds to first session. |
Shot Put — Discus — Hammer — Weight Throw — Javelin
Multi-event athletes can track all events with separate PBs, progress charts, landing patterns, and achievement recognition.
16 unlockable badges: Milestone, Streak, Competition, Volume, Special. Toast notifications appear on unlock. Examples:
- Milestone: First Throw, 50 Sessions, Century Club
- Streak: 7-Day, 14-Day, 30-Day Iron Streak
- Competition: First Meet, Meet Warrior, PB in Competition
- Volume: 500 Throws, 1K Club, 5K Throws
- Special: Multi-Event Athlete, Full Season Tracker
v3 rebuilds the visual system around a TV-broadcast athletics aesthetic: a dark-ink default register with a rationed electric-lime accent, Fraunces display headlines, JetBrains Mono data/eyebrows, and big tabular stat numbers. Personal bests read as the live signal (lime), every event has its own identity hue, and the dashboard, onboarding, and Season Wrapped are anchored by cinematic, baked-in imagery. A clean paper register is one tap away. The whole thing is token-driven (Tailwind v4 @theme), so light/dark stay in sync and the palette lives in one place.
| Framework Next.js 16 with App Router, serverless coach route, Vercel integration. |
Language TypeScript strict mode, type safety across data & analytics. |
UI React 19, component architecture, hooks for state management. |
Styling Tailwind CSS v4 token system (Broadcast Sports Editorial), dark-first + paper registers. |
| Charts Recharts — line, bar, composed charts. |
Canvas HTML5 sector map & video annotation overlay. |
Video HTML5 Video API, slow-mo, frame stepping. |
Storage localStorage + IndexedDB, fully offline-capable. |
- throwingProfile: name, height, weight, events, notes (localStorage)
- throwingSessions: all session & competition logs (localStorage)
- throwingDarkMode: theme preference (localStorage)
- IndexedDB media-store: videos/images as binary data
Export regularly. Clearing browser data will permanently delete all stored info.
src/
├── app/
│ ├── layout.tsx
│ ├── page.tsx
│ └── globals.css
├── components/
│ ├── DashboardTab.tsx
│ ├── LogTab.tsx
│ ├── HistoryTab.tsx
│ ├── ProfileTab.tsx
│ ├── MeetDayMode.tsx
│ ├── ProgressChart.tsx
│ ├── SectorMap.tsx
│ ├── ThrowScatter.tsx
│ ├── VideoPlayer.tsx
│ ├── AchievementBadges.tsx
│ ├── AchievementToast.tsx
│ ├── PRAlert.tsx
│ ├── Onboarding.tsx
│ ├── Icons.tsx
│ ├── TabButton.tsx
│ └── FloatingElements.tsx
├── lib/
│ ├── types.ts
│ ├── constants.ts
│ ├── storage.ts
│ ├── analytics.ts
│ ├── personal-bests.ts
│ ├── achievements.ts
│ ├── export.ts
│ └── media-storage.ts
└── hooks/
├── useProfile.ts
└── useSessions.ts
Pull requests welcome! Contributions from throwers who code, developers working with athletes, or open-source enthusiasts are appreciated. Areas include cloud sync, additional events, accessibility, internationalization, and test coverage.
MIT — see LICENSE