尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Pick every game of the NFL Season through the Super Bowl. Compete with friends. Have a great time.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Pick every game of the NFL season through the Super Bowl. Compete with friends. Have a great time.
Each game takes one pick — who wins, and roughly by how much — and the leaderboard scores the winner as results come in. Your picks also build your own version of the season: division and conference standings resolved with the league's real tiebreakers, and a 14-team playoff bracket seeded from them.
Live at https://nfl-season-predictions.vercel.app/.
Weekly picks. Pick a winner and roughly how big the margin will be. Point spreads are shown beside each side as context but are not pickable. Picks lock at each game's kickoff, enforced on the server.
Leaderboard. One point per game whose winner you called, plus one more where the margin bucket landed. Filterable by week or season to date.
Postseason bonus. Your bracket is paid per club that actually reached each round, doubling as it goes — 2 for the field, 4 divisional, 8 conference championship, 16 Super Bowl, 32 for the champion. A club you had going all the way is worth 62; a perfect bracket is 156, against 544 for a flawless regular season. The real bracket is derived from ESPN's postseason schedule, not entered by hand.
All five numbers live in POSTSEASON_POINTS in lib/seasonScore.ts and are
the whole tuning surface for how much January matters — everything else,
including the on-page copy, is derived from them.
Standings. Division and conference tables from your picks, or from the real results, with the league's published tiebreaking procedure applied and the deciding step named wherever one was actually needed.
Playoffs. Four division winners and three wild cards per conference, a bye for the top seed, and a divisional round that reseeds the way the real one does.
Provision Postgres and put the connection string in DATABASE_URL. On Vercel:
Storage → Create → Neon, then vercel env pull .env.local to get it
locally. A pooled endpoint is what you want; lib/db.ts already sets
prepare: false for it.
npm install
cp .env.example .env.local # fill in DATABASE_URL and AUTH_SECRET
npm run db:migrate
npm run seed:teams
npm run seed:schedule
db:migrate applies lib/db/schema.sql, which is idempotent — re-running it
is safe and is how schema changes are rolled out.
In the Google Cloud console, create an OAuth 2.0 Client ID (Web application) and add both redirect URIs:
https://nfl-season-predictions.vercel.app/api/auth/callback/google
http://localhost:3000/api/auth/callback/google
Put the client id and secret in AUTH_GOOGLE_ID / AUTH_GOOGLE_SECRET, and
generate AUTH_SECRET with openssl rand -base64 32.
Set every variable from .env.example in the Vercel project, then push. The
cron in vercel.json pulls fresh scores and lines daily; it authenticates with
CRON_SECRET and refuses to run without it.
The daily cron syncs a window of weeks — the previous one (a Monday night game finishes after the week has rolled over, and ESPN sometimes corrects a score after the fact), the current one, and the next two, which is roughly how far ahead lines are posted.
To repair something by hand:
curl -X POST "$URL/api/admin/sync?what=teams" -H "x-admin-secret: $ADMIN_SECRET"
curl -X POST "$URL/api/admin/sync?what=week&week=3" -H "x-admin-secret: $ADMIN_SECRET"
A whole season is 18 sequential ESPN calls and will usually exceed the
60-second function limit, so run that from a terminal instead:
npm run seed:schedule.
Rules code fails silently — it produces a plausible order that happens to be wrong, and nobody notices until a division is decided incorrectly in December. So there is a check that replays a finished season through the same functions the app uses and diffs the result against ESPN's own seeds:
node --import tsx scripts/verify-tiebreakers.ts 2025
Both 2025 and 2024 come back 14/14. Those two seasons happen to cover the cases
that actually exercise the rules: an 8-9 division winner seeded above two 12-5
wild cards, two 11-6 division winners split by a tiebreaker, a 9-7-1 club with
a real tie, and three 10-7 clubs competing for two wild-card spots. Run it
after touching anything in lib/tiebreakers.ts or lib/playoffs.ts.
Two steps of the published procedure are deliberately not implemented, and both are documented at their position in the list rather than silently skipped: net touchdowns (a pick records a margin bucket, not a box score) and the final coin toss, replaced by a stable alphabetical order so a page does not reshuffle itself between visits.
ESPN's public endpoints — schedule, kickoff times, live scores, logos, team
colours and DraftKings point spreads. There is no free official NFL feed, so
lib/espn.ts reads every field defensively and a shape change degrades rather
than throws.
The spread's sign is verified against ESPN's favourite flags rather than trusted. Nothing is scored against the line, but "Fill week" defaults from it, so a mis-signed line would hand every auto-filled game to the wrong team.
lib/espn.ts ESPN client
lib/ingest.ts upserts ESPN data into Postgres
lib/standings.ts tallies results into records and points
lib/tiebreakers.ts the league's published tiebreaking procedure
lib/playoffs.ts seeding and the reseeding bracket
lib/grade.ts how one pick settles (pure -- the client imports this)
lib/seasonScore.ts scoring constants and the postseason bonus (pure)
lib/postseason.ts real bracket from the DB, predicted bracket per user
lib/scoring.ts leaderboard totals
lib/queries.ts everything else that touches the database
lib/grade.ts is split out from lib/scoring.ts on purpose: the pick UI is a
client component and needs the same settlement rules, and importing them from
the scoring module pulled the Postgres driver into the browser bundle.
Not affiliated with or endorsed by the National Football League. Team names and logos are trademarks of their respective owners. Point spreads are shown for reference only — nothing here takes a wager.