NBA Feed
팀 뉴스와 경기 정보를 제공, 점수는 직접 확인할 때까지 숨겨져 있습니다
테니스 경기 이야기를 탐색하고 관심 경기·선수를 별표해 공유 스토리를 만들며 기록을 확인
Explore the story of any tennis match, star the ones you care about to build your own shareable story, and look up the records behind them. Launching before the 2027 Australian Open.
스포츠·피트니스TypeScript · CSSGitHub @isaacslavens-beep온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 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. |