CampaignRepo
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 6 GitHub stars
Code Warn
- network request — Outbound network request in app/admin/users-client.tsx
- process.env — Environment variable access in app/api/auth/oauth/[provider]/callback/route.ts
- network request — Outbound network request in app/api/auth/oauth/[provider]/callback/route.ts
- process.env — Environment variable access in app/api/auth/oauth/[provider]/start/route.ts
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
A self-hosted, Git-backed campaign manager for tabletop RPGs with wiki pages, player-safe portals, maps, sessions, quests, imports, AI tools, and MCP support.
CampaignRepo
A campaign wiki built for the table, not the desk. CampaignRepo turns a plain
Markdown repository into a shared wiki where the GM keeps secrets, players see
only what they should, and an AI can help fill it all in — while every word
stays as portable Markdown in a repo you own.
Your whole world lives in a normal GitHub repo (or a local folder). A
purpose-built web app renders it as a wiki, map viewer, relationship graph,
session tracker, calendar, and character-sheet system — but nothing requires
CampaignRepo to read your files. Delete the app tomorrow and you still have a
clean folder of Markdown.
Why not just use Obsidian (or Notion, or a Google Doc)?
Those are excellent tools — for one person taking notes. Running a game is a
different job: you are keeping secrets from the very people you are sharing with,
across sessions, for months. That is the job CampaignRepo is built for.
| CampaignRepo | Obsidian / Notion / Docs | |
|---|---|---|
| Running a game for others | Built in: GM/player roles, a review queue, and a no-login player portal | You are the only user; sharing means a second copy or a paid sync add-on |
| Secrets on the page | :::gm blocks — the same page shows the villain's true plan to you and only the rumor to players |
You redact by hand, or keep two vaults in sync |
| Knows it's a TTRPG tool | Character sheets for 40+ systems, a relationship graph, family trees, sessions, quests, a fantasy calendar, and battle maps — out of the box | A pile of community plugins you assemble and maintain yourself |
| AI that touches your world | An MCP endpoint lets Claude read and write your campaign — and its changes wait in your review queue | Not native; copy-paste in and out |
| Sharing a whole world | A public gallery: publish your setting, or clone someone else's as a starting point | Export a zip and hope the other person can import it |
| Your files | Plain Markdown in your GitHub repo — versioned, diffable, yours | Plain Markdown on your disk — also yours (this part they get right) |
The honest version: if you keep a solo worldbuilding vault and never share it,
Obsidian is wonderful and you should keep using it. The moment real players,
hidden lore, and "what did we decide three sessions ago?" enter the picture,
those tools make you do the coordination by hand. CampaignRepo does it for you —
without giving up the portable-Markdown promise that made you trust them.
What it does for your game — at the table
- Prep once, reveal slowly. Write the secret and its public face on one page.
Players only ever load the public half; you flip a switch when they earn the rest. - Never lose the thread. A relationship graph answers "wait, how does this NPC
connect to the cult?" at a glance, and full-text search is instant even mid-scene
because reads are served locally, not fetched from GitHub every time. - Give players a living recap. Send one link to a no-login site that shows only
approved, player-safe lore and open quests — their window into the world between games. - Turn notes into canon. After a session, hand your scrawl to the built-in AI (or
your own MCP client) and it drafts linked, categorized pages — that land unapproved
in your queue, so the AI never rewrites your canon behind your back. - Run the fiddly bits. Session agendas, quest clocks, a custom calendar, initiative
and world timelines, character sheets that actually render for your system.
Status
CampaignRepo is a working, self-hostable app (Docker/GHCR), not a prototype:
GitHub-backed and local campaigns, GM workspaces, player portals, public
discovery and world-cloning, sessions, quests, calendars, maps, graphs, imports,
AI/MCP, and full backups all ship today. The active focus is reliability — see
ROADMAP.md for the app-first, Git-backed sync work and the biggest
hidden risks.
Product Tour
Campaign Dashboard
Search across every connected campaign, open a repo, or expand setup tools only when you need them. Once GitHub is connected, setup panels stay collapsed by default.

Campaign Workspace
Each campaign has a workspace with a wiki, maps, relationship graph, timeline, calendar, session board, quest tracker, media manager, settings, and health center. Campaign themes reskin the workspace for any RPG system.

Wiki Page Editor
Pages are Markdown with YAML frontmatter. The editor shows source and preview side by side, with a slash-command menu, format toolbar, paste-to-upload images, wiki-link insert, gallery blocks, transclusion, and GM-only blocks.

GM Review Queue
AI-created, imported, or otherwise unapproved content waits for GM review before it becomes player-visible.

Player Portal
Players see only pages that are both approved and marked player-visible. GM-only blocks, import metadata, and draft content are stripped.

What CampaignRepo Does
- Stores everything in Git: pages, media, maps, sessions, quests, templates, calendar config, and campaign settings as Markdown and YAML.
- Loads campaign navigation from a generated
.campaignrepo/index.jsonmanifest, so large repos do not need to enumerate every folder or download every Markdown file on startup. - Renders wiki pages with
[[links]], aliases, backlinks, covers, galleries, transclusion, and:::gmsecret blocks. - Provides an interactive map viewer with pins, player/GM layers, nested map links, and article panels.
- Shows a force-directed relationship graph with typed edges, category filters, and a detail panel.
- Tracks quests with objectives, faction clocks, participant links, and arc grouping.
- Runs a session workspace with agenda checklists, pinned pages, GM notes, handout queues, and session-to-event report generation.
- Manages a custom fantasy calendar with configurable months, weekdays, and eras - and a world timeline across sessions and events.
- Keeps a version history for every page with diff and restore-to-editor workflows.
- Publishes a no-login public site for approved, player-visible lore and quests - shareable and cloneable.
- Sends in-app notifications for review requests, assignments, mentions, and watched page changes.
- Imports from Foundry actors and journals, character JSON, Obsidian, Notion, Google Docs, CSV, Roll20, LegendKeeper, World Anvil, and other world/journal exports.
- Exports a full CampaignRepo backup as ZIP or JSON, including pages, media, maps, sessions, quests, search data, templates, and settings.
- Offers AI page generation and full-campaign Q&A over Markdown with citations.
- Exposes an MCP JSON-RPC API for AI tools and external clients.
FAQ
Do I need to know Git or GitHub?
No. Connect a repo once and the app handles every commit, push, and pull in the
background. You edit in the browser. (If you do know Git, everything is plain
Markdown you can also edit directly — the app catches up on the next sync.)
Do my players need accounts?
No. Publish your campaign and share one link — the public player portal shows only
approved, player-visible pages, with no login. Accounts are for you and your
co-GMs, not the table.
What happens to my world if CampaignRepo goes away?
Nothing. It was never locked in the app. Your campaign is a folder of Markdown and
YAML in your own GitHub repo; the generated index and search files are disposable
snapshots. Clone the repo and you have the whole world, readable in any text editor.
Is it free? Can I self-host?
Yes. CampaignRepo ships as a Docker image (GHCR) you run yourself. See
Docker and Quick Start.
Which game systems does it support?
Any system works as a wiki. On top of that, dozens of systems ship a ready-made
starter kit, and the most popular ones — D&D 5e, Pathfinder 2e, Traveller, the
World of Darkness lines, Dune, Call of Cthulhu, Cyberpunk RED, Blades in the Dark,
and more — get real, rendered character sheets rather than plain tables.
Can I bring my existing notes?
Yes. Importers cover Obsidian, Notion, Google Docs, Foundry (actors and journals),
Roll20, LegendKeeper, World Anvil, character JSON, and CSV. You don't have to start
from a blank page.
Won't the AI mess with my canon?
No — that's the point of the review queue. Anything the AI (or an import) creates
lands as unapproved and invisible to players until you approve it. The AI can
draft; only you canonize.
How is this different from a private GitHub wiki?
A GitHub wiki is raw pages with no notion of players, secrets, sessions, or sheets.
CampaignRepo adds per-page visibility and :::gm blocks, a player portal, character
sheets, a relationship graph, session and quest tracking, maps, and AI — while still
being just Markdown in a repo underneath.
Is it any good for solo worldbuilding?
It's fine — but if you never share your world and never hide lore from players,
you're not using the parts that make it worth switching from a local notes app.
CampaignRepo earns its keep the moment other people join your table.
Core Features
Accounts and Permissions
- Local accounts with username/password login.
- Seeded admin account with forced first-login password change.
- Global admin dashboard for users, campaign memberships, roles, password resets, and disabled accounts.
- Per-campaign GM tools for members, invite links, and player access.
- Owner, GM, and player campaign roles.
Storage Backends
- Local folder - no GitHub account required; works offline; compatible with Dropbox, Syncthing, Nextcloud, or OneDrive for optional sync.
- GitHub - version history, offsite backup, collaboration, multi-machine access via GitHub App or personal token.
GitHub-backed campaigns are powerful, but GitHub is not a low-latency database.
The roadmap moves routine editing toward a local DB working copy with queued
Git sync, so page organization and approvals stay fast while repositories
remain the durable archive.
Wiki and Editor
- Markdown pages with YAML frontmatter and structured fields per article type.
- Categories: characters, NPCs, organizations, species, locations, items, events, lore, game notes, and more.
[[Page]]and[[Page|Label]]wiki links, aliases, key links, and backlinks.- Slash-command menu (
/) for headings, tables, code blocks, dividers, GM blocks, transclusion, and task lists. - Paste an image into the editor to upload and insert it in one step.
:::gmGM-only blocks,:::galleryimage grids with lightbox, and:::includetransclusion.- Cover images rendered as article banners.
- Save conflict detection when a file changes after it was opened.
- GM preview, player preview, and handout views.
- In-editor slash commands, format toolbar, and diff-based history restore.
Maps
- Upload a map image and place pins that link to wiki pages.
- Organize pins into player-visible or GM-only layers.
- Mark locations discovered/undiscovered and preview the player-safe map view.
- Link pins to nested maps as well as wiki pages.
- Click a pin to open an article panel without leaving the map.
- Pins stored as portable JSON alongside the map image.
- Early UI exists for routes, regions, measuring, and journeys; the full 2.0 map model still needs complete persistence.
Relationship Graph
- Force-directed SVG graph of all pages as nodes colored by category.
- 20 built-in typed relationships (member-of, located-in, allied-with, parent-of, appears-in-session, and more) with defined inverses.
- Typed edges dashed and labeled on hover; category filter checkboxes and typed-only toggle.
- Click a node to focus: dims unconnected nodes, shows detail panel with outgoing and incoming links.
Family Tree
- Dedicated family-tree route separate from the general relationship graph.
- Shows only family relationships: parent, child, spouse, sibling, guardian, and ward.
- Defaults to hierarchy layout, places spouses beside each other, and uses existing page portraits/images when available.
- Edits write normal relationship frontmatter, so genealogy stays portable in the campaign repo.
Sessions
- Sessions stored as
wiki/sessions/<slug>.mdwith YAML frontmatter and Markdown notes. - Agenda checklist, pinned pages, status, date, private GM notes, and handout queue with copy-link.
- "Make report page" converts checked agenda items and notes into a wiki event page.
- Next-session widget on the campaign overview dashboard.
Quests
- Quests stored as
wiki/quests/<slug>.mdwith status, arc, reward, visibility, objectives, and participant/location links. - Faction clocks: SVG ring segments with click-to-fill and configurable segment count.
- Active quests widget on the campaign overview dashboard.
- Player-visible quests appear in the player portal and public
/site/<slug>view.
Calendar and World Timeline
- Custom calendar per campaign: configurable months (name + length), weekdays, and era name.
- Tracks the current in-world date with weekday-correct formatting.
- Advance the date by day, week, or month from the calendar view.
- World timeline on the calendar page shows past and future sessions and events sorted by in-world date with a "Now" divider.
- Current date widget on the campaign overview dashboard.
Version History and Activity
- History tab in the page reader: last 20 commits with date, author, message, SHA, and GitHub diff link.
- Diff viewer: click-to-compare any historical version against the current text, with colored add/remove/unchanged lines.
- Restore: load any historical version into the editor for review before saving.
- Campaign activity feed on the overview dashboard: last 30 repo commits with author, date, and message.
Campaign Overview Dashboard
- Configurable widget layout stored in
campaign.yaml. - Widgets: page counts, active quests, next session, current calendar date, recent activity, review queue, and campaign health.
- GMs enable/disable and drag-to-reorder widgets; players get a spoiler-safe view (GM-only widgets are never rendered).
Campaign Health Center
- Scans every page for broken wiki links, invalid parents, parent category mismatches, missing media, duplicate aliases, empty names, unapproved pages, orphaned pages (no incoming links and no parent), and oversized media files.
- Findings grouped by type with severity badges and links to affected pages.
- Inline bulk repair: approve all unapproved, clear invalid parents, and more.
Bulk Organization
- Table view for pages with filters, sorting, multi-select, and bulk changes for category, visibility, approval, parent, and tags in one commit.
- Media table with name/type/tag/unused filters, sorting, bulk tag add/remove, and bulk delete.
Character Import Sync
- Single-character JSON imports preserve the original source under
wiki/imports/characters. - Imported pages store the source path, source ID, and stable source hash in frontmatter so later imports can be recognized as new, unchanged, or changed.
Character Sheets
- Traveller (Mongoose 2e): characteristics (STR/DEX/END/INT/EDU/SOC) with computed DMs, skills, weapons, armour, equipment, contacts, and credits. Click any characteristic or skill to roll 2D6 + that modifier with an animated result toast.
- D&D 5e: fenced
dnd-sheetYAML blocks render as designed character sheets, and Foundry D&D actor import can create those blocks. - Pathfinder 2e: fenced
dnd-sheetYAML blocks withsystem: pathfinder2render rank-aware skills, saves, actions, feats, equipment, and spell/focus sections. - World of Darkness: fenced
wod-sheetYAML blocks render World of Darkness style sheets. - Traveller has the most complete editor/roller experience today; D&D, Pathfinder, and World of Darkness still need deeper field editors and more print polish.
Public Site and Discovery
- GMs publish a no-login public site for any campaign at a stable
/site/<slug>URL. - Public link names can be customized from campaign settings.
- Public sites include approved player-visible pages, media, covers, galleries, wiki links, and player-visible quests.
- Individual pages and quests can also get token-based public share links at
/share/<token>. - Public gallery at
/sitelists all published worlds, sorted by most-cloned, with name and system search. - "Clone this world" copies a published campaign into the viewer's own GitHub repo as a new campaign.
- Fork proposals are available for public-world collaboration; true cross-repo GitHub pull requests are still roadmap work.
Command Palette
Cmd/Ctrl+Kfrom any authenticated screen: search pages, navigate to workspace sections, and find media.
Imports and MCP
- Foundry Actor JSON and generic character JSON import with optional field mapping and source diffing for re-import.
- Foundry journal, Obsidian, Notion, Google Docs, CSV, Roll20, LegendKeeper, World Anvil, and world export import routes.
- Basic export downloads as ZIP or JSON from the import/export hub.
- Media upload, rename, delete, captions, alt text, tags, and repo-persisted metadata.
- SQLite full-text search, portable
/wiki/search/index.jsonsnapshots, and the repository navigation manifest at/.campaignrepo/index.json. - MCP JSON-RPC endpoint at
/api/mcpwith tools for search, page reads/creates/updates, templates, media, graph data, review queues, and setup instructions.
AI Tools
- Random-table generators for NPCs, settlements, factions, rumors, quests, and encounters.
- Optional OpenAI-compatible endpoint expansion with generated drafts kept unapproved until reviewed.
- Full-campaign Q&A chat over the search index with page citations.
Collaboration and Workflow
- Review queue for player-visible drafts.
- In-app notifications for review requests, assignments, mentions, and watched page changes.
- Page watches and assignee frontmatter.
- Presence endpoint foundation for future soft locks and live collaboration.
Theming
- Per-campaign accent colors, display font, and banner image stored in
campaign.yaml. - Flagship themes for specific RPG systems (Traveller, Dark Ages: Vampire, and others) with curated palettes and campaign title logos.
- Applied to the workspace, player portal, and public site.
Quick Start
Install dependencies and run the development server:
npm install
npm run dev
Open:
http://127.0.0.1:3000
The local database seeds this first admin account:
Email: [email protected]
Password: admin
CampaignRepo forces the seeded admin password to be changed before the dashboard or APIs can be used.
Common Commands
npm run dev # Start local development server
npm run typecheck # TypeScript check
npm test # Run Vitest tests
npm run build # Production build
npm start # Start built Next.js app
GitHub App Setup
The easiest setup path is from the CampaignRepo dashboard:
- Sign in as a global admin.
- Click Connect GitHub.
- Let GitHub create the CampaignRepo GitHub App from the manifest.
- Choose the campaign repositories the app can access.
- Return to CampaignRepo and connect or repair a campaign repo.
CampaignRepo stores the GitHub App configuration in SQLite and uses short-lived installation tokens for repo access.
To create the GitHub App manually, create a new app at:
https://github.com/settings/apps/new
Use these values:
- Homepage URL: your CampaignRepo URL.
- Callback URL:
https://YOUR-CAMPAIGNREPO-HOST/api/github/app/callback. - Setup URL:
https://YOUR-CAMPAIGNREPO-HOST/api/github/app/callback. - Repository permissions:
- Contents: read/write.
- Metadata: read-only.
- Installation access: only the repositories CampaignRepo should manage.
After adding the GITHUB_APP_* environment variables and restarting the app, use Install or update GitHub App access from the dashboard.
Campaign Repo Layout
CampaignRepo creates and expects this structure inside each campaign repo:
/.campaignrepo
index.json
/wiki
/pages
/media
media.json
/templates/<game-type>
/imports/characters
/sessions
/quests
/maps
/search
index.json
campaign.yaml
README.md
Manual edits are welcome. Preserve YAML frontmatter and CampaignRepo conventions for wiki links, visibility, approvals, and GM-only blocks.
Repository Manifest
CampaignRepo repositories include a generated manifest at:
.campaignrepo/index.json
The manifest is the fast navigation/index layer for CampaignRepo. It stores page IDs, titles, paths, types, tags, aliases, summaries, visibility, approval status, parent metadata, and link metadata. Markdown files remain the canonical source for page content and frontmatter; the manifest does not duplicate full Markdown bodies.
Normal repository loading uses this pattern:
Open campaign:
1. Fetch .campaignrepo/index.json
2. Build sidebar, tags, links, backlinks, and public navigation from the manifest
Open page:
1. Fetch that one Markdown file
2. Render the page body
If .campaignrepo/index.json is missing, CampaignRepo falls back to wiki/search/index.json and older cache/rebuild paths. Rebuilding the search index also writes the repository manifest. Creating a page through CampaignRepo commits the Markdown file and manifest update together, keeping the repository index consistent.
Generated indexes are disposable. If a manifest, search snapshot, or DB cache
disagrees with real page content, the repair path should rebuild generated
state from the canonical page source rather than treating the generated file as
truth.
The Git Trees API is used for recovery and rebuild paths, not as the normal navigation source. The GitHub Contents API remains suitable for reading or writing a single known file.
Visibility Rules
Player safety is based on page metadata and GM-only blocks:
visibility: playersmakes a page eligible for player view.approvalStatus: approvedis required before players can see it.:::gmblocks are removed from player reads.- Source import metadata is hidden from player reads.
- Players can read campaign content without GitHub credentials.
Docker
Run the prebuilt image from GitHub Container Registry:
docker compose -f docker-compose.image.yml up -d
The published image is:
ghcr.io/avorial/campaignrepo:latest
For Portainer, create a stack from docker-compose.image.yml or use this image in your own compose file. The SQLite database is stored in the campaignrepo-data volume at /app/data.
After the first publish, make the GHCR package public in GitHub Packages if you want unauthenticated pulls.
To build locally instead:
docker compose up -d --build
Open:
http://127.0.0.1:3000
Useful environment variables:
APP_URL=https://campaignrepo.example.com
SECURE_COOKIES=true
GITHUB_APP_ID=123456
GITHUB_APP_SLUG=your-github-app-slug
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
GOOGLE_CLIENT_ID=your-google-oauth-client-id
GOOGLE_CLIENT_SECRET=your-google-oauth-client-secret
GITHUB_OAUTH_CLIENT_ID=your-github-oauth-client-id
GITHUB_OAUTH_CLIENT_SECRET=your-github-oauth-client-secret
Set SECURE_COOKIES=true when serving behind HTTPS so session cookies use the Secure flag.
Google and GitHub login are optional. The Docker image only contains the OAuth
code; each server supplies its own credentials at runtime. Use these redirect
URLs when creating OAuth clients:
- Google:
https://your-domain.example/api/auth/oauth/google/callback - GitHub OAuth App:
https://your-domain.example/api/auth/oauth/github/callback
GitHub OAuth login requests repo access so it can also act as the user's
GitHub connection inside CampaignRepo. Use the separate GitHub App settings
above if you want repository connection through the install-per-repo flow
instead.
Without Compose:
docker build -t campaignrepo .
docker run -p 3000:3000 -v campaignrepo-data:/app/data campaignrepo
Portainer Updates
For a local Portainer install, GitOps polling is simpler than a webhook while testing.
Recommended stack settings:
- Repository:
https://github.com/avorial/CampaignRepo.git - Reference:
refs/heads/main - Compose path:
docker-compose.yml - Update method: polling
- Polling interval: 5 minutes
Roadmap
See ROADMAP.md for the current shipped/partial/open feature
status, the reliability/sync architecture plan, and the recommended next
release sequence.
License
See LICENSE.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found