Campaign Writing Best Practices
Essential tips and patterns for writing excellent dynamic campaigns.
Placeholder Best Practices
1. Always Use Placeholders for Locations
✓ Good: "Travel to {nearestBurg}"
✗ Bad: "Travel to Millhaven"
✗ Bad: "Travel to Millhaven"
A hardcoded name assumes every party's generated roster happens to include a town by that exact name - it won't. Placeholders resolve to whatever that specific party's roster actually contains.
2. Keep Low-Level Adventures Small
✓ Good: {randomBurg:maxPopulation=300}
✗ Bad: {randomBurg} // Could resolve to a major city
✗ Bad: {randomBurg} // Could resolve to a major city
See Scope Control for the full strategy - population is the one dimension you can actually filter on.
3. Match Population to Context
✓ Good: "Small village: {randomBurg:maxPopulation=300}"
✗ Bad: "Small village: {randomBurg}" // Might be a city
✗ Bad: "Small village: {randomBurg}" // Might be a city
Quest Action Best Practices
1. Always Accept Before Complete
✓ Good: Scene 1: accept → Scene 5: complete
✗ Bad: Scene 5: complete (never accepted)
✗ Bad: Scene 5: complete (never accepted)
2. Provide Failure Paths for DC Checks
✓ Good: "DC 15 - PASS" and "DC 15 - FAIL" choices
✗ Bad: Only success option
✗ Bad: Only success option
3. Use Exact Quest Names
✓ Good: "accept:The Missing Merchant"
✗ Bad: "accept:Missing Merchant"
✗ Bad: "accept:Missing Merchant"
Scene Writing Best Practices
1. Write Vivid Descriptions
Make scenes come alive with sensory details:
"readAloud": "<div class='read-aloud'><p>The tavern reeks of stale ale and wood smoke. A cloaked figure beckons from the shadows...</p></div>"
2. Keep Scenes Focused
One scene = one decision point or narrative beat.
3. Provide Clear Choices
✓ Good: "Investigate the noise" (clear action)
✗ Bad: "Do something" (vague)
✗ Bad: "Do something" (vague)
Campaign Structure Best Practices
1. Start Small
First campaign: 1 episode, 1 quest, 5-7 scenes.
2. Test Early and Often
Load your campaign after every major addition.
3. Use Consistent Naming
Scene IDs: ep1-scene1, ep1-scene2, ep1-scene3
Quest IDs: my-campaign-id (kebab-case)
Quest IDs: my-campaign-id (kebab-case)
Common Mistakes to Avoid
| Mistake | Why It's Bad | Solution |
|---|---|---|
| Hardcoded location names | Won't work for other parties' generated rosters | Use placeholders |
| No failure paths | Removes player agency | Add failure options |
| Unscoped locations on level 1 quests | A major city feels wrong for a low-stakes lead | Use maxPopulation |
| Typos in quest names | Quest actions won't work | Copy-paste from questTemplates |
Quality Checklist
Before publishing your campaign:
- ☐ All locations use placeholders (no hardcoded names)
- ☐ Low-level quests use
maxPopulationto stay small - ☐ All DC checks have success AND failure paths
- ☐ Quest names match exactly between scenes and templates
- ☐ All scenes have at least one choice
- ☐ Scene IDs follow naming convention (ep1-scene1)
- ☐ Tested in Campaign Cookbook Testbed(no errors)
- ☐ JSON validates (no syntax errors)
See Also
- Scope Control - Keep adventures local
- Basic Campaign Example - See best practices in action
- Quick Start - Step-by-step guide