From a Chat Prototype to a Real Codebase
Ski Resort Empire started as a rough idle-game draft. Day one was about the foundations every idle game needs: a state store that survives sixty updates per second, numbers far beyond what JavaScript can hold, and game data that lives outside the code.

Every project has a messy first version. Mine was a single-file draft of an idle game in the style of Adventure Capitalist, except that instead of lemonade stands you buy ski lifts. It worked: you could buy a platter lift, wait for it to finish a ride, collect the money and buy the next one. But it was clearly a sketch, not something to build a game on.
So the first real day of development was not about features at all. It was about foundations.
Three libraries before anything else
An idle game has an unusual technical profile. Very little happens per second from the player's point of view, but the game state changes every single frame: progress bars fill, money is credited, cycles restart. I made three decisions right at the start.
Zustand for the game state. The whole game lives in one store: wallet, every business in every location, timers, boosts. Components subscribe to tiny slices of it. That matters more than it sounds: if a business card re-rendered every time the wallet changed, the phone would redraw the whole list sixty times per second. With narrow selectors a card only updates when its numbers change.
react-i18next for every visible word. I live in Austria and think in German, but the game was always meant for a wider audience. Retrofitting translations is painful, so from day one there are no hard-coded texts in the interface. Today the game runs in German, English, Italian and French, and a missing translation key is a build error, not a bug a player finds.
break_infinity.js for the numbers. This one is specific to the genre. Idle games are about exponential growth, and a normal JavaScript number stops being precise at around 9 quadrillion and gives up entirely near 1.8 × 10^308. Late-game idle numbers go far beyond that. break_infinity stores a number as mantissa plus exponent and is designed for exactly this use case: fast, a little imprecise in the last digits, and practically unlimited. The price is discipline: money values are Decimal objects everywhere, so a + b becomes a.plus(b). Mixing the two is the classic source of bugs, so the rule is written down in the project notes and checked by the type system.
Game data belongs in JSON
The second big change was moving all game design numbers out of the code. Costs, cycle times, profits, the cost multiplier per purchase, milestone thresholds, starting money: all of it now lives in JSON files under config/. The code only knows how a business works, never which businesses exist.
This sounds like an architect's hobby, but it changed how I work on the game. Balancing an idle game means changing hundreds of numbers, often many times a day. When those numbers are data, I can change them, run a simulation (more on that in a later entry) and compare results without touching logic. It also means adding a new business is mostly a data entry plus an icon.
While I was at it, I renamed all business ids to short English identifiers (plate, tbar, hut, chair4, gondola, …). The player never sees them, but they appear in save files and configuration, and mixing German and English ids would have haunted me forever.
A first look
The prototype used emoji as icons. That was fine for testing but looked nothing like a game, so I created simple SVG icons as a first step and started on a splash screen. My brief for the splash was simple: more distance, several mountain ranges in the background, at least one mountain with a chairlift in the foreground and a hut somewhere on the slope. The final splash art was later painted with an image model from a detailed prompt, and that prompt is stored in the repository next to the image, so the picture can be recreated or varied later.
That habit, keeping the prompt next to every generated asset, turned out to be one of the most useful decisions of the whole project. I come back to it in the entry about painting the icons.
Hosting
One practical question came up the same day: can a React app like this run on ordinary shared web hosting? It can. Vite builds the game into plain static files: HTML, JavaScript, CSS and images. No server code is needed for the game itself, which is why the browser version today runs on the same simple hosting as my homepage. (Server code did appear much later for purchases and cloud saves, but that runs on Firebase, not on the web host.)
What I learned on day one
- Decide how you store numbers before you write the first formula.
- Keep design data out of the code; you will change it more often than anything else.
- Translations are cheap at the start and expensive later.
None of this is visible to a player. But every later feature in this devlog sits on top of these few decisions.