← /journal

May 28, 2026 · 5 min

Card-native VTT on a Kanban board

We merged a full combat engine into DND Cards without pretending the board was a battle map.

DND Cards started as a Kanban board with wax-seal buttons and /roll in descriptions. Useful. Not a VTT.

Then we needed scenes, tokens, initiative, and attacks that respect what’s on the card — not a generic grid with a ruler tool.

What we shipped

M1 — scenes and tokens. Card-native placement: tokens carry HP/AC seeded from character or monster data, HP bars on the canvas, batch fetch for player-linked tokens.

M2 — combat engine. Encounters and combatants tables, initiative rail with round tracking, action bar derived from parsed 5e action prose, resolution panel with editable assisted rolls, combat log inserts that mirror the same roll_events shape the rest of the app already used.

Monsters were the sharp edge — blank “custom roll” attacks weren’t acceptable once we wired real NPC cards. We fixed seeding so a goblin on the board fights like the goblin on the card.

Why not Foundry-in-a-tab

Scope. The product promise is campaign management with dice inline, not a second virtual tabletop product. The VTT layer shares auth, workspaces, and card data — one database, one Netlify deploy, one mental model for DMs.

Headless proof harness

We added a /proof harness for combat panels so initiative + action bar behavior can be verified without clicking through a full session. Boring infrastructure. Saves an afternoon when AC editing regresses.

What’s next

M3 is the handoff doc in-repo — fog, movement constraints, maybe player-facing views. We’re not racing Roll20. We’re making the board feel like the table already is.


I’m still surprised how much of “VTT” is just initiative order and readable HP — the rest is polish.