dmderelyn53 downloadsRun D&D 5e campaigns in Obsidian with a typed entity graph, session runner, initiative tracker, quest board, and player-facing site export.
Plan and run D&D 5e campaigns entirely inside Obsidian. One plugin replaces a stack of single-purpose tools: typed entity management, a session runner dashboard, an in-house initiative tracker, an interactive map with fog of war, and more.
Device support: Optimized for desktop and tablet use. Mobile (phone) is usable for quick additions and references — slash commands, secrets, quick notes, statblock reading, quest board, timeline — but canvas-based views (Campaign Map, NPC Relationship Graph) are not an ideal experience on small touch screens. Multi-panel layouts like the Session Runner also work best with a wider display.
main.js, manifest.json, and styles.css into your vault's .obsidian/plugins/dnd-campaign-manager/ folder. Enable the plugin in Settings > Community Plugins.Ctrl/Cmd + P) and run "Campaign: Initialize Campaign Vault". Enter your campaign name (e.g., Curse of Strahd). This creates all the folders and templates you need. This can be done in an already existing vault./add npc Goruk the Mighty in any note.| Plugin | Why |
|---|---|
| Templater | Powers entity creation from templates. Without it, the plugin uses built-in templates (still works, but Templater gives you customizable prompts). |
| Dataview | Enables advanced queries in your notes (e.g., "all NPCs in Waterdeep"). The plugin detects both and warns you in settings if they're missing. |
Command: Campaign: Initialize Campaign Vault
Sets up a fresh vault for campaign management in seconds. Perfect for DMs who start a new vault for each campaign.
What it creates:
Campaign/
PCs/
NPCs/
Quests/
Locations/
Sessions/
Factions/
Items/
Templates/
Campaign/
npc.md
pc.md
quest.md
location.md
session.md
faction.md
item.md
D&D Example: You're starting Waterdeep: Dragon Heist. Run the command, type "Waterdeep: Dragon Heist", and you've got a fully organized vault ready to fill with NPCs, locations, and session prep.
Commands: Campaign: Create NPC, Create PC, Create Quest, Create Location, Create Session, Create Faction, Create Item
Each command prompts you for a name and creates a fully structured markdown file with frontmatter fields tailored to that entity type.
D&D Example — Creating an NPC:
Run Campaign: Create NPC and type "Volothamp Geddarm". The plugin creates Campaign/NPCs/Volothamp Geddarm.md with:
---
id: 01HXK...
kind: npc
disposition: neutral
status: alive
role:
race:
factions: []
location:
relationships: []
secrets: []
---
Plus sections for Appearance, Personality (Ideal/Bond/Flaw), Voice & Mannerisms, Secrets (GM-only), Plot Hooks, and Relationships.
Templates live in your vault at Templates/Campaign/. You can edit them to match your style — add custom sections, change the prompts, restructure as you like.
Type / in any note to access quick commands. A suggestion popup appears as you type.
| Command | What it does | Example |
|---|---|---|
/add npc <name> |
Creates an NPC file and inserts a [[link]] |
/add npc Xanathar |
/add pc <name> |
Creates a PC file and inserts a link | /add pc Elara Moonwhisper |
/add quest <name> |
Creates a quest and inserts a link | /add quest The Missing Diplomat |
/add location <name> |
Creates a location and inserts a link | /add location Yawning Portal |
/add faction <name> |
Creates a faction and inserts a link | /add faction Zhentarim |
/add item <name> |
Creates an item and inserts a link | /add item Cloak of Elvenkind |
/roll <dice> |
Rolls dice and inserts the result | /roll 2d6+3 |
/link |
Opens a picker to insert a link to any entity | /link |
/log event <text> |
Inserts a timestamped event line | /log event Party enters the dungeon |
Tip: If you type /add npc without a name, the plugin will prompt you for one instead of creating a dead link.
D&D Example — Mid-session notes: You're running a session and the party meets a new NPC. In your session note, type:
/add npc Renaer Neverember
This creates the NPC file, links it in your session note, and you can flesh out the NPC later. Then log what happened:
/log event Party rescued Renaer from the Zhentarim warehouse
/roll 2d6+3
Result: - **2026-04-16 19:30** — Party rescued Renaer from the Zhentarim warehouse
and: `2d6+3 = 11` (4, 4)
Type /roll followed by standard dice notation.
| Expression | Meaning |
|---|---|
/roll 1d20 |
Roll a d20 |
/roll 2d6+3 |
Roll 2d6 and add 3 |
/roll 4d6-1 |
Roll 4d6 and subtract 1 |
/roll 1d100 |
Percentile roll |
The result is inserted inline: `1d20 = 15` (15)
Command: Campaign: Auto-link entities in current file
Scans your note for entity names and wraps them in [[wikilinks]]. Knows all entity names and aliases. Respects existing links, code blocks, and frontmatter — won't double-link or break formatting.
D&D Example: You write a session note with plain text:
The party met Goruk at the Yawning Portal. He told them about the Zhentarim's plot.
Run the auto-link command and it becomes:
The party met [[Goruk]] at the [[Yawning Portal]]. He told them about the [[Zhentarim]]'s plot.
Command: Campaign: Open Quest Board | Ribbon icon: Scroll
A dedicated panel that groups all your quests by state: Hook (rumors the party hasn't engaged with), Active, Completed, Failed, Abandoned.
D&D Example: You've created quests like "Find the Stone of Golorr" (active), "Rescue Floon" (completed), and "Investigate the Fireball" (hook). The Quest Board shows them grouped and color-coded. Click any quest to jump to its note.
Quest states are controlled by the state: field in quest frontmatter. Update it to active, completed, failed, or abandoned and the board updates automatically.
Command: Campaign: Open Campaign Issues
Shows all entity files with schema validation errors — missing required fields, wrong types, invalid values. Like a linter for your campaign notes.
D&D Example: You accidentally set an NPC's disposition: grumpy (not a valid value — should be hostile/unfriendly/neutral/friendly/allied). The diagnostics panel flags it with the file, field, and error message. Click the filename to jump there and fix it.
Command: Campaign: Open Initiative Tracker | Ribbon icon: Swords
A full combat tracker built into Obsidian. No external dependencies.
Features:
D&D Example: The party is ambushed by 3 goblins and a bugbear.
Command: Campaign: Start Session (layout) | Ribbon icon: Play
Opens a three-panel layout optimized for running a live game session:
Session Runner features:
D&D Example: Session 12 of your campaign. You:
Command: Campaign: Open PC Sheet
A read-only character sheet view that displays ability scores, combat stats, spell slots, and a link to the full note.
Importing from D&D Beyond:
https://www.dndbeyond.com/characters/12345678) — the character must be set to Public on DDBFallback: If the URL doesn't work (character is private or DDB changes their API), paste the character's JSON export from the Beyond20 browser extension instead.
D&D Example: Your player just leveled up on DDB. Paste their character URL into the importer and the PC file updates with new HP, spell slots, and ability scores.
Command: Campaign: Open NPC Relationship Graph
A canvas-based visual graph showing NPCs and factions as nodes, with edges drawn from relationships, factions, allies, and enemies frontmatter fields.
D&D Example: You've built out the Waterdeep faction network — Zhentarim, Xanathar Guild, Harpers, Lords' Alliance, Force Grey. Open the graph and instantly see who's allied, who's at war, and which NPCs belong to which faction. Drag the Xanathar node next to the Zhentarim to visually group the antagonists.
Command: Campaign: Open Campaign Map
An interactive map view with fog of war and pin placement.
Setup:
map_image: field pointing to an image in your vault (e.g., map_image: Maps/waterdeep.png)Using the map:
D&D Example: You have a dungeon map. As the party explores, toggle fog reveal and paint the rooms they've entered. Place pins labeled "Trapped Door", "Boss Room", "Secret Passage". The fog state saves to frontmatter so it persists between sessions.
| Setting | Default | Description |
|---|---|---|
| Entity folders | Campaign/PCs, etc. |
Where new entities of each kind are created |
| Strict validation | Off | Show a notice when opening a file with schema errors |
| Auto-link on save | Off | Automatically rewrite entity names as wikilinks on save |
| Excluded folders | (empty) | Folders the plugin should ignore entirely — their contents won't appear in Campaign Issues or be indexed as entities |
Every entity file has YAML frontmatter that the plugin validates. Here are the key fields for each kind:
kind: npc
disposition: neutral # hostile | unfriendly | neutral | friendly | allied
status: alive # alive | dead | missing | unknown
role: Tavern keeper
race: Dwarf
factions: ["[[Zhentarim]]"]
location: "[[Yawning Portal]]"
relationships:
- target: "[[Renaer Neverember]]"
kind: rival
secrets: ["Secretly reports to Manshoon"]
kind: pc
player: Alex
class: Wizard
level: 5
race: High Elf
hp: { current: 32, max: 38, temp: 0 }
ac: 15
stats: { str: 8, dex: 14, con: 12, int: 20, wis: 13, cha: 10 }
kind: quest
state: active # hook | active | completed | failed | abandoned
giver: "[[Volothamp Geddarm]]"
objectives:
- text: Find Floon Blagmaar
done: true
- text: Investigate the warehouse
done: false
rewards: ["10 gold dragons", "A map to the Vault"]
kind: location
type: settlement # region | settlement | dungeon | poi | realm | plane
parent: "[[Sword Coast]]"
map_image: Maps/waterdeep.png
kind: session
number: 12
date: 2026-04-16
pcs_present: ["[[Elara]]", "[[Goruk]]", "[[Theron]]"]
strong_start: "A fireball explodes in Trollskull Alley"
kind: faction
alignment: Lawful Evil
leader: "[[Manshoon]]"
influence: 7 # 0-10 scale
allies: ["[[Doom Raiders]]"]
enemies: ["[[Harpers]]"]
kind: item
rarity: rare # common | uncommon | rare | very-rare | legendary | artifact
attunement: true
cursed: false
owner: "[[Elara]]"
Commands:
Secrets: Add a secret or clue to the poolSecrets: Reveal a secret to the playersSecrets: Open pool fileA Lazy DM pool of unrevealed plot threads for the current campaign. Stored as plain markdown at Campaigns/<name>/Secrets.md with GFM task-list syntax so you can also check boxes manually.
D&D Example: During session prep you brainstorm 10 secrets the players could uncover. Run "Add a secret or clue" for each: "The innkeeper is a werewolf", "The map was forged by the BBEG". During play, when the party discovers one, run "Reveal a secret" — it moves from the Unrevealed section to Revealed, tagged with the current session. Any unrevealed secrets roll forward to the next session automatically.
Inline D&D 5e-style monster statblocks via a campaign-statblock code block. DM-friendly YAML format, no external plugin dependency.
Usage:
```campaign-statblock
name: Goblin
size: Small
type: humanoid (goblinoid)
alignment: Neutral Evil
ac: 15 (leather armor, shield)
hp: 7 (2d6)
speed: 30 ft.
stats:
str: 8
dex: 14
con: 10
int: 10
wis: 8
cha: 8
skills: Stealth +6
senses: darkvision 60 ft., passive Perception 9
languages: Common, Goblin
cr: 1/4
actions:
- name: Scimitar
text: "Melee Weapon Attack: +4 to hit, reach 5 ft., one target. Hit: 5 (1d6 + 2) slashing damage."
- name: Shortbow
text: "Ranged Weapon Attack: +4 to hit, range 80/320 ft., one target. Hit: 5 (1d6 + 2) piercing damage."
```
Supports all 5e statblock fields: AC, HP, speed, stats, saves, skills, damage/condition immunities/resistances, senses, languages, CR, traits, actions, bonus actions, reactions, legendary actions. Missing fields just don't render.
When creating an NPC — via the command palette or /add npc — the prompt includes a Generate name button. Click it to fill the field with a random fantasy-flavored name across 9 races (human, elf, dwarf, halfling, dragonborn, tiefling, gnome, half-orc, orc). Click again to cycle through suggestions. The generator is built-in and doesn't depend on any network call.
Command: Open Campaign Timeline
A chronological ItemView that aggregates every ## Session log bullet from every session note in the active campaign. Sessions group by number (then date); entries within each session appear in their original order.
Goruk) to show only lines that mention it.D&D Example: Halfway through a campaign you ask "wait, when did the party first meet Strahd?" Open the Timeline, type Strahd in the filter, scroll to the first match — it's right there with a session link.
| Command | Description |
|---|---|
| Initialize Campaign Vault | Create all folders and templates for a new campaign |
| Switch Active Campaign (default) | Pick the default campaign when no campaign file is open |
| Create NPC / PC / Quest / etc. | Create a new entity from template |
| Open Quest Board | View quests grouped by state |
| Open Campaign Issues | View schema validation errors |
| Open Initiative Tracker | Combat tracker |
| Start Session (layout) | Three-panel session running layout |
| Open NPC Relationship Graph | Visual NPC/faction graph |
| Open PC Sheet | Character sheet viewer + DDB importer |
| Open Campaign Map | Interactive map with fog of war |
| Open Campaign Timeline | Chronological log of all session events |
| Secrets: Add / Reveal / Open pool | Lazy DM secrets & clues pool |
| Auto-link entities in current file | Convert entity names to wikilinks |
| Fix frontmatter position (current file) | Manual repair if another plugin injected content |
The plugin is designed to stay usable on its own, and to interoperate cleanly with a future hosted memory service (campaign-scribe, planned for v0.6) and other tools in the same ecosystem.
Every entity writes an envelope with a version stamp:
id (ULID), kind, aliases, visibility, tagsschema_version: 1canonical_name (optional; falls back to the note's file name)summary (optional, ≤240 characters)created, updated (ISO 8601)NOTICE.md lists the exact values of every shared enum (EntityKind, Visibility, Disposition, NPCStatus, QuestState, LocationType, ItemRarity). Renaming or adding a value is treated as a schema_version bump.
A few things the plugin does not adopt on purpose:
friends:, factions:, etc.) remain canonical, editable directly in Obsidian's Properties panel. When a central relationship service lands, it will merge with those fields rather than replace them — the offline, in-Obsidian experience stays first-class.gm, player, or both. Per-player fog of knowledge is a future concern, not a v0.1 field.MIT. See LICENSE.
This plugin vendors code from Fantasy Statblocks (MIT) and Zoom Map (MIT) — see NOTICE.md for attribution details. These are scheduled for integration in future releases.