This project is a Curse of Strahd campaign turned into a living compendium: a large, searchable library of game content plus a set of files that track the campaign's state as it actually changes. If you clone it to build your own game, this chapter explains the bones.
Two layers
The project is deliberately split in two:
- The compendium — static content: characters, locations, quests, creatures, spells, magic items, rules, lore. These files rarely change once written, and they are the shared vocabulary of the world.
- The state — live content: the campaign state, world state, settlement status, party treasury, faction reputations, corruption trackers. These files move every session, and they are the memory the game runs on.
Keep the two layers honest. Don't bury a session outcome in a lore file, and don't put world lore in the campaign state. If it happened once, it belongs in state. If it is always true, it belongs in the compendium.
File types and folders
Each file type lives in a folder named for its plural form, and files end with the type's slug: /Characters/Ireena Kolyana.character.json, /Locations/Vallaki.location.json, /Lore/The Mists of Ravenloft.lore.md. Folders are the browseable index; the file type schema is the contract.
- JSON types — structured data with a schema and a rendered layout (characters, locations, quests, creatures, spells, items, encounters, schedules, trackers).
- Markdown types — prose (lore, rules, glossary entries, GM instructions). A markdown file's
body is the content.
Markdown types have no rendered layout and are searched by content. Use JSON types for anything the game needs to read as data — stats, references, status. Use markdown for anything it needs to read as text — explanations, flavor, procedures.
Slugs and references
A file's name becomes its slug (lowercased, spaces to dashes): Blue Water Inn → blue-water-inn. Reference fields point at other files by slug — a character's equippedArmor is leather-armor, a quest's location is church-of-saint-andral. When you rename a file, every reference to its slug breaks, so treat slugs as public API: rename deliberately, and update references in the same pass.
The voice
Every written field shares one register: the cursed atlas voice. Descriptions read like entries in a haunted ecclesiastical record — atmospheric, specific, slightly formal, never comic. GM-facing notes can be plainer (they're operational), but the player-facing fields (description, atmosphere, appearance) should feel like they were written by someone who has been there and barely survived. Match the tone of existing files when you add new ones.