Inspiration

Canada hosts its first home men's FIFA World Cup match on June 12, 2026, against Bosnia and Herzegovina at BMO Field. We're both immigrants in Toronto, and we kept noticing how Canada Soccer's marketing leans on the same set of stories - Alphonso Davies in a Ghanaian refugee camp, Jonathan David in Brooklyn, Tajon Buchanan in Brampton. Refugees and children of immigrants are about to carry Canadian soccer onto the world stage. But the more we read, the more we noticed the gap between the story and the system. Davies didn't come up through Canada Soccer's developmental pipeline - he was discovered through Free Footie, a free after-school program that exists because the official pipeline costs $3,000 to $10,000 a year and prices most newcomer families out. David skipped Canadian academies entirely. Twelve of the thirteen Canadian national-team players we researched bypassed the system Canada now wants to celebrate. We wanted to build something that lets a player feel that gap - not read about it.

What it does

One in a Million, By Design is a 90-second interactive experience in two acts. Act one - the Pipeline. You play an immigrant family arriving in Canada with an eight-year-old who loves football. Over four decisions across his ages 9 to 15, you face real Canadian soccer fees: the $3,200 OPDL invoice, the $1,400 Cleveland showcase weekend, the choice between paying for next year's club fees or your daughter's braces. Most playthroughs end with your kid quitting because the family runs out of money. The math forecloses your options before age 14. Act two - The Almost-Stories. Your family's exit becomes one dot on a wall of 735 dots. Each dot represents a family who came to Canada through one of sixteen real migration corridors - Liberian refugees in Edmonton, Tamil families in Toronto, Punjabi families in Brampton, Syrian refugees in Mississauga, and more. Thirteen of those dots glow gold: Canada's national-team players. Twelve of them carry a "BYPASSED" badge - they didn't come through the official system. The Brampton-Caribbean corridor alone produced five of them. The closing line lands once you see the layout: Canada is selling thirteen players. The system produced one. The rest of the dots are why.

How we built it

React, TypeScript, Vite, Tailwind CSS for the frontend. Zustand for global state - one store managing a six-phase machine (title → framing → origin → pipeline → seam → map). Framer Motion for transitions between screens. Howler.js for the sound layer. We split the build cleanly. One of us owned the Pipeline game - decision logic, money math, framing screens, the four real-cost decisions - using local state and a Zustand bridge to write the player's outcome. The other owned the data layer and the visualization - sourcing real corridor numbers from Statistics Canada and IRCC, verifying the pathway and bypass status of all thirteen national-team players against Wikipedia and player profiles, generating the procedural dim arcs from real migration corridor sizes, and building the DotWall visualization. The DotWall is the heart of the second act and ironically the simplest piece of code in the project. It started as a 3D globe with react-globe.gl, then a 2D map with react-simple-maps - both fought us hard. We pivoted to a CSS grid of dots clustered by corridor, sorted by gold-dot density. The visualization landed harder this way than either map ever did. The argument lives in the proportions, not in the geography. Every claim on screen - every census number, every player pathway, every refugee resettlement count - comes from a primary source. We cite IRCC, Statistics Canada 2021 Census, CIC Facts and Figures, FIFA, and player records. The two composite "named failure" cases are explicitly labeled as composites and grounded in Foot Solidaire (the organization founded by ex-Cameroonian international Jean-Claude Mbvoumin to document football trafficking) and MLS SuperDraft conversion data.

Challenges we ran into

The map almost killed the project. We spent close to two hours fighting react-simple-maps - projection mismatches, geography rendering on one coordinate system while arcs rendered on another, Canada appearing in the wrong quadrant of the screen four iterations in a row. At one point Canada was in northern Europe. We tried geoAlbers, then geoConicConformal, then a string-config + manual instance hybrid, then a runtime error about projectionStream is not a function. Eventually we recognized this was a sunk cost problem and ditched the map entirely. The DotWall replacement took 60 minutes and made the project better. The data was the harder challenge - and the one we're most proud of solving. Our first draft of the corridor numbers had the Liberian-Alberta resettlement figure off by an order of magnitude. We had Tajon Buchanan's heritage wrong (Vincentian instead of Jamaican). Half our player current-club fields were stale. We caught all of this through manual verification against StatsCan and IRCC primary sources before we shipped, but it took most of a research sprint and meant rewriting our closing-screen math from "12 of 13 bypassed" to a stronger framing once we re-verified Osorio's Uruguay developmental years. Merging two parallel branches with two different agents producing two different store architectures was its own challenge. We had naming conflicts on store actions (setCorridor vs selectCorridor), divergent phase enums, and two App.tsx files in different directories rendering different parts of the app. We resolved with aliases instead of a rename refactor, and shipped.

Accomplishments that we're proud of

We built a project where every claim on screen is sourced and defensible. Anyone googling our census numbers, refugee figures, or player pathways will find the sources we cite. We took a thesis that's politically and emotionally loaded - Canada Soccer is selling a story the system didn't produce - and supported it with data we ourselves verified, including correcting our own first draft when the numbers didn't hold up. We're proud of the rhetorical move at the end. Twelve of thirteen players carrying a "BYPASSED" badge isn't a metaphor - it's the literal data, visible on screen, with sourcing one click away. We're proud of the Brampton story. Brampton's Caribbean diaspora produced more Canadian national-team players than any official Canadian academy. That's a real claim. It's our top-left dot block and it's labeled. And we're proud of the recovery. We almost shipped a broken globe. We almost shipped wrong census numbers. We almost shipped Tajon Buchanan with the wrong heritage. We caught all of it.

What we learned

That the right form for an argument isn't always the most ambitious one. We thought we needed a 3D globe with arc animations to tell this story. We ended up with a CSS grid of dots that lands the argument harder, faster, and on every screen size. That the data is the project. The visualization is just how the data shows up. When our first-pass corridor numbers turned out to be wrong, we considered shipping anyway and decided we couldn't - the project's whole credibility rests on its sourcing. Spending two hours re-verifying every figure against StatsCan was the right call. That the closing line of an interactive experience does more work than any other line. We wrote and rewrote ours four times. The version that shipped - "Canada is selling thirteen players. The system produced one. The rest of the dots are why." - only landed because every word points at something visible on the screen above it. That AI agents are great for scaffolding and bad for content. Agents wrote almost all the code in this project. They could not have written the player bios, sourced the corridor data, or written the decision card prose. The irreducibly human work was the writing and the verifying - the things judges and journalists would push back on.

What's next for One in a Million

The project shipped at minimum scope. There are real expansions we'd want to build: Toronto-specific oral histories. Recording diaspora soccer organizers in Brampton, Scarborough, and East York and folding their stories into hover panels on the dim corridor blocks. Joy-coded counterweight to the structural argument. The women's national team thread, deepened. Four of our thirteen are women's team players, but the women's developmental story has its own version of the bypass - Canada had no women's professional pipeline at all for most of Sinclair's career, so NCAA scholarships became the de facto Canadian system. That deserves its own visualization. Living data. The corridor numbers update with each new census. The roster updates with every match. The bypass count changes when an academy product cracks the senior team. The project should automatically reflect those shifts. A version for other countries. Nearly every World Cup national team has a similar story buried under its marketing. Belgium produced its golden generation through specific city pipelines and immigrant communities. The same template - pipeline simulator + corridor wall - could be turned on any country whose national team's story is more complicated than the federation admits. Outreach to Canada Soccer and the Canadian Premier League. The argument here isn't anti-Canadian-soccer. It's that the system Canada is celebrating is not yet the system that produced Davies, David, Larin, or Buchanan. If the next wave of Canadian players is supposed to come through that system, the system needs the funding and the cultural shift to actually produce them. Most of all: we want this to be visible on June 12, 2026, when Canada walks out at BMO Field. The team Canada will field is real. The story behind that team is bigger than the federation's marketing makes it sound. We'd like the version of this project that lives on the day of the match to be richer, sharper, and more widely shared than what we shipped tonight.

Built With

Share this project:

Updates