May 29, 2026 · 4 min
Importing D&D Beyond without a second app
We wanted characters on the Kanban board, not a parallel sheet product.
DND Cards already had character sheets — prepared spells, upcasting, magic-item bonuses wired into the same modifier pipeline as combat. The gap was getting a real Beyond character onto the board without an afternoon of copy-paste.
Players live in D&D Beyond. DMs live on our board. The import layer is the handshake.
Three doors in
We didn’t pick one winner. We shipped three on-ramps because real tables are messy:
AcroForm PDF. Official character sheet export. Parse the fields, map into our schema. Boring. Reliable when the PDF isn’t lying.
Chrome extension scaffold. One-click from an open Beyond tab — handoff JSON into the app. Still Adam’s OAuth and store listing to finish; the plumbing exists.
Bookmarklet + drop JSON + wizard UI. For the night someone sends a file in Discord and nobody wants to install anything.
Same destination. Different friction.
Why not a separate “import app”
Because the product promise is one database, one deploy, one mental model. Import is ingestion. Combat reads the same characters row the Kanban card already pointed at.
We kept vanity URLs and /roll in descriptions. We added scenes and initiative. The VTT doesn’t get a second login — it inherits whatever the board already knew.
What broke our brains
Beyond’s export isn’t a stable API contract. It’s a PDF that changes edge layout when Wizards sneezes. The extension path needs a host match and a content script that doesn’t fight Beyond’s SPA navigation.
I’m embarrassed how long we treated “paste your stats” as good enough for a demo. Demos lie. Tables don’t.
What’s still open
GitHub secrets for Supabase migration CI — manual step, documented, not blocking local work. Collab read-only view and session recap cards are the next table-feel wins.
The funnel we care about: export sheet → land on board → drag to initiative → roll from the card text. Every step removed is a step someone actually runs at session zero.