OpenAthlete
AGPLv3 endurance training platform: EU-oriented hosting, transparent CTL/ATL/TSB logic in code, self-hosting, and full export. Built in Grenoble.
Weighted-ball velocity tracker for pitching athletes
Translation pending
Sports & fitnessTypeScript · PLpgSQLGitHub @colethomas5280-sudoOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Weighted-ball velocity tracker for pitching athletes — mound and pull-down,
4 throws per ball weight (box 1 = 80% primer, not scored; boxes 1–3 = 100%),
PR / average / floor per weight, the two pull-down 5 oz sets folded into one
combined 5 oz record, dated session history, a progress chart, and "last / PR"
targets on every weight while entering.
The coach manages everyone. Each athlete logs in with their own email +
password and sees only their own tracker; they can log their own sessions.Read the full README ↗Weighted-ball velocity tracker for pitching athletes — mound and pull-down, 4 throws per ball weight (box 1 = 80% primer, not scored; boxes 1–3 = 100%), PR / average / floor per weight, the two pull-down 5 oz sets folded into one combined 5 oz record, dated session history, a progress chart, and "last / PR" targets on every weight while entering.
The coach manages everyone. Each athlete logs in with their own email + password and sees only their own tracker; they can log their own sessions.
DATABASE_URL (Supabase, Vercel Postgres, Neon, …)COACH_EMAILS, plus the shared COACH_PASSWORD.Push to GitHub, then vercel.com → Add New → Project → import the repo → Deploy.
[YOUR-PASSWORD].
Percent-encode any special characters (! → %21).Vercel → Settings → Environment Variables (all environments checked):
| Name | Value |
|---|---|
DATABASE_URL | the Supabase Transaction-pooler URI |
AUTH_SECRET | run openssl rand -base64 33 and paste it |
AUTH_URL | your deployed URL, e.g. https://velo-ladder.vercel.app |
COACH_EMAILS | your email (comma-separated for multiple coaches) |
COACH_PASSWORD | the shared coach password — pick something strong |
SETUP_KEY | any random string — used once in step 5 |
Deployments → ⋯ → Redeploy so the variables take effect.
Visit https://YOUR-URL.vercel.app/api/setup?key=YOUR_SETUP_KEY&seed=1
→ should return {"ok":true,...}.
Open the site → sign in with your email + COACH_PASSWORD → Manage roster to
add athletes → give each athlete their email + password.
npm install
cp .env.example .env.local # USE_PGLITE=1 is set — no database to install
# put a value in AUTH_SECRET and COACH_PASSWORD
npm run dev
Then hit http://localhost:3000/api/setup?key=dev-setup-key&seed=1 once.
Sign in with COACH_EMAILS + COACH_PASSWORD from your .env.local.
npm run build — production builddb/schema.sql — the schema (applied automatically by /api/setup)app/
page.tsx coach/athlete dashboard (gated by session)
login/ email + password sign-in
api/
auth/[...nextauth] Auth.js (credentials provider)
me { role, email } for the current user
athletes, athletes/[id] roster (coach) + own record (athlete)
athletes/[id]/sessions list / create sessions
sessions/[id] edit / delete a session
setup one-time schema + seed (SETUP_KEY-guarded)
lib/
velo.ts pure tracker logic — weights, groups, PR/avg/floor, CSV
auth.ts Auth.js credentials provider (coach password + athlete bcrypt)
scope.ts coach | athlete(ids) | none, resolved from the session email
data.ts typed Postgres queries + password hashing
db.ts node-postgres (prod) / PGlite (local, USE_PGLITE=1)
schema.ts canonical SQL
components/ React UI (Tracker, EntryForm, RecordsPanel, ProgressChart, …)
Every API route checks authorization: a coach can read/write all athletes; an athlete only their own; anyone else gets 403.
next, react, react-dom and next-auth are pinned to exact versions with
no ^. The rest carry a caret, which is fine for packages that keep semver.
next-auth is pinned for a different reason and should stay that way. It is
a pre-1.0 prerelease (5.0.0-beta.32), and prerelease numbers carry no
compatibility promise — beta.33 is free to break beta.32. A caret would also
have spanned into a stable 5.x:
^5.0.0-beta.32 accepts beta.33 … 5.9.9 (a breaking release is inside the range)
5.0.0-beta.32 accepts beta.32 only
Deploys were never at risk, because Vercel installs from the committed
lockfile. The exposure was someone running npm install or npm update
locally and picking up a new version by accident — and this package decides
whether anyone can sign in, so a break there locks out the coach too.
Upgrading it is fine, but do it deliberately: bump the pin on its own, then
sign in as a coach and as an athlete before pushing. Athlete login is the
better check, since it queries the database while the coach path only compares
COACH_PASSWORD from the environment.