/ recent work / dnd-cards
DND Cards
Kanban board, but every column is a campaign. Inline dice rolls, DM-only lists, wax-seal buttons.
A Kanban board redesigned around D&D campaign management. Forked from the kan.bn project, then rebranded, restyled, and extended with three D&D-specific features.
Features added
- DM-only lists. Lists can be hidden from players entirely. Amber parchment background + lock icon. Server-side filtering so players never receive the data.
- D&D templates. “Descent into Avernus” and a generic “Campaign Tracker” template wired into the New Board picker.
- Inline
/rolldice parser. Type/roll 2d6+3in any description or comment, get🎲 2d6 → [4,2] = **6**rendered inline. Supports d20, advantage/disadvantage, keep-highest. Custom parser, ~80 lines.
Design notes
Wax-seal embossed buttons (pill-shaped, radial highlight, inner stamped ring, press animation in orange #c87633, danger variant in oxblood #a04030). Card detail uses a 50/50 split when the first attachment is an image so portrait covers fill column width.
Deploy
Docker image built by GitHub Actions on push to main, pushed to GHCR, pulled by Coolify on a DigitalOcean droplet. The Coolify pull occasionally caches stale digests; documented manual unstick in the deploy notes.
Recent shipping
- Vanity URLs — boards open at
/{workspaceSlug}/{boardSlug}instead of opaque ids. Shallow URL replacement in the board view, readable slugs in imports, and admin/public-view detection done via tRPCgetUser(not router params) to survive SSR mismatch. - AI card art — generate cover images via
gpt-image-1(DALL-E successor), with batched generation across an entire column and a replace-on-regenerate flow. Attachments now copy correctly when duplicating lists. - Strobe fixes — three separate fixes to kill the URL-replace flicker that happened with shallow routing on the board view, eventually landing on a
window.historysolution that doesn’t fight Next.js’s router. - Compiled translations for upstream i18n strings as part of localization rollout.