Hacker News new | ask | show | jobs
by pragmatic 34 days ago
https://80.lv/articles/developing-microlandia-a-socioeconomi...

Do you have a dev blog or anything else? This is super interesting to me as I have an idea for a game I can rapid prototype in the browser.

1 comments

Here is a blog article I wrote when the game was super early but it's outdated.

https://explodi.tubatuba.net/2025/09/26/using-deno-as-my-gam...

I also asked claude to give me a 1-paragraph summary of how our stack works. Anyway, if you have more questions i'm happy to answer e-mail (check my profile)

Robotic text below:

The whole thing is TypeScript end-to-end, run by Deno, which acts as the glue. In the browser, there are just two pieces communicating over a native WebSocket: a React front end bundled by Vite—Deno runs Vite for the development server and hot reload—and a Deno back end that owns the simulation.

The simulation runs on a tick loop, with each tick representing roughly one in-game day and taking about one second of wall-clock time. The client sends small command events such as `newBuilding` and `bulldoze`. The server processes each tick and broadcasts all resulting state changes in a single batched frame. This makes the client essentially a renderer of authoritative server state, with a full resynchronization whenever it reconnects.

Under the hood, the simulation distributes heavy workloads—including demographics, taxes, and housing markets—across Web Workers. These workers coordinate through a shared SQLite database used as a cross-thread bus, allowing the game to simulate tens of thousands of citizens.

The 3D layer uses Three.js with WebGPU, a WebGL2 fallback, TSL shaders, and batched draw calls. It runs imperatively in its own `requestAnimationFrame` loop inside one large component, deliberately avoiding React Three Fiber. React manages only the 2D HUD and menus layered on top, keeping the performance-critical rendering loop entirely outside React’s reconciliation process.

The key point for prototyping is that the browser application—the client plus a local server connected over WebSocket—is the entire game. The desktop builds are simply thin native shells around the exact same application. On macOS, the shell uses Tauri with Rust and the operating system’s WKWebView. On Windows and Linux, it uses Electron with bundled Chromium.

Each shell launches the server, compiled into a single self-contained binary using `deno compile`, as a sidecar process. It then finds an available localhost port and points its webview at the bundled client. This means the game can be built and iterated entirely in the browser, with native packaging added only at the end.