Delve: Ashes of the Pale Flame — Case Study
Context
Delve is a real-time browser roguelike — procedural floors, permadeath, tile-based movement. After building out its world (lore fragments, classes, bestiary), the obvious question was whether that world could support a different genre. The deckbuilder format felt like a natural fit: same dungeon, same monsters, different combat grammar.
The goal wasn’t to rebuild Slay the Spire. It was to make something playable in a browser with no install friction, using the lore and art assets already developed for Delve.
Approach
1. Shared world, separate game
The deckbuilder inherits Delve’s visual language — dark palette, gold/amber accents, Cinzel typefaces, Aldric’s chronicle as the framing device. The seven classes (Warrior, Mage, Rogue, Ranger, Necromancer, Paladin, Bard) mirror their roguelike counterparts, with starter decks that reflect their play style: Warrior builds block and pressure, Mage spikes damage at the cost of fragility, Necromancer poisons and outlasts.
Enemies and bosses are pulled directly from the roguelike’s bestiary. The Brood Mother ends The Warren. The Warlord ends The Ruins. The Pale King closes The Crypt — and the game’s own intro (Aldric’s chronicle, the Dungeon Heart, the failed seal) implies there’s something deeper still.
2. Combat engine
Turn-based. Fixed energy per turn (3 for all classes at baseline). Cards drawn from a shuffled deck, discarded after play, recycled when the draw pile empties. Status effects — vulnerable, weak, poison, block — interact in specific ways: block absorbs damage before HP; poison decays by one each turn after dealing damage; vulnerable amplifies incoming hits; weak reduces outgoing damage.
Block does not persist between turns — a deliberate design choice that makes the Warrior’s block-generation gameplan meaningful (more cards = more block per turn) without making turtling trivially safe.
3. Branching node map
Each act is a branching graph of nodes: Combat, Elite (harder fight, better reward), Event (lore fragments that offer choices — most drawn from the roguelike’s scroll archive), Rest (heal or, eventually, upgrade a card), Shop (spend gold), Boss. The map is seeded per run; paths fork and rejoin. Completing an act boss carries deck, relics, and gold into the next act with a partial heal.
4. Save integrity
No backend — the full run state lives in localStorage. The save format is a JSON object signed with a SHA-256 hash via the Web Crypto API. On every load, the hash is recomputed and compared; a mismatch rejects the save silently rather than crashing. This doesn’t stop a determined player, but it prevents accidental corruption from browser devtools fumbling from being loaded as valid state.
5. Art pipeline
The original card, character, and enemy art was committed as full-resolution PNGs — 168 MB of git history that made clones painful. A Node.js script (scripts/optimize-art.mjs) converts the full set to AVIF at display resolution. Result: 1.3 MB for the entire art set, ~99% smaller, no visible quality loss. Components fall back to a procedural placeholder automatically if an asset is missing, so art can be filled in incrementally without blocking development.
6. Deploy
Single Docker image: Vite build → nginx static serve. No server-side logic. A Gitea Actions workflow builds and pushes to the container registry on every push to main.
What’s missing
The game’s own framing promises a fourth act — the Abyss, and the Dungeon Heart the intro screen tells you about. Right now a run ends after the Pale King, which is anticlimactic given what Aldric’s chronicle sets up. That’s the biggest remaining content gap.
Mechanical gaps: no card upgrades (rest sites only heal), no card removal (you can’t thin a Strike out of your deck), no meta-progression across runs (no unlocks, no reason to try a different class beyond curiosity).
The .git history still carries the original PNG blobs (~166 MB); they’re gone from the working tree but not from history. Fixing it requires a history rewrite — doable, but needs an explicit go-ahead since it rewrites commit hashes.
Stack
| Layer | Tech |
|---|---|
| Client | React + TypeScript + Vite |
| Styling | Plain CSS — dark/gold palette shared with Delve roguelike |
| Persistence | localStorage, signed with Web Crypto SHA-256 |
| Art pipeline | Node.js + AVIF conversion (scripts/optimize-art.mjs) |
| Deploy | Docker + nginx; Gitea Actions CI |