May 24, 2026 · behind-the-scenes
The tech behind Dungeon Diary
A plain walkthrough of what runs under the hood and what that means for you at the table. Written for users who want to know what they're actually getting.
Why a blog post about this
A lot of tools tell you what they do. Fewer tell you how. This post is the how, in plain language, so you can decide whether Dungeon Diary is the right shape of thing for your table. Each section pairs a piece of tech with what it actually means for you when you're prepping on a Tuesday or running a session on a Saturday.
The shape of the app
Dungeon Diary lives entirely in your browser. There's nothing to install, nothing to update. You sign in, your stuff is there. The same campaign, the same NPCs, the same dice, the same voice room, whether you're on a laptop at home or a tablet at the table.
There's only one Dungeon Diary, not a separate "app" and "server." That sounds technical but it's actually a user thing. It means the app and your data are never out of sync, you don't have to wait for a download when something changes, and there's nothing to "update" the day before session.
Your campaign lives in a real database
The thing storing your campaign is Postgres, hosted by Neon. That matters for three reasons:
Backups. Every campaign, every NPC, every session note is backed up continuously. If your hard drive dies tomorrow, your campaign is still there when you sign in from a new machine.
Exports. Your data is yours. There's a one-click export that gives you the whole campaign as structured JSON plus Markdown files you can drop into Obsidian, Notion, or just a folder on your desktop. If Dungeon Diary ever goes away, your campaign survives.
Version history. Pro subscribers get up to 50 snapshots per entity (200 for Founders). Renamed a city? Changed an NPC's backstory? You can scroll back and restore the older version. Real database, real history, not "we'll try to remember."
Sign-in that doesn't get in the way
The login system is called better-auth. Two things about it.
Your email and password live in our own database, not a third-party identity service. That means nobody else (no Clerk, no Auth0, no Google) is tracking when you sign in or which campaigns you open.
Verification goes through Resend, which handles the "click the link in your email" step. The link expires in 24 hours. The session cookie is signed and HTTP-only, which is the secure way to do it. Boring on purpose.
AI that doesn't lock you in
When you ask the AI to draft an NPC or recap a session, what's actually happening is Dungeon Diary calls a model through a layer called the Vercel AI SDK, which routes through OpenRouter.
Three practical consequences:
Multiple models, automatically. Most surfaces use Google's Gemini 2.5 Flash because it's fast and cheap and good enough for an NPC draft. Higher-stakes surfaces (the canon doc that grounds every AI reply in your actual campaign) use Anthropic's Claude Sonnet. You don't have to think about which model is running where.
Automatic failover. When one provider has an outage, the next request rolls over to another. You usually won't notice.
Bring Your Own Key. If you'd rather pay for AI directly (which is cheaper at heavy usage), there's a BYOK plan where you plug in your own OpenRouter key. Your generations don't count against any Dungeon Diary quota because we're not paying for them.
Dice, combat, and voice all sync instantly
Live D&D needs everyone to see the same thing at the same moment. The dice roller, the combat tracker, the scene token positions, the voice presence: all of those run through a service called Ably, which is a real-time pipe between everyone in the campaign.
What that gets you at the table:
- When the wizard rolls a 20, every player sees the d20 land at the same time. No "wait, what did you roll?"
- When the DM marks a combatant defeated, the X appears on every screen immediately.
- When a player drags their token across the tactical map, the move shows up for everyone within a heartbeat.
- The voice room knows who's connected, who's muted, and who's talking, without anyone refreshing.
Permissions on these channels are scoped to your role. Players can subscribe and chat. Only the DM can publish combat updates, scene moves, or session notes. A malicious player can't fake a 20 from their browser console.
Voice in the browser, with transcripts
The voice room is built on WebRTC, which is the same technology your browser uses for video calls. No extra app, no Discord required. It works directly inside Dungeon Diary, so you can roll dice and look at NPC notes without alt-tabbing.
The mesh setup we use is sized for tables up to about six speakers, which covers basically every D&D table. (Beyond that we'd move to a different setup, and we will when usage warrants.)
If you record the session, the audio gets stitched together from every speaker's track, uploaded, and sent to Deepgram for transcription. Deepgram does speaker diarization, which means the transcript comes back labeled by speaker with timestamps. Not "wall of text." Real "Marcus said this, then Edda said this." Which is the difference between a transcript you'd actually re-read during recap and one you'd never open.
Images stay in your campaign
Every image you upload, character portraits, map tiles, scene backgrounds, the campaign banner, lives in Vercel Blob storage. Each one is private by default.
The way that works: the actual blob URL is hidden behind a proxy. When you (or your players) load an image, the proxy checks that you're a member of that campaign before serving the file. So nobody can guess a URL or scrape your campaign's portraits even if they know the campaign exists.
When you upload an image we also drop you into a crop dialog with the right aspect ratio for the surface you're uploading to. Banners are 3:1, portraits are square, map images preserve their natural ratio. You position, zoom, and confirm. The cropped version is what gets stored.
A public API and an Obsidian sync
For the technically inclined: every campaign has a public REST API, accessible through Personal Access Tokens you mint yourself in settings. Every entity supports ?format=markdown so you can fetch ready-to-read files for your own tools.
The Obsidian plugin (a one-click install once it's in the community store) uses that API to mirror your whole campaign into a vault folder as Markdown files. Your Dungeon Diary world becomes searchable in Obsidian, linkable in Obsidian, and version-controllable through Git if you want that.
Webhooks let you wire Dungeon Diary into Zapier, n8n, Make, or anything else that speaks HTTP. The session-ended event, for instance, can post directly to your group's Discord, or trigger an automation that mails your players the session recap.
Where your subscription actually goes
If you're a Pro subscriber, here's what's running under the hood on your behalf.
- Vercel hosting (compute and bandwidth) for the app itself.
- Neon Postgres for every campaign, character, NPC, region, session, and chat message.
- Vercel AI Gateway tokens, routed through OpenRouter, for every AI generation.
- Deepgram for session transcription, if you record.
- Vercel Blob for every portrait, map tile, scene background, and uploaded audio file.
- Ably for the realtime channels behind dice, combat, scenes, presence, and chat.
- Resend for verification and notification email.
- Sentry for error tracking so the next bug gets caught fast.
- Stripe for billing.
None of those are cheap individually. None of those are skippable. The subscription covers all of them with enough left over to keep building the next feature. Most users don't push their limits to the cap, which is what makes the maths work across the population.
If you're reading this because you're considering using Dungeon Diary at your table, that's the deal. None of the choices above are flashy. They're the boring, well-trodden options that mean the tool will still be running smoothly two years from now, your campaign will still be yours, and the next session is one click away.
Dungeon Diary