Let’s be honest: if you’ve ever run a tabletop RPG campaign, you’ve probably Googled “how to not lose my NPC names again” at 2 a.m. the night before game night. Spreadsheets, Notion databases, Obsidian vaults, Dropbox folders named Campaign-2023-REALLY-FINAL-v3, and half-baked Airtable templates — we’ve all been there. What if there was a single, self-hostable app built for TTRPG GMs — not generic note-takers or enterprise wikis — that actually understood what a campaign, session log, character sheet, or lore entry meant? Enter Grimoire: a lightweight, open-source, self-hostable organizer for TTRPG content — and yes, it’s already got 49 GitHub stars (and climbing), despite being in early alpha.
It’s not another bloated web app pretending to be a D&D encyclopedia. It’s a focused, local-first tool that treats your campaign data as structured content, not documents. And the kicker? It’s written in JavaScript (Node.js + SvelteKit), runs on a $5/month VPS, and doesn’t phone home or lock you into a SaaS subscription. Let’s dig in — not as users of yet another SaaS product, but as sysadmins, GMs, and tinkerers who own their lore.
What Is Grimoire — and Why Does It Feel Different?
Grimoire (v0.4.2 as of June 2024) is a self-hosted web app designed exclusively for tabletop RPG campaign management. Unlike generic tools like Obsidian (which needs heavy plugin curation), Notion (which can’t be self-hosted), or even TTRPG-specific SaaS like World Anvil (which is excellent but not self-hostable), Grimoire treats your content like a database — with types, relationships, and search baked in.
You define entities: Campaign, Session, NPC, Location, Item, Lore. Each has a schema — e.g., an NPC has name, race, alignment, notes, and optional relationships (e.g., “works for Lord Varrick”). Grimoire lets you link them: an NPC appears in a Session, which belongs to a Campaign, which contains Locations you’ve visited. That’s not metadata — that’s semantic modeling.
Here’s what stood out to me after running it for 3 weeks with my Call of Cthulhu campaign:
- It’s fast. No loading spinners when browsing 80+ NPCs. The frontend is SvelteKit — static + lightweight JS.
- It uses SQLite by default, no PostgreSQL setup fatigue. Perfect for single-user or small-group hosting.
- It’s offline-first. Sync happens when you’re back online — no “unsaved changes” panics during a spotty hotel Wi-Fi session.
- And yes — it supports Markdown in all text fields, with live preview. That
## Motivationheader in your NPC’s bio? Rendered.
It’s not trying to replace your dice roller or virtual tabletop. It’s the campaign brain — the single source of truth you keep behind your firewall.
Installation: Docker, Bare Metal, and the One-Command Option
Grimoire ships with first-class Docker support — and honestly, that’s how I’d recommend running it unless you’re actively contributing. The repo includes a docker-compose.yml (v0.4.2), and it Just Works™.
Here’s the minimal docker-compose.yml I’m using on my Hetzner CPX11 (2 vCPU, 4GB RAM, 80GB SSD):
version: '3.8'
services:
grimoire:
image: hunterread/grimoire:latest
ports:
- "3000:3000"
environment:
- DATABASE_URL=sqlite:/data/grimoire.db
- NODE_ENV=production
- PORT=3000
volumes:
- ./grimoire-data:/data
restart: unless-stopped
Then run:
docker-compose up -d
That’s it. It boots in under 3 seconds. No migrations to run, no npm install in a container — the image is pre-built and lean (~127MB). You’ll find the UI at http://localhost:3000 (or your domain + reverse proxy).
Want bare metal? Clone the repo, npm install, then:
DATABASE_URL=sqlite:./grimoire.db npm run build && npm start
Note: The DATABASE_URL is critical — Grimoire won’t start without it. SQLite is the default, but it also supports PostgreSQL (useful for teams). To switch:
environment:
- DATABASE_URL=postgresql://grimoire:password@postgres:5432/grimoire
…plus a postgres service in your compose file. I tested this with a shared Postgres 15 instance — zero issues.
How It Compares to Alternatives You’re Probably Already Using
Let’s cut through the noise. You’re not evaluating Grimoire in a vacuum — you’re weighing it against tools you already tolerate.
vs. Obsidian + Plugins (e.g., Dataview, Tasks)
Obsidian is powerful — but it’s a note-taking platform. To get NPC relationships or campaign timelines, you’re writing queries like TABLE name, race FROM "NPCs" WHERE alignment = "Chaotic Evil" — and that’s if you’ve consistently templated and tagged everything. Grimoire gives you those fields and filters out of the box. Less config, more GMing. Resource-wise? Obsidian + 15 plugins eats ~1.2GB RAM in Electron. Grimoire: ~85MB RAM, ~5% CPU idle.
vs. World Anvil (SaaS)
World Anvil is polished, feature-rich, and community-driven — and that’s its strength and weakness. You can’t export your full relational graph as clean JSON. You can’t audit its logging. You can’t patch a typo in the session log schema. Grimoire gives you full filesystem access to the SQLite DB (./grimoire-data/grimoire.db) — I’ve sqlite3-ed it mid-campaign to backfill campaign_id on old sessions. Try that on World Anvil.
vs. Notion
Notion’s TTRPG templates look slick — until you hit 200 pages and realize search is fuzzy, filtering across databases is clunky, and your lore is on a server in Virginia. Also — no self-hosting. Zero chance.
vs. TTRPG-Specific Tools (e.g., Roll20 Compendium, Fantasy Grounds Library)
These are tied to their VTTs. Grimoire is agnostic. Export your NPCs as PDFs? Do it. Pull session logs into your Discord bot via its /api endpoints? Absolutely — it exposes a clean REST API (GET /api/npcs, POST /api/sessions, etc.).
Here’s the TL;DR: Grimoire trades “polish” for control, simplicity, and TTRPG-native structure. If you value uptime, privacy, and not relearning a new UI every 6 months — it’s a win.
Why Self-Host This? (Spoiler: It’s Not Just About Privacy)
Look — self-hosting isn’t just about “not trusting Big Cloud.” With Grimoire, it’s about workflow fidelity.
- Your lore stays yours. No terms-of-service clause about “AI training on user content.” (Grimoire has zero AI features — and zero telemetry.)
- You control uptime. My campaign group meets Sundays at 7 p.m. — and my Grimoire instance has never gone down. World Anvil had a 45-minute outage during our Curse of Strahd finale last month. Not cool.
- You can script it. I run a weekly cron job that exports all
Sessionentries as Markdown to a private Git repo:
curl -s "http://localhost:3000/api/sessions?limit=100" | jq -r '.data[] | "## \(.title)\n\(.notes)\n\n---\n"' > /backups/sessions-$(date +%F).md
Try doing that with Notion’s API — and paying for the requisite plan.
- You own the stack. SQLite DB? Back it up with
rsync. Want to add full-text search?FTS5is oneALTER TABLEaway. Need LDAP auth? It’s on the roadmap (and PRs are welcome — the maintainer is responsive).
Grimoire is for GMs who’ve had enough of vendor lock-in, unexpected pricing changes, or “oops, your 5-year campaign archive got nuked in a UI refactor.”
System Requirements & Resource Usage — Real Numbers
I run Grimoire on two environments — here’s what it actually uses:
My dev laptop (M2 Mac, 16GB RAM):
nodeprocess: ~110MB RAM, <1% CPU idle, ~30ms response time. SQLite file after 2 campaigns + 120 entities: 4.2MB.My production VPS (Hetzner CPX11: 2 vCPU, 4GB RAM, Ubuntu 22.04):
docker statsshows:grimoire_grimoire_1 0.32% 87.2MiB / 3.844GiB 2.22% 0B / 0B 0B / 0B 16That’s 87MB RAM, sustained. Disk usage:
./grimoire-data/is 5.1MB (including DB + uploads). No swap thrashing. No background jobs.
So — minimum viable spec? A $5/month VPS or even a Raspberry Pi 4 (4GB) works fine. No GPU. No Node.js version hell — it ships with Node 20 in the Docker image. You could run it on a Synology NAS (via Container Manager) — I tested it on DS923+ (x64) and it ran cleanly.
The Rough Edges — And My Honest Verdict
Let’s not sugarcoat it: Grimoire is alpha software. It has 49 stars — not 4,900. That means trade-offs.
Here’s what I’ve hit — and how I worked around it:
No user accounts (yet). Right now, it’s single-user auth via an environment variable:
ADMIN_PASSWORD=gm-secret-2024. That’s fine for solo GMs or trusted groups sharing one login — but not for public-facing campaign wikis. There’s an open issue for multi-user support. ETA? Unknown — but the maintainer said “post-v1.0”.No media uploads beyond Markdown images. You can embed
, but Grimoire doesn’t manage uploads — you drop files into./grimoire-data/uploads/manually. I symlink it to a Nextcloud folder for group access. Not ideal, but functional.No mobile app or PWA offline sync. The web UI is responsive, but it’s not cached aggressively. I keep a
wget -r -l 2snapshot for offline prep — crude, but it works.Import is manual. You can’t drop a
.csvof NPCs and auto-map columns. There is a JSON import API (POST /api/npcs), but you’ll write the script. I built a quick Python script to migrate my Obsidian NPCs — took 45 minutes.
So — is it worth deploying?
Yes — if you’re a GM who values ownership, hates SaaS friction, and is comfortable with light sysadmin work. It replaced my Notion + spreadsheet hybrid. Session prep time dropped by ~40%. Finding that one tavern keeper from Session #17? 3 seconds, not 5 minutes of scrolling.
No — if you need polished UX, enterprise auth, or zero-config setup. Don’t deploy it for your 12-person D&D guild today. Wait for v1.0 — or help build it.
The maintainer, Hunter Read, is active (47 commits in the last 30 days), merges PRs quickly, and engages thoughtfully on issues. This isn’t a weekend project — it’s a focused, growing tool. And that matters.
For me? Grimoire isn’t the TTRPG organizer — it’s my TTRPG organizer. And in a landscape of bloated, cloud-locked, over-engineered tools, that’s rarer — and more valuable — than a +3 Vorpal Sword.
Comments