OpenAthlete
AGPLv3 endurance training platform: EU-oriented hosting, transparent CTL/ATL/TSB logic in code, self-hosting, and full export. Built in Grenoble.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A free, simple diary for the tennis you watch: explore the story of any tour-level singles match since 2003, star the ones you care about, read your saga back, look up the records in Statistics, and play with models of the numbers in Interact. Live at courtsaga.com.
main.drizzle/.scripts/import-matches.ts.| Path | What it is |
|---|---|
app/page.tsx, app/hero*.tsx | The landing page. Its demos run on a sample log and save nothing. |
app/demos/ | The sample log and its hand-checked rivalry records, for the demos only. |
app/diary/ | The log, ranking and saga, used by both the demos and real diaries. library.ts holds the shared types and rules, books.ts the saga's rules, store.tsx the state and saving, and finder.tsx match search. |
app/(app)/ | The app's pages (/explore, /saga, /statistics, /interact, /account) and the server actions that keep a diary. Explore opens signed out only for a shared match, with nowhere to go from it. |
app/diary/records.ts, lib/records.ts | Statistics: every board's rules, and the loader that reads a tour's matches and builds them. The pages are prerendered and rebuilt daily. |
app/diary/models.ts, lib/models.ts | Interact: models fitted to a tour's matches (the top 10 at any moment, upset odds, Elo ratings across eras, serving, big points under pressure, ages), and the loader that fits them. Built ahead of time and rebuilt daily, like Statistics. |
app/(auth)/ | Sign up and log in. |
app/s/[slug]/ | A shared saga: read-only, kept out of search engines. |
app/api/ | Better Auth's endpoints and GET /api/search. |
lib/ | Accounts (auth.ts), diary and search queries (diary.ts). |
db/, drizzle/ | The schema and database client, and the migrations generated from them. |
scripts/ | migrate.ts and import-matches.ts. |
proxy.ts | Sends signed-in fans from / to their log, and everyone else from diary pages to log in. |
npm installunaccent and pg_trgm extensions. A Neon branch works, and so does
local Postgres 15 or later..env.example to .env.local and set DATABASE_URL and BETTER_AUTH_SECRET
(openssl rand -base64 32).npm run db:migrate creates the tables.npm run import:matches -- ~/Desktop/courtsaga/tml-data loads the matches, in about ten seconds.npm run dev, then open http://localhost:3000.The import reads YYYY.csv (ATP) and YYYY_wta.csv (WTA) from a folder, every row of every year it
finds. The CSVs are never committed.
2026.csv and 2026_wta.csv in the folder and run the import again. No code
changes.tour_tourneyId_round_winnerId_loserId (for example atp_2025-540_F_S0AG_A0E2). They
never change between imports, because diary entries point at them.tourney_date is a tournament's first day, so a match's month is estimated from how far into
the event its round falls. The season always comes from the file name.The data is TML-Database (non-commercial use) built on Jeff Sackmann's tennis data (CC BY-NC-SA 4.0). CourtSaga credits both in its footers. Keep the site non-commercial (no ads, no paid tier) unless you get permission, and don't publish the raw data.
A push to main deploys to production. Vercel runs npm run vercel-build, which applies any new
migrations before next build. That only happens on production builds; previews skip it, so a branch's
migrations never reach the production database before it's merged. Every setting is in .env.example.
| Script | What it does |
|---|---|
npm run dev / build / start / lint | The usual Next.js commands. build needs no database, but without one the prerendered pages (the landing page's demo and Statistics) say the match data isn't available. |
npm run db:generate | Writes a new migration to drizzle/ after a change to db/schema.ts. |
npm run db:migrate | Applies migrations to DATABASE_URL_UNPOOLED (or DATABASE_URL). |
npm run import:matches -- <folder> | Loads or refreshes the match data. |