D&D Campaign App
Built with heavy AI assistance (Claude Code). The feature scope, tech stack constraints, and search design were mine.
Premise
In my personal time, I DM a campaign set in a world I wrote myself, and I was struggling to keep track of all of it: places, people, and events. My lore was scattered across numerous Google Drive documents, in varying stages of being copied to World Anvil, where I hoped to eventually keep everything.
Problem
One day when I was trying to prep, after a relatively long hiatus, I realized I knew I had given my players the name of an NPC but I had no idea what that NPC's name was, or even where to look for it. Having recently started using AI a lot in my work, I knew AI could search across all of this content for me, if only it had access. The problem was, I didn't pay for AI usage in my personal life, and I didn't want to add that cost for something so simple.
I was also struggling with the prep itself. I prep on my laptop so I can bring it to my friend's house where we play, and on that screen the World Anvil interface didn't work well for me. I'd often have four different documents open just to run a session. If I could put my own interface over my World Anvil data, one that worked better for my brain, both prepping and running sessions would be much easier.
Solution
So I set out to build, with AI doing most of the coding, a simple app for my personal use that would:
- Connect to my google drive and search a specific folder of documents
- Connect to World Anvil and search all my previous session prep, my session notes, and my lore articles
- Connect to World Anvil and display my current session prep, my previous session notes, and whatever else I need to both prep for a session, and also to run that session
In the end, I ended up with a fairly sophisticated app that does way more than I had originally planned and I love it. It has so many additional baked in features such as:
- Name generator, following my in world lore rules for different races
- A calendar tracker that allows me to advance time and keep track of what the current date is in game
- A media library of purchased audio tracks that I can attach to any note and play during a session
Constraints
I gave the AI agent some very specific constraints when building the app. I wanted the tech stack to be something I could understand so that if I ever wanted to work on it directly in the future, I'd understand what's under the hood:
- Simple JS/CSS
- PHP
- Gemini API
- A local LLM, called from PHP
- Google Drive API, and World Anvil API
Challenges
Along the way I ran into a handful of issues, such as having to wait for approval and application keys before I could use the World Anvil APIs, or AI just being outright incorrect. The most interesting exercise was getting the AI powered "spicy Google" working for retrieving my lore content.
Initially AI told me I didn't even need to use AI to search for my content, which was technically true, it posed a solution which could return me WHICH article was MOST LIKELY to contain the result I was looking for pretty easily. In practice, it brought back a lot of false positives. For example, when I searched for "who is the metal man," it found a suit of armor, because armor is made of metal and mentioned numerous times, instead of the character with the literal nickname "metal man," who is only mentioned once.
After some further exploration, I not only found out I needed AI to synthesize the response for me, turning "this article" into "human-style response to your question", but that I also needed it to break down my initial question. When I'm searching for "Who is Tabys' black market contact" it's important to know "Who is Tabys" and "What is the black market" and "Who does Tabys know" which weren't all things that appeared in the same article, or in a sentence altogether, and the LLM aided in synthesizing the response into a "most likely" answer by piecing together "Tabys has a random name written in a book. Tabys was interacting with the black market. Most likely, that random name is the name of her black market contact."
In the end, I ended up with a solution where a local lightweight LLM will parse my initial question into a set of keywords to search for, then run a set of queries against my lore looking for those keywords, then pass off the highest hits of those results to a more powerful AI agent such as Gemini in order to piece together the disjointed information.
It still needs polish. Searches can be slow, sometimes taking over half an hour, which I plan to look into in the future. But I'm pleased with the accuracy: when I ask it "Who is the metal man?" it now answers "Nightshade."
Kia Skretteberg