No description
- TypeScript 82.8%
- Python 11%
- CSS 5%
- Shell 0.7%
- HTML 0.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| backend | ||
| frontend | ||
| scripts | ||
| shared | ||
| .gitignore | ||
| AGENTS.md | ||
| biome.json | ||
| config.yaml | ||
| package-lock.json | ||
| package.json | ||
| project.md | ||
| README.md | ||
| tsconfig.json | ||
D&D RAG — AI-Powered D&D 5e Reference & Dungeon Master
A local web app that combines RAG over the full 5e.tools dataset with an AI Dungeon Master.
Features
- Reference Mode: Ask any D&D 5e rules question. The AI answers backed by real-time semantic search across spells, monsters, classes, items, feats, backgrounds, rules, and adventures.
- DM Mode: The AI acts as your Dungeon Master, narrating the story, adjudicating actions, and running combat. An OOC sidebar lets you pause for meta-discussion.
- Proactive RAG: The agent silently injects relevant rules into context before every turn, so the DM often knows the answer before asking.
- Dice Roller: Built-in dice notation parser (
2d6+3,1d20kh1,4d6k3) with animated rolls and history. - Fantasy UI: Parchment light mode, obsidian dark mode, with responsive design for desktop and mobile.
- Fully Local: Everything runs on your machine. No accounts, no cloud. Use local LLMs (Ollama) or API providers (Anthropic, OpenAI, etc.).
Screenshot
Prerequisites
- Node.js 20+ and npm 10+
- Python 3.10+ (for data ingestion)
- Git (for downloading 5e.tools data)
Optional:
- An API key for your chosen LLM provider (Anthropic, OpenAI, Google, etc.)
- Or a local LLM via Ollama or LM Studio
Installation
# 1. Clone and install Node dependencies
git clone <your-repo-url>
cd dnd-rag
npm install
# 2. Download 5e.tools data
bash scripts/download.sh
# 3. Set up Python environment and ingest data
python3 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r scripts/requirements.txt
npm run ingest
# 4. Configure your LLM
cp config.yaml.example config.yaml
# Edit config.yaml with your API key or local LLM settings
Running
# Development mode — starts backend (port 3000) + frontend (Vite proxy)
npm run dev
# Then open http://localhost:5173 in your browser
Other Commands
npm run build # Production build (frontend + backend)
npm run start # Production start
npm run lint # Biome lint + format check
npm run lint:fix # Auto-fix lint issues
npm run typecheck # TypeScript check across all workspaces
npm run ingest # Re-run data ingestion
npm run ingest:force # Force full re-ingestion (clears existing DB)
Configuration
All settings live in config.yaml at the project root:
# === LLM ===
llm:
provider: anthropic # anthropic | openai | google | ollama | openai-compatible
model: claude-sonnet-4-5-20250929
api_key: ${ANTHROPIC_API_KEY} # Or set directly (not recommended)
# base_url: http://localhost:11434/v1 # For local LLMs
# === Embeddings ===
embeddings:
provider: local
model: BAAI/bge-small-en-v1.5
# For OpenAI embeddings:
# provider: openai
# model: text-embedding-3-small
# api_key: ${OPENAI_API_KEY}
# === RAG ===
rag:
data_dir: ./5e-data
vector_db_path: ./data/vectordb
chunk_size: 500
chunk_overlap: 50
top_k: 5
proactive_search: true
proactive_top_k: 3
# === Server ===
server:
port: 3000
host: localhost
# === DM Mode ===
dm:
default_edition: 2024
style: theatrical # theatrical | gritty | comedic | by-the-book
rule_strictness: moderate # strict | moderate | loose
auto_roll_dice: true
narration_detail: high # low | medium | high
You can also edit configuration from the Settings UI (gear icon in the header).
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Frontend │
│ React 19 + Tailwind v4 + Vite │
│ ├── ChatPanel (main chat stream) │
│ ├── OocSidebar (out-of-character, DM mode only) │
│ ├── InputBar + DiceRoller │
│ └── SettingsModal │
└──────────────────────┬────────────────────────────────────────┘
│ WebSocket / REST
┌──────────────────────▼────────────────────────────────────────┐
│ Backend │
│ Hono (Node.js) │
│ ├── Agent runtime (custom, OpenAI-compatible API) │
│ ├── RAG tools (dnd_rules_search, roll_dice, send_to_dm) │
│ ├── WebSocket relay for streaming events │
│ └── REST API (/api/search, /api/roll, /api/config) │
└──────────────────────┬────────────────────────────────────────┘
│
┌──────────────────────▼────────────────────────────────────────┐
│ Data Layer │
│ LanceDB (embedded vector DB) │
│ └── Ingested from 5e.tools JSON via Python script │
└──────────────────────────────────────────────────────────────┘
Key Design Decisions
- LanceDB over ChromaDB: Zero-setup embedded vector database with hybrid search (semantic + full-text). No server process required.
- Custom agent runtime instead of Pi harness: Phase 2 implemented a lightweight agent loop with tool calling and streaming events, built directly on the OpenAI-compatible chat completions API.
- Proactive RAG: The
transformContexthook extracts keywords from the last user message and searches LanceDB before each LLM call, injecting relevant rules silently into the system message.
Dice Notation
The built-in dice roller supports standard D&D notation:
| Notation | Meaning | Example |
|---|---|---|
XdY |
Roll X dice with Y sides | 3d6 |
XdY+Z |
Add modifier | 2d6+3 |
XdYkhN |
Keep highest N | 2d20kh1 (advantage) |
XdYklN |
Keep lowest N | 2d20kl1 (disadvantage) |
XdYkN |
Keep highest N (shorthand) | 4d6k3 |
XdYro<Z |
Reroll once if < Z | 1d6ro<3 |
Data Source
This project uses data from 5e.tools, distributed under the CC-BY-SA 4.0 license. The data covers all official D&D 5e content including:
- Player's Handbook, Dungeon Master's Guide, Monster Manual
- Xanathar's Guide, Tasha's Cauldron, Fizban's Treasury
- Mordenkainen's Monsters of the Multiverse
- And 50+ other sourcebooks and adventures
License
MIT License — see LICENSE for details.
The D&D game rules and sourcebook data used by this application are property of Wizards of the Coast and are distributed by 5e.tools under CC-BY-SA 4.0.
Development
Project Structure
dnd-rag/
├── config.yaml # Main configuration
├── package.json # Root workspace config
├── scripts/
│ ├── download.sh # Download 5e.tools data
│ ├── ingest.py # Parse → chunk → embed → LanceDB
│ └── requirements.txt # Python dependencies
├── backend/ # Hono server (TypeScript)
│ └── src/
│ ├── index.ts # Server entry
│ ├── agent.ts # Agent runtime + LLM client
│ ├── tools.ts # Tool definitions
│ ├── vectordb.ts # LanceDB queries
│ ├── prompts.ts # System prompts
│ ├── config.ts # Config loader
│ ├── ws.ts # WebSocket handler
│ └── routes/api.ts # REST endpoints
├── frontend/ # React 19 + Tailwind v4
│ └── src/
│ ├── App.tsx
│ ├── components/ # UI components
│ ├── hooks/ # React hooks
│ ├── context/ # App state
│ └── styles/
└── shared/ # Shared types + dice parser
└── src/
├── types.ts
└── dice.ts
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | React 19, Tailwind CSS v4, Vite |
| Backend | Hono, WebSocket, TypeScript |
| Vector DB | LanceDB (embedded) |
| Embeddings | sentence-transformers (local) or OpenAI API |
| LLM | Anthropic, OpenAI, Google, Ollama, or any OpenAI-compatible API |
| Build | Biome (lint + format), TypeScript |