DEV Community

MyToolster
MyToolster

Posted on

I Built a Life Simulator That Deals You a Random Country at Birth — With Real UN Data

Every life simulator starts the same way: you design your character. Pick a country, pick a family, optimize the stats. I wanted the opposite. Real life doesn't let you pick — you are dealt a country, a family, a body, at random, weighted by how many babies are actually born in each place. So I built a game around the deal itself: 1in8b.dev — "1 in 8 billion". You press one button, and you are born somewhere on Earth, with probabilities proportional to real birth counts. Then you live that life, year by year, until the local statistics say you don't.

The data layer

The whole game runs on public statistics for 172 countries and territories:

  • UN World Population Prospects for life tables and birth counts
  • WHO / World Bank indicators for life expectancy, under-5 mortality, income (GDP per capita, PPP), urbanization, fertility
  • Cause-of-death distributions per country — what people actually die of in Lagos is not what they die of in Osaka

That last one matters more than I expected. In the dataset, life expectancy runs from 54.5 years (Nigeria) to 85.5 (Hong Kong) — a 31-year gap determined almost entirely by the flag next to your birthplace. A simulation that ignores that is just a dice game. A simulation that uses it becomes something else: every run is a small lesson in how much of a "life outcome" is dealt before any choice is made. Mechanically, each in-game year rolls against the country's survival curve, its cause-of-death profile, and milestone events (schooling, work, migration, family) whose probabilities shift with the country's stats. Rich-country lives and poor-country lives don't just end at different ages — they have different shapes.

The build

It's a static site — vanilla JS, no framework, no backend, no accounts. All data ships as JSON and the simulation runs entirely in the browser. Two details from the build that might be useful to others:

1. Nine languages as static routes, not runtime switching. Each language is its own pre-built page (/ja/, /ko/, /fr/ …) with its own title, description, and canonical URL. The app detects the language from the path. This cost some duplication and bought a lot: every language version is independently indexable, and the first paint is already in the right language.

2. Country names are a real i18n problem. A UI string table is the easy part. But the game also needs the names of all 172 countries in every language — plus region names. We had Chinese, English, and Korean in the data; the other six languages were showing Chinese country names to French and Thai players. The fix was CLDR data (via Intl.DisplayNames) for the missing names, wired through one countryName() helper — and auditing ~250 hardcoded bilingual strings that had quietly bypassed the string table entirely. If your app "supports 9 languages," the long tail of strings outside the table is where it actually doesn't.

Try it

It's free, no sign-up, runs in the browser: 1in8b.dev

Play one life as yourself-by-birthplace, then re-roll and see who else you could have been. The second run is usually the one that sticks with you.

Top comments (0)