A fur-hooded survivor with a slung rifle and their husky trudge through deep snow toward a burning crashed bush plane, dwarfed by a vast frozen mountain valley at dusk.

Top-down survival · Nordic winter

Frostwake

The crash was the survivable part.

Scavenge the wreck, keep your dog alive, and follow a radio signal deeper into a frozen valley that stopped answering years ago.

REGION  Nordholm Valley POS  64°11′N 14°22′E TEMP  −8°C WIND  NNE 24km/h DAY  01

Everything out here is trying to cool you to the temperature of the snow. Warmth is the only thing you really own — and the valley keeps asking for it back.

A survivor stands by a lit campfire and a pitched tent, supply crates stacked in the snow at night.
01 — SURVIVAL

Warmth is a resource you spend

Cold, wet, hunger and exhaustion each pull on the others. Let your core temperature fall and hypothermia sets in; frostbite takes fingers; damp gear stops insulating. Fire, food and shelter aren't features — they're the loop.

HypothermiaFrostbiteWet gearAfflictions
An abandoned mining compound with a headframe, a radio tower topped by a red beacon, and a Nordholm Drift Mine sign.
02 — WORLD

A valley built by hand, not spawned

Nordholm Drift Mine. Site 7. A radio mast that shouldn't still have power. Landmarks are authored, not scattered — each one is somewhere to reach, read, and figure out what happened here before you did.

Authored landmarksEnvironmental storyFast travel
A fur-clad survivor with an axe stands ready as a wolf prowls in through a stand of dead birch.
03 — THREAT

You are not the only thing awake

Wolves hunt in packs, bears and moose hold their ground, and something colder keeps watch near the mine. Read tracks, pick fights you can win, and know when the smart move is simply to be somewhere else.

Pack AIHuntingPredatorsThe Warden
Snow-laden log cabins and an abandoned truck in a pine forest.
04 — PROGRESS

Shelter, craft, and dig in

Turn a wreck and a treeline into a foothold: light fires, cook what you hunt, craft tools and warmer clothing, and set snares while you sleep. Every night survived is ground you don't have to take twice.

CraftingCookingTrapsPerks

Behind the build

A from-scratch game engine, hiding under the snow

No off-the-shelf engine. Frostwake is a custom TypeScript ECS driving a deterministic simulation through a hand-rolled Three.js renderer — 80+ independent systems held together by a typed event bus.

Read the field notes →
EngineCustom · TS + Three.js
SimDeterministic 1/60
Systems80+
TargetElectron desktop

Field notes · engineering

Inside Frostwake

A survival game is a lot of small systems arguing about one player. This is how Frostwake keeps that argument fast, deterministic, and buildable by many hands at once — a from-scratch TypeScript engine, no off-the-shelf framework doing the heavy lifting.

01 — The game

A frozen valley, a dog, and a signal

Frostwake is a top-down survival game set in Nordholm Valley, a Nordic wilderness after a bush-plane crash. The core loop is the honest survival one — manage warmth, water, food and rest against weather and injury — but it's wrapped around a place with a history: an abandoned drift mine, a radio mast still transmitting, and a companion husky you keep alive alongside yourself.

Progression is spatial. You push out from the wreck to authored landmarks, each a small story beat and a survival problem: how far can you get before dark, how much warmth does the trip cost, and what's waiting when you arrive. Perks, crafting and better gear widen your range; the valley's threats — and something colder near the mine — keep pushing back.

02 — Architecture

An ECS built to be worked on in parallel

Everything in the world is an entity — a bag of optional components, which are pure data. Behaviour lives in systems: plain functions of the shape (world, dt, ctx) => void that query for the components they care about and mutate them. That's the whole model.

The rule that makes it scale: systems never import each other. They coordinate only through shared components and a typed event bus — a system reacts to damaged or fireLit without knowing who emitted it. Decoupling like this isn't just tidy; it's what lets many separate coding sessions build different systems at once without colliding. Each new system is one line in the registry.

03 — Rendering

Top-down look, real 3D underneath

The game reads as a clean 2D top-down world, but it's rendered in genuine 3D through Three.js with an orthographic camera — that's what gives the crisp, flat, readable silhouette while still allowing real geometry, height and dynamic light. Gameplay stays honest 2D in pixel space; the render layer maps those coordinates onto the ground plane via a single WORLD_SCALE constant and a height function.

The hard part is volume. A valley holds tens of thousands of static props — trees, rocks, scatter. Walking that whole set every frame would stall, so the renderer keeps an active set and freezes static chunks: props that never change are baked into per-cell groups and stop updating, while anything that can move or change stays live. A winter shader, tree-reshaping and instancing sit on top for the snow-blown look.

1/48
World scale
~50k
Entities in a valley
480
Worldgen grid
O(n)
Placement, area-scaled

04 — Simulation

Deterministic on purpose

The simulation runs on a fixed 1/60-second timestep with an accumulator, decoupled from render framerate. Given the same seed and the same inputs, it produces exactly the same run — every time. That's enforced, not hoped for: gameplay randomness only ever comes from a seeded ctx.rng, and sim code is forbidden from reading the wall clock. A unit test fails the build if either rule is broken.

Determinism buys three things at once: tests can assert on outcomes, bugs reproduce from a seed instead of a shrug, and the door stays open to lock-step co-op later — the codebase already avoids assuming a single player and gives every networked entity a stable id.

Why it matters

“It only crashes sometimes” is the most expensive sentence in games. A deterministic sim turns intermittent into reproducible — you replay the seed and watch it happen.

05 — Tooling

The game can be driven — and can play itself

Frostwake ships with an unusually deep verify loop. The dev build runs in an Electron window with a live debug port, so a script can reach into the running game: teleport the player, set the weather, spawn a wolf pack, then screenshot or record a clip — every marketing still on the home page was captured this way.

  • Agent-play harness — a scripted “player” that can navigate, gather, craft, fight and survive, used to smoke-test the game end to end without a human at the keys.
  • Playlog + QA monitor — every run logs survival snapshots and flags physics anomalies (stuck-in-solid, wedged, out-of-bounds) automatically.
  • In-app map editor — author and place landmarks live inside the running world.
  • Vite · Vitest · CI — instant reloads, unit tests mirroring each system, and a pipeline that gates every change on type-check, tests and dead-code.

06 — Scope

Eighty systems and counting

Survival, afflictions, fire, weather, crafting, cooking, hunting, AI and combat, save/load, fast-travel, a journal, a perk tree, a full render pipeline, an editor — 80+ systems, each in its own file, each individually testable. Content is data, not code: items, recipes, enemies and biomes are JSON, so the world grows by adding files rather than editing engine internals.

It is, deliberately, a game first and a systems-engineering showcase second — but the two are the same artifact.

80+
Systems shipped
TS
Strict, no any
JSON
Content pipeline
1 dev
Solo-built
← Back to the game