All projects

Case study · Personal project

Cartomancer

A map-first campaign manager for Dungeon Masters, with Spark, an optional AI librarian that files what happened at the table, keeps a ledger of what's true in the world and flags contradictions. The DM always has the final word, and the whole thing works without AI.

Role
Solo design and build, directing a team of AI coding agents
Status
Live · still building
Built with
React · TypeScript · Vite · Leaflet · Dexie.js · Zustand · Supabase · MCP
Visit the site Private repo
Cartomancer screenshot

1,596

automated tests

01 Brief
Most D&D tools are either a wiki you fill in by hand or an AI that writes lore for you. I wanted a librarian: something that files what happened at the table, keeps the record straight, and leaves the DM with the final word.
02 Approach
Map-first and local-first. Spark, the optional AI, files session notes into a canon ledger and flags contradictions, and everything it suggests waits in one review inbox to keep, edit or undo. I built it solo, directing AI coding agents through written specs, reviews and browser verification.
03 Outcome
Live at cartomancer-phi.vercel.app: about 90,000 lines of TypeScript and 750+ commits, with 1,596 automated tests. I use it to run my own campaign.

01What sets it apart

  1. 01

    Canon you can trust

    Every fact records when it's true (timeless, backstory, played in Session 4, or planned) and who may know it, and a permanent changelog shows which sentences Spark wrote and which the DM did.

  2. 02

    Nothing lands without the DM's say

    Spark's suggestions arrive marked in one review inbox. Keep, edit or discard them, and undo any batch in one step.

  3. 03

    Works without AI

    Every Spark feature has a manual path, so it's a complete campaign manager with no API key at all.

  4. 04

    Bring your own key, see the cost first

    AI calls go straight from the browser to the provider, every action shows its estimated price before it runs, and a spend cap stops surprises.

  5. 05

    The DM owns the data

    Worlds live on the device, back up to a folder the DM chooses, and can sync through the DM's own server. Export is always open.

  6. 06

    Built from how DMs actually prep

    Planning follows Mulligan's toy method and Matt Mercer's scene prep: situations, not scripts, with arcs as seasons and sessions as episodes.

02Engineering highlights

  • Local-first data safety. Multi-step writes run in single transactions, and undo uses compare-and-swap so it never overwrites newer edits.
  • Sync without data loss. Last-write-wins with a base-version guard, so a device that has never synced can't overwrite the cloud copy, plus 20 retained snapshots per world.
  • Provenance. Every AI-written sentence is tagged until kept, and a changelog records Spark and DM edits side by side.
  • AI cost discipline. Model tiers matched to each task, prompt caching of the world context, estimates before every call, and untrusted text wrapped before it enters a prompt.
  • Quality process. 1,596 automated tests, a golden-set evaluation for fact extraction, a coverage ledger of what was last tested and at which commit, and multi-agent reviews including panels of simulated DMs.
  • Accessibility. A UI-scale setting, no text under 12px, and theme tokens throughout, tested at 140% scale on tablet and phone widths.