Campaigns and live sessions, or making D&D online actually work
Running D&D online means juggling five tabs. The campaign manager and live session view are the start of putting all of that in one place.
The thing that frustrates me about running D&D online isn't any one part. It's the seams.
You schedule the session in Discord. You share the campaign notes in a Google Doc. You roll dice in a chat bot. You watch each other on Zoom or Discord video. You manage initiative in someone's homebrew tracker. The session itself is fine. The five minutes before and after, where everyone is loading three different tabs and asking "wait, where's the map again," is where the energy leaks out.
This stretch was about closing some of those seams. Not all of them. There are still rough edges. But the campaign manager and the live session view are the start of putting the parts that need to be together actually together.
Campaigns were always the goal
The product had been moving toward this for months without saying so out loud. The character generator made characters. The monster generator made monsters. The NPC generator made NPCs. Each of those features answered a small question for a DM. The big question, the one that made the small features matter, was "how do I run a campaign."
A campaign is what a D&D world actually is. It owns the story. It owns the cast. It owns the maps and the encounters and the session notes and the unresolved threads. Without a campaign, the entity generators are a toy. With a campaign, they're a place to put your work.
So the campaign became a real container. A campaign owns chapters. A chapter owns encounters. An encounter owns the monsters and NPCs that show up in it. The schema is opinionated on purpose. DMs already think this way. They have a session in mind, and the session has scenes, and the scenes have things in them. The data model just matches the mental model.
Building this surfaced an architectural choice I'd been deferring. Most of the entities in the database had been free-floating, attached to a user but not to anything else. Once campaigns existed, every other entity got the option to belong to one. Belonging is permissive, not exclusive. A monster can live in a campaign, or it can live in a user's general library, or both. The campaign isn't a wall around content, it's a context that organizes it.
Live session is the campaign in motion
The campaign manager organizes the world. The live session is where the world actually happens.
The live session view is its own page, not a modal. It has its own URL, its own join flow for participants, its own state. Once the session is running, the DM and the players are looking at the same place. The campaign book is on one side. The active scene is in the middle. The cast is visible. The notes are reachable. None of the information a DM needs in a session lives in another tab.
This is the part the post can be honest about: it's not finished. Some of the live session work in this stretch is structural, not polished. The dual-sidebar pattern is in place. The tabs are wired. The campaign book is reachable. The realtime layer is connected and works. But the surface is still being figured out, and a few of the interactions that need to feel game-table-grade still feel like a meeting tool with extra steps. The next stretch will keep tightening those.
What's in place is the shape. The shape is right. The polish is the next pass.
Live collab as the connecting layer
The thing that makes the campaign and the live session feel like one product instead of two is that they share live collaboration. When two people are looking at the same campaign chapter, both of them see the changes in real time. When the DM moves something during a session, the players see it move. The collaborative behavior isn't a feature of any one screen. It's a property of the whole product.
Getting that to work meant making decisions about state that I'd been able to dodge before. Which writes need to broadcast immediately, which can settle eventually. Which surfaces need cursor presence, which would feel claustrophobic with it. How to keep the realtime layer from leaking into every component that doesn't care about it. The full architecture for this is its own post (or a few of them), but the short version is that everything that should be live, is, and everything that shouldn't be, isn't.
What the stretch shipped
A campaign manager that owns chapters, encounters, and the cast. A live session view with its own page, its own routing, and its own join flow. A campaign book that travels with the session. Real-time collaboration on the surfaces that need it. The first version of an in-session experience that doesn't require the DM to alt-tab between five different products.
The rough edges are real. The seams aren't fully closed. But the parts that need to be together are now together, and that's the difference between a tool that helps you run D&D online and a place where you actually do it.
The next stretch is about everything that touches a session table. Initiative, dice, story beats, the small live-session interactions that have to feel right because they're the ones the players see most. That work is already in motion.

Written by Jean P.
Solo builder.
Discuss this post
Join the D3 Designs Discord to share thoughts and follow along.
