Case study: Djupet

A Lovecraftian idle cult management game set in Malmö, Sweden — built as a small weird thing and kept weird.

Context

The brief was “something tiny and weird.” The Lovecraftian idle game emerged from two constraints: place it somewhere specific, and draw from sources with actual texture — Anders Fager’s Swedish folk horror, the Kult RPG, Call of Cthulhu. The result is a cult running out of a basement in Rosengård, managing devotion, dread, secrecy, and chaos while the Turning Torso does things it shouldn’t.

The register matters more than the mechanics here. Events are described the same way a bus schedule would be. An ICA cashier hasn’t blinked in three weeks. An SJ train stopped in a tunnel that isn’t on any map; passengers arrived on time and can’t remember boarding. A city on the bottom of Öresund with its lights on. The horror is in the tone, not the content.

Problem

Build an idle game that:

  1. Has enough mechanical depth to keep a player engaged through a full run
  2. Reads as a specific place — Malmö, not a generic fantasy city
  3. Draws the right lore register without tipping into parody
  4. Feels handmade rather than procedurally generic

Approach

Four interlocking resources

Rather than a single currency, four resources pull against each other:

  • Andakt (devotion) — passive income, the primary spendable. More believers means more andakt, but also more exposure.
  • Dread — accumulates as the ritual deepens. High dread unlocks areas and events, but also attracts investigators.
  • Hemlighet (secrecy) — drains as the cult grows. Reaches zero, game over.
  • Kaos — builds naturally, triggers chaotic events at 100, resets. The pressure valve.

This creates a genuine tension: the fastest path to winning the ritual depletes hemlighet fastest.

The Malmö map

Leaflet with CartoDB dark tiles, centered on Malmö at zoom 12. Seven named locations pulse as dread rises — markers scale from 6px to 24px and shift from near-black through deep purple to full magenta. Clicking a location visits it: unlocked cult areas give resources, locked ones give lore. There’s a 30s cooldown per location so it’s a decision, not a spam button.

Event pool

40+ events in two pools. Standard events fire every ~6 seconds; kaos events trigger when kaos reaches 100. Each event is drawn without replacement until the pool is exhausted, weighted by relevance to current game state.

The Anders Fager register: mundane Swedish detail, matter-of-fact voice, the horror in what isn’t said. The Kult register: city officials who exit through doors that no longer exist, Broder Mattsson dying mid-lecture and finishing it anyway. The CoC register: fish circling in a precisely shrinking radius, investigators losing track of when they are rather than where.

Kaos as a chaos engine

Kaos events are Henderson-tier: Göran from Discord (who joined by accident and thinks it’s a board game server) now leads prayers. A rival cult tries to summon a different entity and reaches IKEA customer service instead. Zlatan posts on Instagram at 3am with the caption “jag vet.” The events let the game breathe between the heavier lore beats.

No framework, same stack

Vanilla TypeScript + Vite, same as rack and 2048. State is a plain immutable object; each tick and each user action returns a new state. The render layer only rebuilds the upgrade buttons when affordability actually changes — replacing innerHTML 30 times per second was killing click events (mousedown on a button, button replaced, mouseup on a different element, click never fires).

LocalStorage autosave with a versioned key (djupet_v001) — bump the version constant to wipe incompatible saves on deploy.