Skip to content
← Back

Invicto

Draft nine players across all six World Baseball Classics and try to go 7-0. Ships in four languages.

Live TypeScriptViteCloudflare D1
Invicto: Draft nine players across all six World Baseball Classics and try to go 7-0. Ships in four languages.

Live at invictobaseball.com. Code private.

The idea

Every World Baseball Classic, my whole family stops to watch. Invicto turns that into a game: draft a nine-man lineup from random country-and-edition rolls across all six Classics, 2006 to 2026, sim the tournament, and try to run the table. Going 7-0 earns the INVICTO title. Winning it all with one loss is CAMPEÓN.

What I built

The rosters are real. A build step fetches and caches the Wikipedia roster for every WBC edition and joins it against the Chadwick and Lahman baseball databank, validating roster sizes, positions, and duplicate IDs, with spot checks against famous players. Bad data fails the build, not the player.

The game itself is Vite and TypeScript with no framework, running on Cloudflare. Difficulty is calibrated with Monte Carlo simulation: a top-percentile lineup should go 7-0 only 2 to 5% of the time, and soft-min gating means one weak position caps your ceiling, the way it does in a real lineup. It ships in four languages, Spanish first, then English, Japanese, and Korean, and a test fails the build if any table drifts from the Spanish key tree. Daily stats are anonymous by design: no accounts, no cookies, just a random client ID against Cloudflare D1.

The hard parts

01

Real rosters, messy sources

Wikipedia tables and the baseball databank disagree in small, painful ways. The pipeline reconciles them and refuses to build when the numbers do not check out.

02

Difficulty that feels like baseball

A lineup is only as strong as its weakest spots. Soft-min gating plus Monte Carlo calibration keeps a stacked draft beatable and a perfect run rare.

03

Four languages that stay in sync

Each locale needs at least eight flavor variants per outcome, and the build fails if any language drifts. INVICTO and CAMPEÓN stay untranslated everywhere, on purpose.

What’s next

More outcome flavor, and rosters for whatever the next Classic brings.