Project
A browser empire-survivor roguelite, built solo. Lead a people from the Stone Age to the stars one survivor run at a time. The reason it is on this site is the engineering: a framework-free game-logic core under 400+ unit tests, procedural audio and art, and a static build with no backend.
Two genres wired together. The action layer is a survivor-style auto-battler: you move, the weapons fire themselves, the screen fills, and you bank what you kill. Between runs you spend that progress on a tech tree and a base camp that carry forward, advancing your people through nine ages from the Stone Age to a space-age final stand. Death is not the end of a run in the usual sense. Whatever a run banks, the empire keeps, and the next run starts stronger.
It is single-player, free, and has no monetization and no backend. It runs entirely in the browser and saves to local storage. The point of building it was not the design; it was finishing and shipping a complete piece of software, solo, with a real test suite and a real build.
I spend my days on security architecture and policy. This was a deliberate swing in the other direction: take a project from an empty repo to a shipped, playable product, owning every layer myself. Logic, rendering, audio, art, build, and tests. No team, no framework doing the hard parts for me.
It is also a working demonstration of AI-augmented execution. I built it the way I build everything now, pairing with AI tooling to move at a pace that used to take a team, while keeping the architecture decisions and the quality bar my own. The interesting question for a portfolio is not "can you make a game." It is "can you hold an entire system in your head, keep it tested, and actually ship it." This is the evidence that I can.
The design decision that made the rest possible: the game rules do not know how the game looks. The economy, tech tree, camp, and run state are framework-free TypeScript with zero Phaser or DOM dependency, so they run and test in a plain Node environment. Rendering is a separate concern layered on top.
Economy, tech tree, base camp, run state, and progression as pure TypeScript with no engine or DOM imports. This is where the 400+ unit tests live. Because the rules are decoupled from rendering, the hard-to-get-right parts are testable in isolation and the engine is swappable in principle.
The survivor auto-battler runs on a Phaser canvas: spawning, movement, projectiles, collisions, the gem economy, and the in-run upgrade draft. This is the only part that needs a game engine, and it is kept to exactly that.
The between-runs layer (tech tree, base camp, ages, persistence) is plain HTML and CSS, not canvas. Using the right tool per surface: a document-shaped UI for a menu-driven 4X layer, a canvas for the action.
Every sound effect is synthesized at runtime from oscillators, filtered noise, and ADSR envelopes. No SFX files ship. Music is a set of context-selected CC0 tracks routed through one master gain, with a procedural fallback bed if a track fails to load.
All sprites are generated from a shape-data plus render-pass system rather than authored image files, with a one-line toggle between a flat and a shaded style. The art is data, which keeps the repo light and the look consistent.
Vite builds the whole thing to static files that deploy to any static host. No server, no database, no telemetry. State persists in local storage. A security habit that turned out to be a clean architecture too.
Built in tracked feature batches, each gated on its own tests and a play session before it counted as done. 40 of 42 planned work items delivered, 400+ unit tests green.
Run, bank resources, research, build, advance an age, run again. Verified end to end: a complete survivor run feeds the empire, which unlocks the next run's options.
Stone, Bronze, Iron, Classical, Medieval, Renaissance, Industrial, Modern, and Space, ending in a scripted last-stand boss run against an invasion.
A weapon draft and a Forge-and-Fuse fusion system, a multi-tier gem economy, perks and relics, dungeon expeditions, points of interest, and mini-boss events. Enough interacting systems to make two runs play differently.
Difficulty pass, onboarding help, pause menu, a persisted volume and mute panel, and an art pass that replaced every placeholder with the procedural pipeline output.
One person across logic, rendering, audio, generated art, build tooling, and tests. Not a fork, not a tutorial, not a framework demo. An empty repo to a shipped product.
400+ unit tests, concentrated on the game logic that is easy to break and hard to debug by playing. Tests written alongside the code, not bolted on after.
Separating rules from rendering is the decision the whole project rests on. It is why the logic is testable, why the code stayed maintainable across 40 feature batches, and why the action and menu layers could use different technologies cleanly.
Shipped a feature batch most days while keeping the design and quality bar my own. The throughput is the point; the judgment stayed human.
Code and original art and sound are mine, released under the MIT license. Sound effects are synthesized at runtime, so no audio files ship for them. The background music is a set of Creative Commons CC0 (public domain) tracks from OpenGameArt.org, selected by age and biome. CC0 needs no attribution; the authors are credited in the project's CREDITS file out of respect for their work.