Wax PackCase study · Oct–Nov 2026
A fun project

Gretzky ’82 and Lemieux ’89 on the same roster

Wax Pack is a set of salary-cap sports sim games built from one memory of a 2006 browser game. It went from "can we make a nicer version of this?" to four live games, one shared account and 52,009 draftable NHL seasons, built in a running conversation with Claude Code and shipped to Cloudflare as it went.

Hockey player-seasons52,009
Baseball player-seasons7,728
Live games4· 1 account
League sizes8 · 16 · 32
Trade deadline30sec
The itch

A game worth paying too much for

Around 2006, WhatIfSports ran a hockey sim league. You were general manager and coach: draft players from any season in NHL history under a salary cap, set your lines, and watch an 82-game season play out in box scores and play-by-play.

The hook was the butterfly effect. Every player-season was its own card with its own price, so with careful cap math you could put peak Gretzky and peak Lemieux on one bench and see what happened.

The brief was never to clone that game. It was to build an original one in the same genre, around the same idea, and make it feel good on a phone.

A shareable score card: Barn Burners 3, Yellowknife Auroras 2, final in a shootout. Gordie Howe, Wayne Gretzky and Guy Lafleur are the three stars.
The share card. Every box score exports as an image. Here Howe and Gretzky beat Lafleur and Selanne in a shootout.

“Ancient, but wildly comprehensive… if you could afford it you could have Gretzky ’82 and Lemieux ’89 on the same roster.”

The original request, describing the 2006 game
What exists now

Four games, one account

Hockey · quick gameLine Change

Six spins, three skips, one trade. Build a lineup from three blind real seasons at a time, then see what it does over 82 games. Has a leaderboard.

Play Line Change →
Hockey · leagueTime on Ice

The full salary-cap league: draft, lines, a live Game Center, the trade deadline, playoffs, and franchises that run for years.

Play Time on Ice →
Baseball · quick gameRally Cap

The lineup game for baseball, built on the same pattern with real MLB seasons.

Play Rally Cap →
Baseball · leaguePennant Race

Every season since 1890, a $190M cap for 26 players, and best-of-seven series. Built on the same league core as Time on Ice.

Play Pennant Race →
The design problem

The cap is the game

Everything interesting comes from scarcity. If every legend costs the same, the draft is a formality. So every player-season has a salary set by its rating, and the cap forces trade-offs: one Gretzky, or three solid second-liners.

SalaryA 99 costs $13.5M, a 75 about $1M. The curve is steep at the top on purpose.
Cap$98M for 23 players, rising 3% a season: $101M in season two, $110.5M by season five.
Roster12 forwards, 6 D, 3 goalies, 2 bench skaters, plus 4 cap-free minor leaguers aged 24 or under that season.
FormatsOne season or Franchise. 8, 16 or 32 clubs, 14 to 84 games.
House rulesOrr can never cost more than Gretzky or Lemieux. Hasek’s .932 season was bumped to 99 because “the 99 club needs a goalie.”
The Time on Ice draft: Wayne Gretzky's seasons listed with real stat lines and salaries, one signed, the others marked Have him; Mario Lemieux available with a To minors option.
The draft. Real season lines next to each rating. Signing Gretzky ’85-86 blocks his other seasons. Lemieux ’88-89 was 23, so he could ride free in the minors.
The data

From 484 cards to 52,009

The first version had 484 hand-rated seasons, mostly career peaks. That was enough for one 8-club league. It was nowhere near enough for 32 clubs with bench players, minor leaguers and players who age.

So the pool grew to every NHL season a player actually played. The 484 hand ratings stay as they are. Every other season gets an estimated rating: the player’s hand-rated level, moved up or down by how that season’s era-adjusted scoring compared. Gretzky the rookie rates 91, Gretzky in his prime 99, Gretzky at 38 rates 87.

The pool now covers 5,771 players from 1917 to 2025. Estimated ratings show with a dashed outline in the draft, so nobody mistakes a guess for a hand rating.

Wayne Gretzky, every seasonHand-ratedEstimated from stats
Playing a season

Coach it, trade it, share it

The sim runs in 20-second slices of game time, with line changes, penalties, power plays, pulled goalies, 3-on-3 overtime and shootouts. Tuned over full test seasons, it lands near 3 goals and 32 shots per club per game, with about one game in six going past regulation.

How it got built

One ask at a time, shipped as it came

No spec, no backlog. Each request was a sentence or two in chat. Each one was built, tested in a real browser at phone and desktop widths, and usually live on Cloudflare within the hour. These are the requests in order.

  1. Night oneOct 27
  2. “Can we make a really nice, responsive version of this bad boy?”

    An original salary-cap league: draft from 484 real player-seasons, 8 clubs, a full sim with box scores, play-by-play, standings and a playoff.

  3. “Can we deploy on Cloudflare?”

    Live on the existing Worker the same night, next to the original lineup game.

  4. “Can you put a salary range filter?”

    A dual-handle slider over a histogram of how many players sit at each price.

  5. Stat lines, then “make the stats sortable”

    Real season lines on every card, with a switch. Every column sorts both ways, including position and club.

  6. “16 and 32 team versions… a bench and/or a minor league… injuries… a third goaltender”

    Divisions, wild cards, a 16-club bracket, a 23-man roster with cap-free minors, injuries, and the pool expanded to 4,955 seasons.

  7. “I personally think Bobby Orr was overrated.”

    His rating stayed. His salary didn’t. Then Hasek got the 99 he deserved.

  8. “Allow the user to play their game and see a box score”

    The Game Center, with live play and coaching at each intermission.

  9. Night twoOct 28
  10. Share options, league stats sharing, a save option

    Short share links stored in D1, score-aware link previews, image cards, CSV export, and save files.

  11. Another season, historical stats, and a trade deadline

    Careers or Keep core seasons, the History tab, pre-deadline offers and the 30-second Deadline Day.

  12. “A small cap increase over the years”

    3% a season, rounded to the nearest half million.

  13. “Make the save an add account thing”

    Username and password with optional passkeys, then one account for every Wax Pack game, with cloud saves that autosave.

  14. “There’s no option to start a fresh league, let’s get that first haha”

    A New league button, then a start screen: One season or Franchise, followed by an account step.

  15. “You took away the single season 82 (should be 84 tbh) 32 team stuff”

    Size and length back on One season, 84-game seasons, more lengths, and Sim to the end.

  16. Since thenParallel sessions
  17. Baseball, and every NHL season

    Other Claude sessions built Pennant Race on a shared league core and grew the hockey pool to 52,009 seasons. Deploys were coordinated so half-finished baseball files never went live.

Bugs worth remembering

What testing caught

The sim

Every shot ended the game

Splitting the sim into periods added a function called finish. It quietly replaced the shooter-skill function of the same name, so every shot tried to end the game and nobody could score. A full test season caught it before release.

Trades

Bobby Hull for Bobby Hull

The first Deadline Day offered Hull ’68-69 for Hull ’61-62. Technically legal. Swaps of the same player are now blocked.

Careers

Jagr inherited a stranger’s career

When Jagr ’95-96 aged into ’96-97, another club signed the freed ’95-96 season and got his career stats. Every signing now starts its own career line.

Passkeys

The domain that wasn’t localhost

Passkey sign-in failed in local testing because the dev server reports the production domain. The check now follows the browser’s own rule, and a simulated authenticator verifies sign-in, replay and cloned keys.

Under the hood

Small stack, no framework

Front end

Plain HTML pages and JavaScript modules, no build step. The league engine is pure logic, so the same file runs in the page and in Node for full-season checks.

Server

One Cloudflare Worker serves the pages and a small JSON API. D1 holds leaderboards, share links, accounts and saved leagues.

Accounts

Passwords stored only as PBKDF2 hashes, sessions as hashed tokens in HttpOnly cookies, and WebAuthn passkeys verified in the Worker.

Saves

Leagues are gzipped in the browser before upload, a 32-club league down to a few hundred KB. A revision check stops two devices from overwriting each other.

Size

About 10,000 lines of code, plus 60,000 lines of generated player data built offline from cached NHL stats.

Speed

A full 32-club, 84-game season simulates in under a second in Node, and in a few seconds in the browser with a progress readout.

Still open

What comes next

Monetization is the live question: a free tier with a Pro subscription, pay per season like the original, a one-time unlock, or human-vs-human leagues first. Real player names in a paid game also raise a licensing question to settle before charging anything.

Screenshots are from the live site at waxpackgames.com. Player ratings, salaries and leagues shown are from the game’s own sims. Wax Pack is an independent project and isn’t affiliated with the NHL, MLB or WhatIfSports.