Local-first D&D web app powered by Ollama. The app runs a local Dungeon Master model, a smaller utility model for rules/state/action extraction, streamed responses, dice prompts, reusable heroes, campaign history, and optional PDF lore/RAG.
- Local DM narration through Ollama
- Separate utility model for dice checks, scene state, and player choices
- FastAPI backend with streamed Server-Sent Events
- Vite React frontend launched by Bun
- SQLite app database through SQLModel
- LanceDB local vector store for uploaded PDF lore
- Hero manager with reusable player characters
- Campaign intro generation from the campaign brief and selected heroes
- Click-to-roll dice checks when the rules referee requires uncertainty
The launcher installs/syncs Python packages with uv and frontend packages with Bun. If uv is missing, it attempts to install it with Python.
git clone https://github.com/tegridydev/dnd-llm-game.git
cd dndllm26
bun run devThe launcher will:
- create/sync
.venv - install frontend packages
- start FastAPI on
http://127.0.0.1:8765 - start Vite on
http://localhost:5173 - open the browser automatically
Start Ollama first:
ollama servePull the default models:
ollama pull llama3.2:1b
ollama pull granite4:350m
ollama pull nomic-embed-textCopy .env.example to .env if you want custom models or ports:
cp .env.example .envModel settings:
OLLAMA_CHAT_MODEL=llama3.2:1b
OLLAMA_UTILITY_MODEL=granite4:350m
OLLAMA_EMBED_MODEL=nomic-embed-textOLLAMA_CHAT_MODEL is the main DM narrator. OLLAMA_UTILITY_MODEL should be a smaller/faster model used for dice decisions, world-state extraction, and dynamic player choices. If it is blank, the app falls back to the main chat model.
Upload PDFs from the Lore panel, or place PDFs in data/uploads. The app discovers queued PDFs and indexes them into LanceDB using the configured embedding model. Indexed lore is retrieved into DM prompts and rules/state context.
Runtime data is stored in data/ and is intentionally ignored by git.
bun run dev # sync deps, start backend + frontend, open browser
bun run start # same as dev
bun run build # type-check and build the frontendbackend/dndllm26/api: FastAPI routesbackend/dndllm26/core: settingsbackend/dndllm26/db: SQLite models and sessionsbackend/dndllm26/game: campaign, dice, hero, and world-state orchestrationbackend/dndllm26/llm: Ollama clientbackend/dndllm26/rag: PDF extraction, chunking, LanceDB searchfrontend/src: React app and stylesscripts/start-dev.ts: one-command local launcher
DM responses are capped for playability (Feel free to change and experiment!): max 1000 characters and max 200 words. The utility model generates the player-choice buttons after each DM response, so the main DM can focus on narration.
