↑↓move ↵open escclose Players, teams and this week's games · type a position like "rb" for the list

Players, teams and this week's games. Type a position like "rb" for the list.

Releases

2.0.0

All releases, newest first

For you

  • Every page of the site is rebuilt from one set of design boards: the game pages, the rankings, the team pages, the player pages, the track record, and the site and tool pages. The value rankings that lived at /rankings/value/ are now the league chips on /rankings, and an old link takes you there.
  • Before kickoff, a game's page shows our call, the projected score and margin with its range, a chart of how our number moved from run to run, each club's last three results, how often our calls at that percentage have hit, and the injuries and players already in the model. After the final it adds the score by quarter, the five biggest moves in our reading during the game, each player's actual fantasy points with the top three performers, and the market's closing margin and total, labelled as the market's and never as ours.
  • While a game is being played, its page updates in your browser: the score, the score by quarter, our win probability charted through the game, where it stands, and the swings and leaders so far. A page you opened before kickoff turns live by itself, and at the final it reads as the page built after the game does. A game with no live feed says so and reads KICKED OFF; a feed that has sent nothing for three minutes is marked stalled while the page keeps reconnecting, less often the longer it waits; a game that went to overtime, a tie, and a game we published no call for each have a page of their own.
  • The rankings open on one list across positions, ranked by value: a player's projection minus the last starter at his position, in a 12 team 1QB, Superflex, 2QB or Flex league, with each range drawn on one scale. The QB, RB, WR and TE pages add projected stats, the change since the last run and the injury report's status, and switch between standard, half PPR and PPR scoring. Twelve rows show first and the rest load 25 at a time.
  • A star saves a player, up to 40, on this device only. My players lists them with the best lineup they make in the league you choose and who sits on the bench. Start or sit compares two players on the rankings page, and up to three at /compare, with their ranges on one scale and a sentence on why.
  • The rankings, the position pages, /compare and search show a run exactly as it was published; the site ranks and values no one again. An edition published before projections froze at kickoff projected a player again after his game began, so it leaves those players out of all of them and out of the players ranked around a player, and the numbering keeps its gaps; everyone else shows exactly as that edition published them. On the rankings and at /compare a sentence below the run stamp says how many players are shown from before kickoff or left out, and where the players ranked around a player leave any out, its panel says so.
  • Each player page shows this week's projection with its floor and ceiling, how sure it is, his projected stats in each scoring format, our record on him week by week against the box score, the rest of his season, how his rank moved from run to run, the players ranked around him, and his club's context. A questionable player, a player we did not project this week and a rookie projected from earlier rookies each have their own state, and an injury report filed after the projection is dated as such.
  • Each team page carries the club's record, its rating with a chart of the rating through the season and a table of the same numbers for screen readers, the schedule with our call on each game, the games still to play, the standings, the injury report, this week's key players and the season so far. The roster has its own page, linked as Depth chart. The teams index lists all 32 clubs by division in rating order, each with its record and next game. Playoff chances, projected wins and injury impact say they are not published yet.
  • The track record opens on its headline tiles, then how closely our percentages matched the results, the season week by week, how often the final margin landed in our range, and the player projections, with every call listed and tabs to filter and order them. Every week with calls has a page of its own, playoff weeks included, and each season's calls download as a CSV beside a copy of the published track record file. When the record cannot be verified the page shows the last verified one, and before anything is scored it shows last season's.
  • About, Data, How to read, Privacy, Accessibility and this changelog are rebuilt, and the changelog has an RSS feed at /changelog.xml. A schedule at /schedule/ lists each week's games with our call, and exports the week as a CSV or a calendar file. A status page at /status shows what is published and when. An archived run's page shows that run exactly as published and says it has been superseded.
  • A link to a game page shares an image of our call: the split, the margin and its 9 in 10 range. A link to an archived run's game shares a receipt of what that run said, with the final once there is one, and the track record shares its season's last nine scored calls.
  • Amber warning text, such as Questionable and the imputed rookie marker, now reaches the 4.5 to 1 contrast minimum against the page and the cards in both themes; in light mode it had measured 1.75 to 1. Hovering a filled button, such as Start or sit, no longer makes it vanish.
  • Small controls are easier to tap. The phone header's search, theme and menu buttons are 44px tall, and the save stars, load more, clear all, export, Hide and Explain take taps beyond their drawn size.
  • Between 841 and 1199px wide, the game chart cut off its fourth quarter and the final; it now scales to fit its box. At 320px the score by quarter and the phone players table no longer push the page sideways.
  • The header on a phone is one row now, 56px tall and pinned to the top of the screen as you scroll: the mark, search, the theme control and a menu control. The four sections of the site used to wrap to a second row and then scroll sideways, so on a 320px screen the longest of them sat off the side of the screen behind a swipe nothing announced.
  • The menu control opens a sheet with those four sections in it, Games, Rankings, Teams and Track record, the one you are reading marked, each with a short status: the week for Games, QB RB WR TE for Rankings, 32 clubs for Teams, and how many of our scored calls have hit for Track record. Below them sit search, a Dark, System and Light choice, and links to the data sources, privacy, accessibility and this changelog. Escape closes it, so does a tap on the dimmed page beside it, and the keyboard stays in the menu while it is open rather than wandering onto a page you cannot see.
  • On a phone the theme control is one moon button in the header that steps through dark, system and light and says which is on, and the menu sheet carries all three as a row. It used to draw all three of its icons at once, the moon, the monitor and the sun, which pushed the rest of the header off the side of a 360px phone.
  • The footer now carries the whole site. On a wide screen the mark and a sentence saying what Sporacle publishes sit on the left, and three columns of links on the right: Product, this week's games, the rankings, teams, the track record and My players; Method, how we score ourselves, our publishing rules, engines and runs, data sources and the changelog; and Site, about, contact, privacy, accessibility and the status page. Below a rule sit the freshness dot with the time and id of the run the page was built from, the version, the copyright and a note that we are not affiliated with the NFL. A phone shows a shorter set of the same three columns. It used to be a disclaimer and three links. There are no social links, because there is no account to send you to.
  • IND at PHI, a week 14 game, showed 40% and 61% on its game page, the week 14 games list and its archived week 2 edition, because each side was rounded on its own. That edition now reads 40% and 60%, and no pair the site prints can sum to 101 any longer. The published probability underneath is unchanged.
  • After a score, a game's live percentage used to go blank for typically about five minutes, until the next snap. The live number now carries on through those minutes: after a score it is the model's reading of the kickoff that comes next, received by the team the rules give it to. At halftime it is the model's reading of the kickoff that opens the second half, received by the team that kicked the opening kickoff, which is the usual outcome, though a team can choose otherwise. In some moments there is still no live number until the next snap, for example between a touchdown and its extra point, once the ball has been kicked, and on a score the rules cannot read, such as a return on a try or a two point score the feed cannot tell from a safety.
  • A game's forecast and its players' projections stay fixed once the game kicks off, whatever kind of run follows. A player's points in every scoring format, his floor and ceiling and his projected stats stay the ones we published before the kickoff, and the ranks and value lists are worked out around them. A player with no projection published before his kickoff is left out, rather than given one made after his game started. Once a game kicks off, every number on a player page is the one that stood at kickoff, and a final game's players panel and a team page's key players show that same projection. Where no run was published before the kickoff, they say Not published yet. The track record's biggest misses label each player with his rank in that same run, and with no rank where none was published before his kickoff.

Under the hood

  • The live Worker answers a new route, /live/games/<schedule game id>/history: the same reading history, keyed by the schedule's game id, with the same rate limit, disclaimer and CORS. The id is checked against a strict pattern before any database read, a page holds up to 500 readings, and a history that ends in a final reading is cached for an hour. It adds no table, migration, secret or write path.
  • Each rebuilt page is measured against its design board on every pull request that touches the site: every drawn box within 4px of the board, and the pixels against a baseline recorded when the page was approved. A browser test also fails on overlapping text or sideways scroll at 1200, 1024 and 375px wide.
  • Share images are drawn at build time from the same boards. One that fails falls back to the generic card and never stops the build, and a check fails the build if any page names a share image that is not there.
  • The data fetch also keeps each week's first run and the run that stood before each kickoff, so the site can read what was published before a game began; nothing on the site ranks or values a player again.
  • Stylesheets are capped per page family instead of as one site wide total, because a page loads only the shared sheet and its own family's.
  • The menu sheet draws its own copy of the four routes, as the phone board draws them, beside the bar's: below 52.5rem the bar's routes are hidden and above it the sheet is, so a keyboard meets the routes once at any width. While the sheet is open the bar and the sheet together are a named dialog, which is the same boundary the scrim draws and the same one focus is held inside.
  • Each route's status in the sheet is read from what is published, the pinned run's week and the track record's calls, tallied the way the track record page tallies them, with a tie a miss and an ungraded call left out; Rankings and Teams carry fixed text. A status with nothing published behind it is left out rather than filled.
  • The header's script now rides in one module beside the search dialog's, and its scoped styles moved to the shared stylesheet. An Astro script owned by one component is copied into every page that renders it, and a scoped style block buys itself an attribute on every element that component draws, which together came to about 1.6KB a page when that was measured, against the attribute marker S11 has since replaced with a cheaper one: that is what paid for the sheet inside the page budget.
  • Every element that pins itself to the top of the window reads a shared --sticky-top, so none of them draws behind the pinned bar. Two tests hold it: every stylesheet and every component is scanned for a rule that pins its top without reading that property, sticky or fixed and the inset shorthand included, and a browser sweep measures ten routes at a real scroll position. A rule that genuinely does not need the offset says why in its own comment, and there are three, the skip link, the search dialog and the styleguide's own navigation.
  • The header, the theme control, the menu sheet and the search dialog carry no scoped stylesheets; their rules live in the shared chrome stylesheet, because an Astro scoped style block buys its rules with a scope class on every element the component renders, on every page that renders it. A source test holds it for the bar's components.
  • A site test whose assertion fails on a page element now reports the failure instead of hanging its file, and a source test fails on the form every one of them took, a page lookup compared directly; it does not catch an element held in a variable or inside a list. Gate 1's jobs carry a time limit, so a hang ends in minutes rather than holding a runner for six hours. The private MCP server's stalled store test checks its five second bound on a fake clock, so a busy machine can no longer fail it.
  • A game in progress whose live feed reports no possession, which it does after every score until the next snap and all through halftime, no longer has our pregame number stored or served in place of a live reading; where the rules of the game do not settle the next state it serves no live number and stores nothing. About a quarter of week 3's in game readings were that pregame copy; the ones already stored stay exactly as they are, still labelled prior.
  • Those kickoff readings are labelled model, with the detail live-0.1.0 kickoff, so the live API and the stored history say which readings were made on a kickoff rather than on a snap the feed reported: after a score the rules fix who receives it, and at halftime the receiver is taken to be the team that kicked the opening kickoff, the usual outcome though a team can choose otherwise. Who kicked the opening kickoff comes from the first play of the game's own drive log, read when the game reaches halftime, up to three times until one succeeds; nothing else in that log is read.
  • Each player's fantasy points in every finished game are now published beside the schedule, in all three scoring formats, and they are the same points our projections are scored against. A player with no recorded stats in a game is left out rather than given a zero. The game pages, the player pages and the archived rankings read them.
  • The closing market figures for every finished game, the margin and the combined points the market settled on, are now published in a file of their own, labelled as the market's and kept apart from everything our model reads or publishes. A figure is published only when it was read after the game ended, so nothing published is a number from before kickoff. The game pages, the schedule and the track record read them.
  • The twice daily data refresh now also rebuilds the table those market figures come from, which had been rebuilt by hand and was weeks old. A failure there is logged and never stops the rest of the refresh.
  • The track record now scores projections through the same function that publishes those fantasy points, so the two can never disagree about a player's total.
  • The freeze runs in every run kind, the weekly full run included, on the same clock and the same kickoff times, so a game and its players never disagree about whether it has started. A kicked off club's rows are the ones published by the last run before its kickoff: read from the newest publication when that one can vouch for them, otherwise from the published runs the forecast container restores. A run that cannot read what to carry refuses to publish, and so does one whose restore came back incomplete when it needs those runs.
  • Each run publishes player_freeze.json beside the rankings, naming every player whose row was carried forward and the run that published it; the rankings file keeps its shape. The site fetches and validates the new file, and a run whose run.json lists it is known to freeze players, even where the file itself is not on disk or cannot be read. The restore that brings the newest publication back now brings its rankings and that file too, even when the season listing fails.