OpenAthlete
AGPLv3 기반 지구력 훈련 플랫폼—EU 호스팅, 투명한 로직, 자체 호스팅·전체 내보내기 지원
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A private NFL pick'em league for friends: a modern, animated take on Yahoo Pick'em.
Stack: TanStack Start (React 19, TanStack Router + Query), Tailwind CSS v4 + shadcn/ui, Motion, Supabase (Postgres with row-level security + magic-link auth), deployed on Vercel. NFL schedule, scores and spreads come from ESPN's public scoreboard feed.
npm install
cp .env.example .env.local # fill in Supabase values
npm run dev # http://localhost:3000
Other scripts: npm test (Vitest), npm run check (Biome), npm run build.
Database: run each file in supabase/migrations/ in order in the Supabase SQL editor. 0005_profile_flair.sql also creates the public avatars storage bucket for uploaded profile photos. 0029_custom_emoji.sql creates the public emoji bucket for custom reaction emoji. GIFs in comments need a free GIPHY API key (developers.giphy.com) set as GIPHY_API_KEY in Vercel.
Auth redirect: in Supabase > Authentication > URL Configuration, set the Site URL to your Vercel URL and add http://localhost:3000/** and https://<your-app>.vercel.app/** as redirect URLs.
Vercel: import the repo and set VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY, SUPABASE_SECRET_KEY and CRON_SECRET (any random string).
Pick reminder emails (optional): they're sent from a Gmail account. Turn on 2-Step Verification for it, create an app password, and set GMAIL_USER (the address) and GMAIL_APP_PASSWORD in Vercel. In GitHub, add the repo secret CRON_SECRET (same value as Vercel) and the repo variable APP_URL (your Vercel URL); the Pick reminders workflow then runs hourly.
Sign-in emails: Supabase's built-in email sender only delivers to your own Supabase team's addresses (and a couple an hour), so friends' sign-in emails won't arrive without your own SMTP. In Supabase > Authentication > Emails > SMTP Settings, turn on custom SMTP with host smtp.gmail.com, port 465, your Gmail address as username and sender, and the same app password. Then replace the Magic Link email template (subject Your Air Bud Pick'em sign-in link) with:
<h2>Sign in to Air Bud Pick'em</h2>
<p><a href="{{ .RedirectTo }}&token_hash={{ .TokenHash }}&type=email">Sign in</a></p>
<p>Or type this code on the sign-in page: <strong>{{ .Token }}</strong></p>
<p>If you didn't ask for this, ignore this email.</p>
The link goes straight to the app (not supabase.co), which spam filters like better, and it works in any browser. The code covers the home-screen app. Friends should mark the first email "Not spam" and add the sender to their contacts.
Backups (recommended): add the repo secret SUPABASE_DB_URL (Supabase > Connect > Session pooler string, with your database password). The Database backup workflow then saves the app's tables every Tuesday as a downloadable artifact.
games table (at most once a minute), and a daily Vercel cron hits /api/sync.locked_spread; ATS scoring only uses that value.Pick reminders GitHub Actions workflow calls /api/reminders hourly. When a game day's first kickoff is 3 hours out or less, everyone with open picks that day gets one email (or, if they chose Discord DMs on their profile, shows up in the bot's /api/bot/reminders). reminder_log keeps it to one email per person per game day. Running the workflow by hand defaults to a dry run.src/lib/scoring.ts: scoring for all three modes (tested)src/lib/nfl/espn.ts: ESPN scoreboard provider (tested)src/lib/standings.ts: season and weekly standings (tested)src/lib/flair.ts: standings badges, streak flame, and last-place trophy (tested)src/lib/reminders.ts: when pick reminders are due and their wording (tested)src/server/: server functions for auth, leagues, picks and the game syncsupabase/migrations/: tables, security rules, and the create/join league functionssrc/routes/: home, sign in, my leagues, new league, league (picks + standings), invite linkssrc/routes/api/bot/: read-only JSON API for a Discord bot (games, picks after kickoff, who still needs to pick, standings); see docs/bot-api.mdMilestone 1: sign in, create and join leagues, weekly picks for all three scoring modes, and standings.