Scheduling assistant for TTRPG groups. Intended as a selfhosted replacement for RollRota.
  • Python 59.5%
  • JavaScript 26.8%
  • HTML 11%
  • CSS 2.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
renovate-bot ef41b3222d
All checks were successful
CI / Does this change touch the recording path? (push) Successful in 22s
CI / Bot/backend version sync (push) Successful in 32s
CI / Backend lint (ruff) (push) Successful in 36s
CI / Which journeys does this change need? (push) Successful in 37s
CI / Feedback site tests (push) Successful in 1m41s
CI / Summarisation accuracy eval harness (stub provider) (push) Successful in 2m6s
CI / Bot tests and audit (push) Successful in 2m7s
CI / Docker image build (push) Successful in 4m58s
CI / Frontend (shard 2/2) (push) Successful in 8m46s
CI / Synthetic session harness (no GPU, no LLM) (push) Successful in 9m21s
CI / Frontend (shard 1/2) (push) Successful in 11m8s
CI / End-to-end journeys (phone) (push) Successful in 11m20s
CI / End-to-end journeys (keyboard) (push) Successful in 12m16s
CI / End-to-end journeys (desktop) (push) Successful in 12m19s
CI / Backend migration, tests, and audit (push) Successful in 1h7m0s
Merge pull request 'chore(deps): update dependency @vitejs/plugin-react to v6.3.0' (#1373) from renovate/vitejs-plugin-react-6.x into main
2026-11-09 08:12:20 +00:00
.claude feat(repo): prereleases for dev and image deploys, profile answers (#1043) 2026-10-03 14:09:52 +00:00
.forgejo feat(repo): PostgreSQL 16 to 18, with make pg-upgrade and a hard-stop guard (#1245) 2026-10-31 06:41:38 +00:00
bot chore(release): v4.8.0-rc1 2026-11-07 15:45:26 +00:00
changelog.d Merge pull request 'docs: D341, a conversion's draft is reviewed in the dialog (#958)' (#1366) from docs/d341-convert-draft into main 2026-11-07 08:22:25 +00:00
docker/keys build: keep the PGDG apt signing key in the repo (#1346) 2026-11-06 07:16:43 +00:00
docs Merge pull request 'docs: D341, a conversion's draft is reviewed in the dialog (#958)' (#1366) from docs/d341-convert-draft into main 2026-11-07 08:22:25 +00:00
scripts fix(repo): pg-upgrade counts tables with a query PostgreSQL accepts (#1245) 2026-11-04 17:08:56 +00:00
tools/feedback-site chore(deps): update dependency fastapi to v0.162.2 2026-11-09 00:28:42 +00:00
webapp Merge pull request 'chore(deps): update dependency @vitejs/plugin-react to v6.3.0' (#1373) from renovate/vitejs-plugin-react-6.x into main 2026-11-09 08:12:20 +00:00
.dockerignore feat(demo): the seed engine, CLI, tripwires and its test (#821) 2026-09-25 20:10:27 -05:00
.env.e2e feat(webapp,bot): remove D67 Discord fallbacks, add bot identity check 2026-09-26 11:33:58 -05:00
.env.example feat(webapp): campaign names go to the transcriber as hotwords by default (#1315) 2026-11-02 17:26:56 +00:00
.gitattributes Say only what is known in the ledger merge note (#1020) 2026-10-01 20:11:05 -05:00
.gitignore chore(repo): shared Claude Code setup for tiered delegation (#935) 2026-09-29 10:59:55 -05:00
.gitleaks.toml chore(repo): allowlist the scanner's 34 known-false secret findings (#132) 2026-11-06 07:17:14 +00:00
.gitmessage chore: add release infrastructure 2026-03-14 20:03:28 -05:00
.pre-commit-config.yaml feat(e2e): the journeys harness — fake OIDC, fake bot, fake AI, Playwright (#726) 2026-09-22 00:57:07 -05:00
ARCHITECTURE.md feat(repo): PostgreSQL 16 to 18, with make pg-upgrade and a hard-stop guard (#1245) 2026-10-31 06:41:38 +00:00
CHANGELOG.md chore(release): v4.7.1 2026-11-06 07:11:41 +00:00
CLAUDE.md feat(repo): PostgreSQL 16 to 18, with make pg-upgrade and a hard-stop guard (#1245) 2026-10-31 06:41:38 +00:00
docker-compose.dev.yml fix(webapp): maps are cut into tiles, and drawn from them (#734) 2026-09-28 22:08:37 -05:00
docker-compose.e2e.ci.yml fix(ci): the journeys stack is per-run, and publishes nothing on a runner (#728) 2026-09-22 13:43:58 -05:00
docker-compose.e2e.dev.yml fix(e2e): the journeys stack mounts nothing from the host (#726) 2026-09-22 00:57:34 -05:00
docker-compose.e2e.yml Merge remote-tracking branch 'origin/renovate/axllent-mailpit-1.x' into chore/deps-4.7.0 2026-11-05 18:25:00 +00:00
docker-compose.images.yml chore(release): v4.8.0-rc1 2026-11-07 15:45:26 +00:00
docker-compose.override.yml Make production compose the default 2026-04-05 01:16:16 -05:00
docker-compose.prod.yml Make production compose the default 2026-04-05 01:16:16 -05:00
docker-compose.yml fix(repo): pg-upgrade review fixes (#1245) 2026-10-31 18:01:17 +00:00
Dockerfile build: keep the PGDG apt signing key in the repo (#1346) 2026-11-06 07:16:43 +00:00
LICENSE Create LICENSE 2026-03-13 21:10:10 -05:00
Makefile feat(repo): PostgreSQL 16 to 18, with make pg-upgrade and a hard-stop guard (#1245) 2026-10-31 06:41:38 +00:00
README.md docs(webapp): guides for the people who use Quest Board, not just run it (#390) 2026-09-06 01:57:32 -05:00
renovate.json feat(repo): PostgreSQL 16 to 18, with make pg-upgrade and a hard-stop guard (#1245) 2026-10-31 06:41:38 +00:00
TEST_FIX_STATUS.md Fix UUID comparison in import test; update handoff doc 2026-05-05 18:58:37 -05:00

Quest Board

Quest Board is a self-hosted TTRPG campaign hub for groups who want scheduling, Discord coordination, session memory, and campaign lore in one place instead of spread across calendars, chat logs, and wikis.

Read This First

Everything above is for whoever runs the deployment. The guides for GMs and players ship inside the app, at /help/gm and /help/player — public routes, so a link works before the reader has an account. Their source is webapp/frontend/src/help/.

What It Does

  • OIDC sign-in with providers like Authentik, Keycloak, and Google
  • Session scheduling with vote, direct, and tentative modes, plus per-session voting grids and GM confirmation flows
  • Campaign-level reminder scheduling with Discord delivery, configurable offsets, and webhook or bot-backed notifications
  • Discord reaction voting, attendance RSVP, account linking, and bot commands like /next, /recap, /note, /ask, and /record
  • Voice session recording with attributed per-speaker capture, backend transcription, review/approval workflow, and AI-generated summaries
  • Session pages with private player notes, GM-shared notes, calendar export links, attendance tracking, and responsive dashboards
  • Campaign journals that combine session history, recap content, and public notes into a readable campaign record
  • Campaign milestones for tracking major events, linked sessions, dates, and long-term progress beats
  • Campaign analytics for attendance, participation, and session cadence
  • A campaign wiki with article pages, relationships, structured sidebar fields, timeline events, aliases, version history, and search
  • Player-character wiki support with owner roles, private character notes, campaign-page linking, and player-editable public character pages
  • Lore pipeline automation that turns approved session recordings into reviewable wiki proposals, relationship updates, and campaign-memory tooling
  • A GM Workbench of campaign-grounded AI tools — read-aloud descriptions, rumor mills, random tables, loot parcels, instant NPCs, session prep sheets, and story-arc suggestions — all reviewed before anything reaches your canon
  • A Session Reference Shelf for live play: a spatial board of generated content and pinned wiki entries that holds the positions you drop them in, with glance-readable cards, a "now playing" spotlight, Ctrl-K retrieval, named scenes you swap between, and per-card notes for tonight
  • Reveal-to-table, which shows a card's player-safe layer to your players in Quest Board or as a Discord embed while the rest of the card stays GM-only
  • An end-of-session sweep that turns tonight's improv into canon deliberately — promote to the wiki via an AI draft, carry forward to next session, or discard — and a warm cold-open that starts the next session with a recap, the loops still open, and the cards you carried

Production Quick Start

1. Clone and configure

git clone https://git.rhoving.com/rbrooks/Quest-Board.git quest-board
cd quest-board
cp .env.example .env

Update .env for your real deployment values. At minimum:

  • set APP_URL and QUESTBOARD_PUBLIC_URL to your public URL
  • set OIDC_REDIRECT_URI to https://your-domain/auth/callback
  • set strong values for SECRET_KEY, POSTGRES_PASSWORD, POSTGRES_MIGRATE_PASSWORD, and BOT_API_KEY
  • configure your OIDC provider settings
  • add DISCORD_BOT_TOKEN if you want bot features enabled

The full environment reference lives in .env.example.

2. Start the stack

docker compose up -d

Or:

make up

3. Run the guarded migration workflow

make migrate-safe

This is the preferred production migration path. It:

  • runs a schema sanity preflight
  • writes an immediate pg_dump snapshot under /app/backups
  • applies alembic upgrade head

4. Put it behind a reverse proxy

Quest Board expects external TLS termination. Point your reverse proxy at the frontend HTTP port exposed by the stack.

5. Finish app configuration

  • sign in through your OIDC provider
  • configure Admin -> Bot Settings
  • configure campaign-level Discord settings if needed

See docs/OPERATIONS.md and docs/INTEGRATIONS.md for the detailed production setup steps.

Privacy / Data Retention

Quest Board can capture voice sessions, so it lets you decide how long the raw audio and the derived transcripts are kept. Policies are set instance-wide in Admin -> Settings and can be overridden per campaign; a campaign that leaves a field unset inherits the instance default.

  • Audio — delete_after_processing (recommended default), retain_days (keep the raw per-speaker recordings for N days after processing, then delete), or retain_indefinitely.
  • Transcripts — retain_indefinitely (default) or retain_months (clear the transcript text N months after processing; summaries and wiki/lore entries are always kept).

The recommended posture is transcript-only: keep the searchable transcript and summary, but delete the raw audio once it has been processed. A daily retention task enforces these policies.

Note: delete_after_processing removes the raw recording as soon as the transcript and summary are saved, which means a session can no longer be re-transcribed. If you may want to reprocess audio (e.g. after tuning Whisper), use retain_days with a window that suits you instead.

Updating Production

git pull
docker compose up -d --build

Migrations now run automatically: a one-shot migrate service applies alembic upgrade head in the correct order before backend, worker, and beat start, so they never serve against an old schema. No manual migrate step.

The automatic path does not take a pre-migration backup. Before a major upgrade, snapshot the database first (while the current stack is still running):

make backup-now        # or `make migrate-safe` to also preflight + migrate now
git pull
docker compose up -d --build

Useful Make Targets

make help

Common operations:

  • make up
  • make down
  • make logs
  • make migrate
  • make migrate-safe
  • make backup-now
  • make set-admin EMAIL=user@example.com

Container Images

Each tagged release publishes versioned backend, frontend, and bot images to the Forgejo container registry (git.rhoving.com/rbrooks/quest-board-*), so you can pin a deployment to exactly what was tested and roll back with a tag change instead of rebuilding from source. See docs/OPERATIONS.md → Running from Published Images.

Notes

  • Review the code before running it in production. This project has been developed with AI coding assistance and may contain mistakes.
  • Development instructions have moved to docs/DEVELOPMENT.md.
  • Integration setup details have moved to docs/INTEGRATIONS.md.