尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
An advanced-analytics site for one NFL team, built to answer the questions a fan
actually argues about — is my team good, is my quarterback good, how do we compare
to the league, how's the secondary — in a form you can read at a glance rather than
a spreadsheet you have to interpret.
Independent fan project, not affiliated with the NFL or any team. Stats from
nflverse (CC-BY 4.0), FTN charting data,
and public endpoints.檢視完整 README ↗An advanced-analytics site for one NFL team, built to answer the questions a fan actually argues about — is my team good, is my quarterback good, how do we compare to the league, how's the secondary — in a form you can read at a glance rather than a spreadsheet you have to interpret.
Live: foxboro-files.vercel.app
Independent fan project, not affiliated with the NFL or any team. Stats from nflverse (CC-BY 4.0), FTN charting data, and public endpoints.
Eight pages covering team strength, per-game recaps, the upcoming matchup, schedule, roster and position grades, a quarterback deep dive, league-wide standings and every team's unit grades, and news. Units are graded out of 100 against the other 31 teams and ranks read "26th of 32", because "−0.15 EPA/play" means nothing to most people and "26th in the league" means everything. Tap a stat and it lists the plays behind it. After each game, What Stood Out lists up to three genuinely rare things — "the 3rd-best defensive game by any team this season", "the first win over PIT since 2023" — each a fixed check in code with its comparison shown, and nothing at all after an ordinary game.
Three things drive most of the value:
Opponent adjustment. A unit isn't judged on raw production — it's compared against what its opponents do in their other games. Shutting down a normally-explosive offense counts for more than shutting down a team that's bad against everybody. This is the same leave-one-out idea behind DVOA.
Prior-season blending, phased out. Through two games, pure current-season data is too noisy to make forward-looking claims from, so predictive numbers blend real 2025 performance, tapering to zero by game four. Descriptive numbers never blend. Which is which is documented per-page and labelled in the UI.
Honesty about what the data can't do. Free data still can't grade individual linemen or defensive backs — that needs every rep charted, which is PFF's business model. (nflverse's participation data shows who was on the field, not who won the rep, and isn't published until after a season.) So the team-unit cards are named for what they measure (Pass Defense, Pass Rush, Run Defense, Pass Protection) rather than for position groups they don't isolate.
data/generated/. Pages read static files; every stat window is precomputed
at build time. Nothing to provision, nothing to migrate, and the full history of every
number is in git.npm run build:data # fetch → build everything → verify
npm run build:data:skip-ai # same, without the AI narrative step
npm run verify:data # check committed data without rebuilding
npm test # unit tests
npm run calibrate:shrink 2025 # re-measure statistical constants off a finished season
scripts/build-all.ts orchestrates every build step off a single raw snapshot, so no
two outputs can be computed from different fetches. It hard-fails on the data steps and
fails soft on the AI step. Refreshes run on GitHub Actions: news every three hours, and
stats four times across the Sunday–Monday cycle plus daily, timed around when nflverse
finalizes play-by-play. A Sunday afternoon game is reflected on the site in about an
hour, including its generated recap.
Early on, three counting stats were wrong in a way no internal check could catch: the
site's numbers agreed with each other perfectly and didn't match football. A fumble on a
reception was attributed to nobody; fumbles lost were counted instead of fumbles; and
every QB scramble in the league was silently dropped, because nflverse leaves
rusher_id empty on those rows and only populates rusher_player_id.
scripts/verify-data.ts now diffs the site's rushing, receiving, passing, defensive and
kicking numbers against nflverse's own independent aggregation of the same games (QB
lines also against Next Gen Stats), alongside cross-file assertions (team EPA must match
the league rankings file to 1e-9; no fabricated position card may exist) and a check that
every "see the plays" list matches the number it opens from. CI gates on it. It caught a
fourth discrepancy within a minute of being written, and later a fifth: every QB's box
score counted sacks as pass attempts. Because nflverse's totals and Next Gen Stats land a
day after the play-by-play, a source that hasn't caught up is skipped with a notice rather
than failing the post-game refresh.
The same comparison also runs for every team in the league on each refresh
(scripts/league-audit.ts), as an early warning that never blocks. Only New England's
player lines are on the site, so a new kind of unusual play used to surface the first time
it happened in a Patriots game — a lateral in Week 5 froze the site for a day. Run
league-wide, it immediately found two more (an aborted snap credited to the center who
fumbled it, a lateral touchdown credited to the first receiver) that had already happened
to other teams. A player traded mid-season is compared on his combined line across both teams,
since that's what nflverse's season total is. The daily health check emails any mismatch.
The AI writes three things — a recap's short Take, the game preview, and the news digest —
from facts handed to it. Every draft passes narrow checks in code
(scripts/lib/aiChecks.ts), each added because that exact error shipped (a road game
placed in Foxborough, an invented first name, a wrong month). A draft that fails twice
isn't published, every attempt is logged to data/generated/ai-diagnostics*.json, and
each AI block has a "Flag it" link. The daily health check reads that log, so an expired API key — which otherwise just leaves recaps without a Take — emails the owner like any other failure. Everything else, including recap bullets and the
injury report, is computed in code.
scripts/lib/reliability.ts exists because shrinkage wasn't enough.
Regressing every team toward the league mean stops one small-sample team from outranking a well-measured one. It does not stop a ranking that is entirely noise — when the whole league is small-sample, every team is pulled by roughly the same weight, the ordering survives, and the table still looks authoritative.
Two games into the season, the receiver "hands" metric ranked New England 3rd in the league. Testing it properly: the spread observed between teams was smaller than random chance alone produces at those sample sizes — a reliability of 0.00. Flipping a single drop moved them from 3rd to 16th. So the site withholds the rank and shows raw counts until the metric earns one, with hysteresis on the threshold because replaying the completed 2025 season showed a single cutoff made the rank blink on and off week to week.
The same tooling measures the shrinkage constants against a finished season instead of leaving them as numbers picked by feel, and reports that RB and TE efficiency don't stabilize even across a full year — which is why those two cards carry a visible caveat rather than a confident grade.
npm install
npm run dev
The generated data in data/generated/ is committed, so the site runs immediately
without fetching anything. To refresh from source, run npm run build:data.
The AI writing (recap Takes, the game preview, the news digest, the Around the League
headline picker) uses one secret: ANTHROPIC_API_KEY, stored only in GitHub. Vercel
doesn't need it — the AI runs in the GitHub refresh jobs, and Vercel serves the finished
files. If the key expires or is deleted, nothing turns red and the site keeps its last good
text, but the daily health check opens an issue saying "API key rejected (HTTP 401)…
Replace ANTHROPIC_API_KEY" (first used for real on Oct 16, 2026).
ANTHROPIC_API_KEY → Update.