— Complete Platform Documentation —

Versyr

User Guide · April 2026

Every session is a story worth keeping. This guide covers every feature of the Versyr chronicle platform — from submitting a note during a session to running the full GM loop.

Platform v2.5 · This guide covers the current production state of versyr.io
Contents
01
Platform Overview

Versyr is a chronicle platform for tabletop RPG campaigns. Every campaign gets a public blog, a GM backstage CMS, a collaborative session room, AI narrative tools, a gallery for generated scene art, and a lootbox that structures treasure from voice or text. The AI tools only see what your group has lived through — no source-book spoilers.

The platform is multi-tenant: each campaign lives on its own subdomain (e.g. hells-vengeance.versyr.io) with its own data, members, and published chronicles. The Hell's Vengeance Pathfinder campaign is the first customer deployment.

📜
Campaign Blog
Published chronicles with a brand chronicle bar, character pills, and a dynamic session archive.
🎲
Session Room
Live collaborative note-taking; AI analysis detects gaps and drafts the session chronicle.
Chronicle Studio
One-shot AI drafting from rough notes when a session room isn't needed.
Scenes
AI-generated atmospheric images for chronicles, watermarked with the Versyr V.
🔮
Campaign Oracle
A chatbot that only knows what your group has actually played. No invented lore.
💰
Lootbox
Voice or text loot entry, AI-structured with values, types, rarity, and Nethys lookups.
Codex
Living directories of characters, NPCs, locations, and factions — kept in sync by an AI lexicon sync after every chronicle.
Continuity
An AI check that scans your draft for contradictions against prior sessions.
02
Roles & Permissions

Every login is mapped to a role. Your role determines which navigation items appear, what you can write, and whether AI-triggering buttons are visible.

RoleWhat you can doTypical user
AdminEverything. Manage users, API keys, rules, campaign config, all GM powers.Platform operator
Spielleiter (master / GM)Create/close sessions, write chronicles, run analysis, manage knowledge, assign loot. Cannot manage users or API keys.The GM
Spieler (player)Read blog, submit session notes, view loot, view gallery, edit own profile, file bugs.Everyone else at the table
Field name quirkInternally the platform uses rolle = admin | master | player (legacy). The label GM / Spielleiter maps to master. If you ever touch the user data directly, know that master and gm mean the same thing.
03
The Campaign Blog

The blog lives at {campaign}.versyr.io (e.g. hells-vengeance.versyr.io). It is public — anyone can read published chronicles without logging in.

What's on every page

Chronicle template

Every published chronicle follows the same structure:

  1. Brand bar — campaign name left, "a Versyr chronicle" right
  2. Session number (DM Mono, blood colour)
  3. Title (Cormorant Garamond, ember, large)
  4. Meta line — date · characters · location
  5. Optional header image (auto-watermarked with the V monogram)
  6. Body — the narrative, structured with ## Abschnittstitel Markdown-like sections
  7. Footer — "Chronicle published by Versyr · versyr.io · [date]"

Navigation

The blog header offers four views: Chronicles (default), Characters, NPCs, Locations. Use the search box top-right to filter chronicles by keyword; clicking a character pill in the sidebar filters the feed to sessions featuring that character.

Avatar dropdown (logged-in)

Once signed in, the four old header buttons (⇄ switch view, campaign badge, ☾ theme, 🐛 bug) collapse into a single avatar in the top-right. Tap it to open a dropdown with: your name + email + active campaign at the top; Zur CMS / Zum Blog as a smart switch; Mein Profil; theme toggle; Bug melden; Abmelden; admin extras for admin accounts. Same dropdown on every page; sidebar redundancies are gone.

URLs and browser back

Every view encodes itself in location.hash: #blog, #post/{id}, #cms/{page}, #gallery, #login. Refreshing the page restores exactly where you were. Browser-back walks one in-app step at a time. CMS hash links opened without a session redirect to the blog so you don't strand yourself behind a sign-in wall.

Tablet layout

On tablets the site header is retired entirely. The hamburger top-left opens a vertical icon+label sidebar pinned to the viewport (scrollable independently of main content); the avatar floats top-right at the same offset as the bottom-right Oracle. Tap a tile to navigate; tap the hamburger again to close.

04
Campaign Oracle

The chat bubble in the bottom-right of the blog opens the Oracle — an AI chatbot with access to your campaign's characters, NPCs, locations, factions, and the last five published chronicles. It does not have access to source books; it won't tell you the stats of a Ring of Protection, but it will tell you what happened the last time your party met the Magister of Kantaria.

What it's good for

What it's not for

TipThe Oracle is available to logged-out blog visitors too. Anyone can ask about published state.
05
Player Guide

Logging in (first time)

An admin invites you by email from Benutzerverwaltung. You'll receive a Versyr-branded email with a one-tap magic link from mail@versyr.io (subject Einladung zur Versyr-Plattform). Click the link — it signs you in directly, then a small modal asks you to set a password so you can sign in with email + password from then on.

If the email landed in spam, mark it as "Not spam" and add mail@versyr.io to your contacts; deliverability improves with send volume. Need a fresh link? The admin can press the ↻ resend button next to your row in the user table.

Logging in (returning)

Tap the avatar / login icon in the top-right of the blog. Enter email + password. After sign-in the CMS sidebar appears with the nav items relevant to your role.

Your profile

Open Mein Profil from the avatar dropdown. You can change your password, select your theme (dark / light / high contrast), and set your character name — this is the label that appears on your session notes.

Submitting session notes

When the GM starts a session, it becomes the "active session" for everyone. Open 🎲 Sitzungsraum — you'll see a green pulsing dot and the session title. Below it:

  1. Your note textarea — describe what happens from your character's perspective
  2. Category chips — Kampf / Dialog / Entdeckung / Entscheidung / Atmosphäre / Sonstiges
  3. Priority chips — Hoch / Mittel / Niedrig
  4. Submit button — Notiz einreichen ↗

Notes appear in real-time for all participants. The contributor bar at the top shows how many notes each character has submitted.

Voice input

Click the 🎤 button above the input to speak your note instead of typing. Works in Chrome and Edge only (Web Speech API). Click again to stop; the transcript lands in the textarea for you to review before submitting.

Deleting your own notes

Hover any note you submitted — a small ✕ appears top-right. Click to remove. You can only delete your own notes; only the GM can delete anyone's.

Filing bugs

The 🐛 icon in the header opens a bug-report modal. Describe what went wrong; GM/admin see it in their Bug-Reports panel.

06
Session Room

The Session Room orchestrates the full lifecycle of one play session: live notes, GM-controlled lifecycle phases, AI analysis, gap-filling Q&A, and chronicle drafting.

Session lifecycle

PhaseWhat happensWho can act
openLive. Players submit notes in real time. Pulsing green dot.All players + GM
closedGM clicked "Sitzung schließen". Notes locked. AI analysis ready to run.GM only (analysis)
reviewingAI analysis in progress (~15–40s). Cancel button available.GM only
closed + gapsAnalysis produced a draft + a list of gaps/contradictions. GM answers each gap, then finalises.GM only
publishedChronicle saved as a blog post. Session appears in the history list.GM only (publish)

Starting a session (GM)

  1. Click 🎲 Sitzung starten
  2. Enter session number (e.g. #16), optional title, optional location
  3. Click Starten

During the session

Players submit notes. The GM's view shows a running list, filterable by character. The GM can delete any note (not just their own) if a player posted in error or duplicated content.

Closing and analysing

When play is done, GM clicks ⛔ Sitzung schließen. A "Narrative Analyse" panel appears. Click 🤖 Analyse starten & Chronik entwerfen ↗ to trigger Claude:

Cancelling or recovering

Three ways out of a stuck analysis
Abbrechen — visible while the fetch is in flight. Aborts the request, reverts to closed.
Zurücksetzen — appears if the session is stuck in reviewing after a browser reload or logout. Force-flips status back to closed.
Sitzung wieder öffnen — on a closed session with no draft, reverts to open so more notes can be added. Disabled once a draft exists.

Answering gaps

Each gap appears as a card with a question and a textarea. Answer them one by one. When all are answered, ✨ Finale Chronik generieren ↗ runs a second AI pass that weaves your answers into the draft and produces the final publishable chronicle. You can re-analyse at any time with ↺ Neu analysieren.

Publishing

The finalised draft drops into the chronicle editor (✍ Neue Chronik). The session-number field is pre-filled with the next number based on the highest existing chronicle (you can override). Review, tweak, tick "Veröffentlicht", click Speichern ↗. The chronicle appears on the public blog immediately — and Versyr runs the AI lexicon sync on the text (see §09).

Reordering chronicles

From Alle Beiträge, the GM can drag-reorder rows or use the inline ↑ / ↓ controls. The session number is what drives blog ordering, so this is the place to fix a mis-numbered or out-of-sequence chronicle without re-editing the post.

Deleting a completed session

In the session history list under the main session panel, each row has a small ✕ button (GM only). Click, confirm, the session and all its notes are removed. Published chronicles are not deleted — those live in the chronicle table independently.

07
Lootbox

The Versyr Lootbox (💰 Lootbox in the sidebar) eliminates the chaos of tracking party treasure. Speak or type what you found, and the AI structures it into items with official names, types, values in GP, weights, rarity tags, and Nethys search links.

Entering loot

  1. Type or speak into the input box. Natural sentences work: "Wir haben einen +1 Longsword gefunden, zwei Heiltränke, einen Ring of Protection +2 und 450 Goldmünzen."
  2. Click 🤖 KI strukturieren & erfassen ↗
  3. The AI returns structured items and adds them to the vault. Currencies are converted to GP (1 GP = 10 SP = 100 CP).

Value overview

At the top of the page, four stats summarise the vault: total GP, unassigned group loot, number of items, and already-distributed value. These always reflect the full vault and aren't affected by the filters below.

Two views

ViewWhen to use
📇 Karten (default)Browsing, assigning to characters, visual inventory
📋 TabelleScanning many items, sorting mentally by column, bulk review

Toggle in the top-right of the control row. Your choice persists across reloads (stored in localStorage).

Filters

Filters combine. The bottom line of each card/row respects all active filters.

Assigning items

Card view: the chip row at the bottom of each card lets you click a character name to assign, click 🗃 Gruppe to unassign, or click 💸 Verkauft to mark as sold. Assigning is instant and synced in real time to all participants.

Nethys lookup

Each item has a 📖 Nethys badge (card view) or 📖 link (table view). Clicking opens a Google search scoped to aonprd.com with the item's English name. This always returns usable results, unlike direct deep-links which the AI used to hallucinate.

NoteThe Lootbox currently assumes Pathfinder 1e. System-aware prompts for PF2, D&D 5e, and custom homebrew are planned — see the Roadmap.

CSV export

Click ⇩ CSV to download the currently-filtered vault as lootbox-{campaign}-{date}.csv. File is UTF-8 with BOM so Excel handles umlauts cleanly. Columns: Anzahl, Name, NameEn, Typ, Seltenheit, Magisch, GP/Stk, Gesamt-GP, Gewicht/Stk, Besitzer, Verkauft, Beschreibung.

09
Game Master Guide

The knowledge modules

Four sidebar entries manage the living world:

The lexicon sync (AI-assisted)

After every chronicle save, Versyr runs a background AI sync: Claude reads the body text and identifies:

If anything matches, a Lexikon-Vorschläge aus Chronik modal pops up. Each suggestion is pre-checked — tick/untick to curate, then click Ausgewählte übernehmen ↗. Approved entries are written to the directories; character arc notes are appended to their Errungenschaften. Nothing is written without your approval.

TipThe sync only surfaces things that are actually new. If an NPC is already in the directory, it's silently skipped. You'll only see the modal when there's something worth deciding on.

Chronicle Studio

◈ Chronik-Studio is a simpler flow for when you want AI drafting without a live session. Paste rough notes, click Chronik schreiben, get a narrative draft. Lands in the editor for publishing.

Continuity checker

⚖ Kontinuität scans any text against the current campaign state and flags warnings, errors, or confirmations. Useful before publishing a chronicle to catch contradictions you might have missed.

Users and bugs

Admins (not GMs) manage users under 👥 Benutzerverwaltung. Bug reports from players appear at 🐛 Bug-Reports — admin-only — with a counter badge in the sidebar when new ones arrive.

10
AI Features

All AI text generation runs through Anthropic's Claude. Every call is logged to the Activity Log with a module label so you can see exactly what fired and when.

Module labelWhere it firesPurpose
Chronik-Studio◈ Chronik-Studio → Chronik schreibenDraft a narrative chronicle from rough notes
Bild-Prompt◇ Bildgenerator → GenerierenOptimise the user prompt before image generation
Kontinuitätsprüfung⚖ Kontinuität → PrüfenFlag contradictions against prior sessions
BeuteextraktionLootbox → 🤖 KI strukturierenParse loot text into structured items
SitzungsanalyseSession Room → Analyse startenDraft chronicle + detect gaps from session notes
Chronik-FinalisierungSession Room → Finale Chronik generierenWeave gap answers into the draft
Charakter-BeschreibungCharacter edit modal → Aus Beschreibung generierenProduce visual description + image anchor for a character
Lexikon-SyncAutomatic after every chronicle saveDetect new NPCs, places, and main-character arc changes
OracleBlog chat widgetAnswer visitor questions against campaign state

Every call logs three events: ⚡ Anfrage gesendet, ✓ Antwort erhalten, or ⚠ …Fehler. If something feels stuck, check the Activity Log first.

Token budget

Max output tokens: 4000. Model: claude-sonnet-4-6. Temperature: default (model-set). The prompt for each module is tuned for its output format (JSON vs prose); if responses get truncated or malformed, the JSON-parse error surfaces as an alert with a raw-response dump in the browser console.

11
Administrator Guide

API keys

Secrets are stored in Firebase under /config and loaded at login — never hardcoded in the client. Admins set them under ⚙ Einstellungen:

User management

Open 👥 Benutzerverwaltung. Create profiles with email, name, character, and role. Saving fires the inviteUser Cloud Function which sends a Versyr-branded magic-link email via Resend (sender mail@versyr.io). The user clicks the link, sets a password on first sign-in, and is then a fully active member.

The status column shows ✓ Aktiv for users who've completed first sign-in, ⌛ Eingeladen DD.MM.YY for pending invites, and for legacy profiles created before the email flow. The ↻ button next to a pending row resends the invite (and quietly upserts the studio membership entry as a side effect). Magic-link sign-in must be enabled in Firebase Auth → Sign-in method, and the Resend API key must be present at config/resendApiKey.

Magic-link Cloud Function setup

The inviteUser and listOrphans callables run on Cloud Run via Firebase Functions Gen 2. On a fresh project they need an explicit roles/run.invoker grant for allUsers (otherwise calls return a bare "Fehler: internal"). Set with gcloud run services add-iam-policy-binding. config/resendApiKey must be populated under each Firebase project's /config.

Firebase Realtime Database rules

Rules live in database.rules.json at the repo root — version-controlled. Deploy with:

firebase deploy --only database

Current rules: root catch-all is .read: false / .write: false; auth-only paths (studios, campaigns inside studios, gallery, characters, bugs, etc.) have explicit overrides. Public blog reads are served via the studio path with platform/studiosIndex/.read: true letting unauth visitors resolve slug→studio. Don't replace the root catch-all without auditing every path the app reads — it will break things silently.

Deployment

Pushes to develop deploy to versyr-dev.netlify.app; pushes to main deploy to versyr.netlify.app and the campaign subdomain. Never push files directly to Netlify bypassing git — that caused a 503KB corruption incident in the past.

The single-file philosophy

platform/index.html is the whole frontend — HTML, CSS, and JS inline. This is intentional for simple deployment. A CI workflow (.github/workflows/validate.yml) checks on every PR that there's exactly one <!DOCTYPE html>, one <body>, and that the main script block parses as valid JS. A refactor into modules is backlog (#63) but not scheduled.

12
Tips & Shortcuts
13
Changelog
v2.52026-04-30
Navigation overhaul, invite emails, image-gen polish, picker
  • Avatar dropdown consolidates the four old header buttons; sidebar redundancies retired
  • Hash-based routing: refresh restores the current view, browser-back walks one in-app step
  • Tablet revamp — vertical icon+label sidebar, retired site header, top-corner avatar + hamburger
  • Default CMS landing flipped from Editor to Alle Beiträge (Kampagnenwissen sidebar)
  • Logout state scrub — listeners detached, in-memory state cleared, no role-account residue
  • Invite-by-email via Resend — Versyr-branded magic-link mail from mail@versyr.io; first-time password setup modal; ✓ Aktiv / ⌛ Eingeladen / ↻ resend in the user table
  • Bildgenerator — expanded mood vocabulary; Pro-Modus for gpt-image-2; brush-mask Anpassen with linear undo + redo; quality respected across adjustments; per-image diagnostics strip (model · quality · WxH · file size)
  • Charakter-Picker — multi-select with thumbnails replaces the comma-typed character input; spans PCs and NPCs (NPCs gain optional visual fields)
  • Chroniken — drag-reorder / inline ↑↓ controls; auto-suggested next session number in the editor
  • versyr.io apex now serves a platform landing page; deep links continue to the campaign subdomain
  • First JS module split — Audio cluster extracted to scripts/audio.js as a no-build proof-of-pattern
v2.42026-04-21
Light-theme readability
  • Chronicle body, post-card excerpts, character pills, loot descriptions and lightbox details use a warm dark-brown text on light theme
  • Primary buttons (Speichern, Veröffentlichen, etc.) force light text on the solid scarlet fill in light theme
v2.32026-04-21
Brand assets + gallery watermark
  • Favicon suite (SVG + ico + PNG), Apple touch icon
  • Open Graph + Twitter meta with Versyr wordmark OG image
  • V monogram watermark baked into every gallery upload — parchment halo + ember V for contrast on dark fantasy scenes
v2.22026-04-21
Lootbox polish
  • Table view toggle (Karten / Tabelle), preference persisted
  • Secondary filters: type, rarity, magic-only toggle
  • CSV export with BOM + UTF-8 for Excel-safe umlauts
  • Nethys linkout now deterministic (Google site-scoped search on aonprd.com); AI-guessed URLs are history
v2.12026-04-21
Session room overhaul
  • Session delete (GM only) with immediate DOM removal
  • Gallery image picker in the chronicle editor
  • AI-assisted lexicon sync — NPCs, places, and main-character arc/status updates after every chronicle save
  • Cancel / Reopen / Reset controls for session analysis; 180s hard timeout; elapsed timer in the loader
  • max_tokens raised to 4000 to fix silently-truncated JSON responses
  • Activity log records every AI call tagged by module
  • Firebase array/object normalisation on read — recovers data shape from prior mixed-key writes
v2.02026-04-21
Multi-tenancy (M1)
  • All Firebase reads/writes scoped to studios/{sid}/campaigns/{cid}/… (studio prefix added by Slice 5 of M2; legacy campaigns/ root decommissioned in Slice 7b 2026-05-03)
  • Migration script + data migration run against prod
  • Public blog listener kept non-auth-gated so chronicles load for logged-out visitors
  • Campaign switcher badge in header
  • Firebase CLI + version-controlled DB rules
  • CI workflow validates single DOCTYPE/body + JS syntax on every PR
v1.xFeb–Apr 2026
Versyr brand + foundational features
  • Versyr brand identity applied (Cormorant / DM Mono / Outfit, Ember #C8923A, chronicle brand bar, site co-brand header)
  • Canonical domain moved from versyr.gg to versyr.io; apex redirects to campaign subdomain
  • Public site footer with Versyr attribution and contact
  • Chronicle editor, public blog, session room, oracle chatbot, knowledge directories, lootbox, image gallery, continuity checker
14
Roadmap

Milestones from the project tracker, in chronological order. Dates are targets, not commitments.

M2 Slice 7b · Decom legacy paths
Shipped 2026-05-03
Stripped the dual-write shim, deleted the legacy /campaigns/{cid} mirror on prod + staging (with backup), removed the legacy DB rule. App reads/writes go solely through the studio path now.
M1.5 · i18n Foundation
Due 2026-05-11
Extract all UI strings, add DE + EN support with a locale switcher, localise AI prompts per campaign. First step toward non-German customers.
M2 · Campaign Wizard + Invites
Due 2026-05-25
Self-service campaign creation wizard. Signup flow for new GMs. Invite links for players. Campaign slug routing at /c/{slug}. Member management page per campaign.
M3 · Stripe + Trial
Due 2026-06-08
Subscription billing via Stripe. 14-day trial auto-starts on signup. Read-only mode when trial expires and payment missing. Stripe customer portal link for card/cancel.
M4 · Legal + Landing + Email
Due 2026-06-15
Terms of Service, Privacy Policy (GDPR). Marketing landing page. Transactional email via Resend (welcome, invite, trial-expiry) using the Versyr brand email template.
M5 · Private Beta
Due 2026-06-22
3–5 external GMs testing outside Hell's Vengeance. Discord deeplink + optional Widgetbot embed per campaign. Post-beta retrospective.
M6 · Public Launch
Due 2026-07-06
Product Hunt submission, Twitter/Bluesky launch thread, Pathfinder and D&D Discord announcements, post-launch monitoring of signup / trial-to-paid / churn.

Key epics (no milestone assigned yet)

Per-campaign game system
epic #84
Make the platform rule-system agnostic. Campaign config picks one of pf1 / pf2 / dnd5e / custom. System registry drives AI prompts (loot parsing, continuity, oracle), item type vocabulary, currency rules, and external reference linkouts (Nethys, D&D Beyond, admin-pluggable).
Sandbox/prod DB split + Admin Center
epic #86
Second Firebase project for sandbox, env-aware config, admin-triggered "refresh sandbox from prod" button via Cloud Function. New Admin Center CMS page as landing for ops functions.
Post-launch: additional languages
Post-M6
Spanish, French, more locales added based on demand after the initial DE + EN support lands.
JS module split
in progress
platform/index.html has crossed the warn cap; the inline script is being chipped out one cluster at a time, no build step (plain <script defer src>). Audio cluster shipped first as proof-of-pattern; Gallery and others follow when their boundaries justify the work.
Native iOS / Android app
under consideration
Capacitor-wrapped SPA the most likely path — same web codebase, native shells, App Store distribution. Design choices going forward already account for it (touch-first interactions, offline tolerance, file-picker abstraction, push notifications via FCM, build-time env injection in place of hostname routing).