Pold English

Tabletop Forge

Handbuch

Selbst gehostete Web-Anwendung für Dungeon Master: Kampagnen vorbereiten, Sessions leiten und einen digitalen Spieltisch (liegender TV) sowie ein Spieler-Display aus einem Browser heraus steuern.

Funktionen

  • Übersichtliche Oberfläche: zwei Modi, oben umschaltbar – Vorbereiten und Spielen (Karte mit Kartenleiste, daneben Szene · Kampf · Kreaturen · Notizen · Lore). In der Kopfzeile siehst du jederzeit, was auf Spieltisch und Spieler-Display läuft. Auf dem Handy: Navigation unten, Listen und Details nacheinander.
  • Mehrere Kampagnen, strikt getrennt gespeichert, gegliedert in Abenteuer und Sessions
  • Ebenen statt einer langen Leiste: Die Vorbereitung ist gegliedert in Kampagne › Abenteuer › Session. Oben zeigt eine Pfadleiste, wo du bist (Abenteuer und Session dort direkt wechselbar), die Seitenleiste nur die Seiten der aktuellen Ebene, mit „‹ zurück“ zur Ebene darüber.
    • Kampagne: Übersicht (erste Schritte, aktive Session, Abenteuer mit Fortschritt, Gruppe), Abenteuer, Gruppe, Welt (alle Lore), Bestiarium (alle Kreaturen), Mediathek (alle Karten, Bilder und Dokumente, nach Tag/Woche/Monat gruppiert, Filter nach Art und Abenteuer), Bildschirme, Einstellungen.
    • Abenteuer: Übersicht (worum es geht, Sessions als Zeitleiste, Inhalte), Karten, Handouts, Lore, NSCs & Encounter – jeweils nur, was zum Abenteuer gehört. Neues (auch Uploads, KI- und Basalt-Bilder) landet automatisch darin; ein Element kann zu mehreren Abenteuern gehören („Abenteuer:“-Knöpfe, „+ Aus der Kampagne hinzufügen“).
    • Session: Ablauf als Folge von Szenen (Vorlesetext, Notizen für dich, Karte, Handouts, Begegnung, NSCs, Lore; sortierbar, „erledigt“ abhakbar; mit KI vorschlagen lassen), Material (Notizen und Schnellauswahl) und Bereit? (prüft Szenen, Gruppe, Raster der Karten, Schwierigkeit der Begegnungen, verbundene Bildschirme) mit „Session starten“. Nicht fertig geworden? „Offene Szenen weiterschieben“ setzt sie an den Anfang der nächsten Session (legt sie bei Bedarf an) und markiert die aktuelle als gespielt. Beim Spielen gilt das Abenteuer der aktiven Session.
  • Spielen nach Drehbuch: Über der Karte die Szenenleiste der aktiven Session; das Panel Ablauf zeigt die aktuelle Szene mit allem, was du brauchst: „Szene beginnen“ (Karte auf den Tisch), Vorlesetext aufs Spieler-Display, Begegnung „verdeckt setzen & Kampf“, Handouts, NSCs und Lore mit einem Tipp, Stichworte „Was ist passiert?“ und „Erledigt & weiter“. Stegreif (in der Leiste und im Panel), wenn die Spieler vom Weg abweichen: Stegreif-Szene hinter der aktuellen, Spontan-NSC (KI oder gewürfelt), Zufallsbegegnung, Schnellsuche (Strg+K) über Karten, Handouts, Lore, Kreaturen und Begegnungen des Abenteuers bzw. der Kampagne – mit „Zur Szene“. Beenden schiebt offene Szenen auf Wunsch weiter und öffnet die Nachbereitung: Szenen mit Stichworten, Notizen aus dem Spiel, Erfahrungspunkte der erledigten Begegnungen, Recap „Was bisher geschah“ per KI (den Spielern zeigen oder als Session-Notiz an BasaltNotes schicken – braucht ein Token mit Recht „Eingang“), nächste Session vorbereiten.
  • KI-Erstellung: NSCs, Monster und Charaktere der Gruppe aus einem Satz („mürrische Zwergenschmiedin, HG 2“) – mit regelkonformem Statblock bzw. Werten (TP, RK, passive Wahrnehmung), Hintergrund und auf Wunsch Porträt und rundem Token (Token liegt getrennt als Token-Bild der Kreatur). Auch beim Spielen im Kreaturen-Tab für Spontan-NSCs.
  • Porträts und Tokens stehen groß im Bogen der Kreatur bzw. des Charakters (Spielern zeigen, optional „In Handouts“). Bei den Handouts erscheinen sie nur, wenn du das so wählst; in der Mediathek sind sie als „Porträt“/„Token“ gekennzeichnet. Ältere Kampagnen werden beim Update einmal Abenteuern zugeordnet (eins: alles dorthin; mehrere: was die Sessions verknüpft haben).
  • Vorbereitung (Prep-Mode): Karten, Handouts und Lore einer Session als Schnellauswahl bündeln
  • Karten: Kampf-, Orts- und Reise-/Weltkarten, Raster über Spalten/Zeilen oder per Rechteck ausrichten
  • Nebel des Krieges: pinselbasiert oder rechteckig, dauerhaft gespeichert über Sessions hinweg
  • Spieltisch-Kalibrierung: Auflösung, Bildformat, Diagonale oder physische Maße – ein Rasterfeld ist auf dem TV immer exakt 1″ × 1″
  • Encounter: Gegner/NSCs vorab verdeckt platzieren und mit einem Tipp aufdecken
  • Licht: statische und flackernde Lichtquellen, Fackeln an Tokens, Umgebungslicht
  • Zauberradien: Kreis/Sphäre, Kegel, Würfel, Linie mit Hervorhebung der betroffenen Felder
  • NPC- & Monster-Kartei: Kreaturen mit vollständigem 5e-Statblock, Hintergrund und Porträt. Import per Copy & Paste eines Statblocks (z.B. aus D&D Beyond, deutsch oder englisch) oder per Suche in frei lizenzierten 5e-Daten (SRD über open5e.com). Beim Spielen direkt als Token setzen oder in die Initiative nehmen (W20 + GE automatisch).
  • NSC-Generator: würfelt Name (passend zum Volk), Beruf, Aussehen, Persönlichkeit, Eigenheit, Stimme, Ideal, Bindung, Makel, Motivation und Geheimnis – einzeln neu würfelbar, mit passenden SRD-Spielwerten. Im Spiel als „Spontan-NSC“ auf Knopfdruck.
  • Monster-Datenbank: Suche auch mit deutschen Namen („Eulenbär“, „roter Drache“), Filter nach Typ und Herausforderungsgrad, Vorschau des Statblocks vor dem Übernehmen.
  • Kreaturen-Bilder: Beim Import aus der Monster-Datenbank wird das Bild mit übernommen, sofern Open5e eins hat (alle Monster aus „Tome of Beasts 2023“, im SRD nur wenige). Für NSCs und Monster gibt es eine Porträt-Bibliothek (70 Bilder, nach Volk und Geschlecht sortiert) – der NSC-Generator schlägt passende Bilder daraus vor, dazu selbst gezeichnete Porträts; in der Kartei über „Porträt wählen“.
  • Encounter-Planer (Kreaturen → Encounter): Gegner aus der Kartei zusammenstellen, Gruppe mit Stufen hinterlegen; die Schwierigkeit (trivial bis tödlich) wird nach dem Spielleiterhandbuch berechnet (EP × Multiplikator für die Gegneranzahl, angepasst an die Gruppengröße, gegen die EP-Schwellen der Gruppe), dazu die EP-Belohnung. Ein Klick setzt die Gegner verdeckt auf die Tischkarte und nimmt sie samt Gruppe in den Kampf.
  • Kampf-Manager (5e-Regeln, SRD): Initiative würfeln, Züge mit automatischen Effekten zu Zugbeginn/-ende (Zustände mit Dauer und Rettungswurf, Reaktion, legendäre Aktionen, Aufladung 5–6, Regeneration), Schaden mit Resistenz/Anfälligkeit/Immunität und temporären TP, Konzentrationswürfe, 0 TP mit Todesrettungswürfen und Massivschaden, Angriffe und Schaden direkt aus dem Statblock würfeln und auf ein Ziel anwenden (mit Treffer-Prüfung gegen die RK), Kampfprotokoll. Auf der Karte TP-Balken über dem Token und Zustandsmarken; Spieler sehen wahlweise nichts, nur ein „Blutend“-Symbol (ab 25 % bzw. 50 %) oder den Balken.
  • Pausenbildschirm: Verdunkelt die Spielleitung den Tisch, erscheint dort „Kurze Pause“ mit wechselnden Sprüchen („Bitte warten – der DM räumt gerade ein paar Sachen um.“) oder einer eigenen Nachricht (Bildschirme → Spieltisch).
  • LED-Streifen (WLED): Beliebig viele WLED-Controller (ESP32/ESP8266), z.B. um den Tisch und an der Decke. Jeder Streifen folgt entweder dem Spiel – Kampf leuchtet rot, beim Verdunkeln wird es ruhig, jede Karte kann eine eigene Stimmung haben (Taverne, Kerzenschein, Lagerfeuer, Wald, Höhle, Nacht, Gewitter, Magie, Unterwasser) – oder hält immer dieselbe Stimmung, etwa „Leselicht“ zum Notizenlesen. Einrichten unter Bildschirme → LED-Beleuchtung (Name, IP des Geräts, „Verbindung testen“); beim Spielen lässt sich die Stimmung der mitlaufenden Streifen in der Leiste unter der Karte auch von Hand wählen. Der Server muss die Geräte im Netz erreichen können (feste IP empfohlen). Die Effekte berechnet der Server selbst und streamt sie live per DDP (UDP-Port 4048, in WLED unter Sync „Receive UDP realtime“ – ab Werk an); Wechsel werden weich übergeblendet. Kommt der Stream nicht an, lässt sich je Streifen auf „WLED-Effekte“ umstellen.
  • Alles zur Karte an einem Ort: Im Panel „Karte“ stehen Notizen, Handouts und Lore der geöffneten Karte – direkt bearbeitbar, Handouts mit einem Tipp auf dem Spieler-Display
  • Notizen: Kartennotizen, laufende Session-Notizen, Kampagnen-Notizblock, handschriftlicher Notizblock
  • Lore: Einträge mit Kategorien, angepinnt oder mit Karten/Sessions verknüpft – erscheinen kontextbezogen
  • Spieler-Display: Handouts, Karten, Lore-Einträge oder Vorlesetexte mit weicher Überblendung
  • Tablet & Stift: Touch-optimiert, Pinch-Zoom, Stiftdruck, Handballen-Erkennung (Finger verschieben, Stift zeichnet)
  • Mehrere Geräte: Laptop oder Tablet allein – oder beide parallel (Layout „Begleit-Instanz“), alles in Echtzeit synchron

Start mit Docker

Fertiges Image von Docker Hub (linux/amd64 und linux/arm64), direkt über die veröffentlichte Compose-Datei:

docker compose -f oci://docker.io/poldion/tabletop-forge-compose:latest up -d

Oder mit der docker-compose.yml aus diesem Repository:

docker compose up -d

Selbst aus dem Quellcode bauen:

docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build

Für TrueNAS SCALE liegt unter deploy/truenas/docker-compose.yml eine Vorlage für „Install via YAML“ (Daten im automatisch angelegten App-Volume, optional eigenes Dataset).

Danach im Browser http://ip>:3000 öffnen. Alle Daten (Kampagnen, Uploads, Kalibrierung) liegen im Volume forge-data unter /data (in der TrueNAS-Vorlage aus Kompatibilitätsgründen dnd-data). Beim ersten Start mit leerem Datenordner entsteht eine Beispielkampagne zum Ausprobieren (DEMO_CAMPAIGN=0 schaltet das ab).

Anmeldung und Zugriff aus dem Internet

Ohne Konto ist die App wie bisher für alle im Netz offen. Sobald das erste Konto existiert, ist sie geschützt:

  • Erstes Konto: /login.html öffnen und den Einrichtungscode eingeben, der beim Start im Server-Protokoll steht (TrueNAS: App → Logs; alternativ fest über die Umgebungsvariable SETUP_CODE). So kann niemand sonst einen frisch erreichbaren Server übernehmen. Das erste Konto ist Admin.
  • Benutzerverwaltung unter „Benutzer & Geräte“ (Kopfzeile bzw. „Konto“ in der Seitenleiste): Konten anlegen, Rolle (Admin oder Spielleitung), Passwort setzen, löschen; jeder kann sein eigenes Passwort ändern.
  • Anzeigen (Spieltisch, Spieler-Display, Kiosk): Ein nicht freigegebenes Gerät zeigt einen Code und QR-Code. Mit dem Handy scannen, anmelden, Namen vergeben, „Freigeben“ – fertig. Die Anzeige bleibt angemeldet, bis die Freigabe unter „Benutzer & Geräte“ entzogen wird (dann wechselt sie sofort zurück zum QR-Code). Anzeigen dürfen nur lesen, was sie zum Darstellen brauchen.
  • Kiosk-Pi: Jedes Gerät hat einen eigenen geheimen Geräteschlüssel. Einmal per QR-Code freigegeben, meldet es seinen Browser nach jedem Neustart selbst an; Einstellungen wie WLAN-Passwörter bekommt nur ein freigegebenes Gerät mit passendem Schlüssel. Wichtig: Kiosks erst auf die aktuelle Kiosk-Software aktualisieren und dann das erste Konto anlegen – ältere Kiosk-Software kennt die Anmeldung nicht und kann danach keine Updates mehr laden. Kiosks, die beim Anlegen des ersten Kontos schon die neue Software haben, gelten als freigegeben.

Sitzungen gelten 30 Tage (verlängern sich bei Nutzung), Passwörter und Sitzungen werden nur als Hash gespeichert (/data/auth.json), wiederholte Fehlversuche bremsen die Anmeldung.

Im Internet betreiben: nur hinter einem Reverse-Proxy mit HTTPS (z.B. Caddy, Nginx Proxy Manager, Traefik oder ein Cloudflare-Tunnel) – ohne HTTPS gehen Passwort und Anmelde-Cookie unverschlüsselt durchs Netz. WebSockets müssen durchgereicht werden. Der Server wertet X-Forwarded-Proto und X-Forwarded-For von Proxys im eigenen Netz aus; sonst die Variable TRUST_PROXY setzen (Express-Syntax, z.B. 1 für genau einen Proxy davor). Stimmt die Adresse im QR-Code nicht (Proxy reicht den Hostnamen nicht weiter), PUBLIC_URL setzen, z.B. https://dnd.example.de.

Beispiel Caddy:

dnd.example.de {
    reverse_proxy 192.168.1.10:3000
}

Sprache und Einheiten

Die Oberfläche gibt es auf Deutsch und Englisch. Die Sprache wählt jedes Gerät selbst (Auswahl im Kopf, auf der Anmeldeseite und unter Kampagne); ohne Auswahl gilt die Sprache des Browsers. Spieltisch und Spieleransicht folgen der Anzeigesprache der Kampagne. Meldungen des Servers kommen in der Sprache des Browsers. Die Sprachpakete liegen unter public/i18n/ (Schlüssel ist der deutsche Text; fehlt eine Übersetzung, erscheint der deutsche Text). NSC-Generator, Funfacts und Pausensprüche sind vorerst nur auf Deutsch.

Entfernungen (Lineal, Flächeneffekte, Licht, Rasterweite, Statblöcke, Zustände) zeigt jede Kampagne metrisch (1,5 m je Feld) oder imperial (5 ft je Feld) – einstellbar unter Kampagne, unabhängig von der Sprache. Gespeichert wird immer in Fuß, ein Wechsel ändert also keine Daten.

KI-Dienste (optional)

Unter Dienste (Kopfzeile, nur Admins) lassen sich Sprachmodell, Bildgenerator und BasaltNotes eintragen. Was dort nicht aktiv ist, erscheint nirgends in der Oberfläche.

  • Sprachmodell – jede OpenAI-kompatible Schnittstelle (/v1/chat/completions), z.B. ein Ollama-Proxy, Ollama selbst oder ein Cloud-Dienst. Adresse, Modell (per „Verbindung testen“ auswählbar) und optional ein Schlüssel. Ergibt einen Knopf KI an den Notizen von Sessions und Karten, an Lore-Einträgen und am Hintergrund von Kreaturen: ausformulieren, Vorlesetext, Ideen, Stichpunkte, NSC ausarbeiten oder eine eigene Anweisung. Der Vorschlag lässt sich vor dem Übernehmen bearbeiten, dann ersetzen oder anhängen.
  • Bildgenerator – Anbieter wählbar: die eigene Bild-App (ComfyUI) über ihre API (/api/v1/workflows, /api/v1/generate, /api/v1/jobs) mit einem dort erzeugten Schlüssel (ig_…), oder ohne eigene KI ein öffentlicher Dienst mit OpenAI-kompatibler Schnittstelle (/v1/images/generations, für „Token aus Bild“ /v1/images/edits): Adresse (z.B. https://api.openai.com), Schlüssel und Modell eintragen. Dort kostet jedes Bild Geld, und die Beschreibungen gehen an diesen Dienst. Ergibt KI-Bild bei Kreaturen (Token/Porträt, auch „Token aus Bild“ aus dem vorhandenen Porträt), Karte mit KI erzeugen bei den Karten und Bild mit KI erzeugen bei den Handouts. Der passende Workflow ist vorgewählt (Token, Battlemap, Ortskarte, Illustration). Erzeugt wird im Hintergrund; fertige Bilder landen als Datei in der Kampagne (mit Workflow und Prompt), auch wenn der Dialog vorher geschlossen wird.

Zufallsbegegnung (Kreaturen → Encounter, braucht das Sprachmodell): Ort, Art (Kampf, NSCs, Hindernis) und Schwierigkeit wählen – die KI entwirft Szene, Vorlesetext, Gegner aus dem SRD (bevorzugt aus der eigenen Kartei), NSCs, Taktik, Wendung und Beute. Die Gegner passen immer zur Gruppe: Herausforderungsgrade werden aus Stufe und Größe der Gruppe vorgegeben, danach wird die Anzahl nach den Regeln des Spielleiterhandbuchs auf die gewählte Schwierigkeit gebracht (bei Bedarf mit verwandten Gegnern, z.B. Hobgoblin zu Goblins; lieber etwas leichter als zu schwer). Mit Bildgenerator entstehen dazu im Hintergrund ein Szenenbild und eine Battlemap; beide hängen am Encounter und an der aktiven Session, „Auf Karte & in den Kampf“ legt dann die eigene Karte auf den Tisch.

Adressen und Schlüssel liegen in data/ai.json auf dem Server; die Oberfläche bekommt die Schlüssel nie zu sehen.

Gruppe und BasaltNotes

Unter Gruppe (Vorbereitung) stehen die Spielercharaktere der Kampagne: Name, Spieler:in, Volk, Klasse, Stufe, TP, RK, passive Wahrnehmung, Porträt (hochladen, aus den Handouts oder per KI) und Hintergrund. Stufe und Anzahl gelten für die Schwierigkeit von Encountern und Zufallsbegegnungen, TP und RK für den Kampf.

BasaltNotes (optional, unter Dienste: Adresse, API-Token mit Leserecht, Vault): Charaktere lassen sich aus der Basalt-Kampagne übernehmen oder einzeln verknüpfen. Der Hintergrund wird dann aus der Charakter-Notiz angezeigt (Links öffnen BasaltNotes, bearbeitet wird dort), Bilder der Notiz lassen sich als Porträt übernehmen. Vault und Basalt-Kampagne wählt jede Kampagne auf der Kampagnenseite (ohne Auswahl der Standard-Vault aus den Diensten bzw. die gleichnamige Kampagne); verknüpfte Charaktere merken sich ihren Vault. Das Token liegt in data/basalt.json und erreicht die Oberfläche nie; Bilder laufen über den Server.

Regeln (Regelwerk aus BasaltNotes)

Liegen die Spielregeln (Zauber, Zustände, Regelkapitel …) als eigener Vault in BasaltNotes, trägt man ihn unter Dienste → BasaltNotes → Regelwerk-Vault ein. Dann gibt es einen Tab Regeln – als Seite auf der Kampagnen-Ebene und als Panel beim Spielen:

  • Suchen: Volltextsuche im Regelwerk mit Treffer-Ausschnitten. Ein Treffer öffnet den Regeltext direkt im Tab; Verweise auf andere Regeln bleiben im Tab, ↗ öffnet die Notiz in BasaltNotes.
  • KI fragen: nur wenn in BasaltNotes unter Einstellungen → Funktionen der KI-Chat an ist. Man stellt eine Frage („Wie funktioniert der Zauber Feuerwand und wie wende ich ihn an?“), BasaltNotes sucht die passenden Einträge heraus und das Sprachmodell erklärt sie. Unter jeder Antwort stehen die Quellen zum Nachlesen; Rückfragen beziehen sich auf das vorige Thema, Neu beginnt ein neues Gespräch.

Ohne Regelwerk-Vault erscheint der Tab nicht. Das Token braucht nur Leserecht auf diesen Vault.

Kiosk-Gerät für den Spieltisch (Raspberry Pi)

Unter kiosk/ liegt ein schreibgeschütztes Raspberry-Pi-Image (z.B. Pi Zero 2 W), das direkt die Spieltisch-Anzeige startet. WLAN, Server-Adresse, Kampagne und Anzeigeart werden im DM-System unter Bildschirme → Kiosk-Geräte gesteuert.

Start ohne Docker

npm install
npm start

Umgebungsvariablen: PORT (Standard 3000), DATA_DIR (Standard ./data), MAX_UPLOAD_MB (Standard 200), SETUP_CODE (fester Einrichtungscode fürs erste Konto), TRUST_PROXY und PUBLIC_URL (Betrieb hinter einem Reverse-Proxy, siehe „Anmeldung“).

Geräte einrichten

GerätAdresse
Spielleitung inkl. Vorbereitung (Laptop/Tablet)/dm.html?c=
Reine DM-Anzeige (nur Panel, z.B. zweites Tablet)/dm.html?c=&layout=panel
Spieltisch (liegender TV)/table.html?c= – optional &name=Tisch als Beschriftung
Spieler-Display/player.html?c=
TV-Kalibrierung/settings.html – Testmuster unter /table.html?calibrate=1

Jede verbundene Tischanzeige meldet ihren tatsächlich sichtbaren Ausschnitt; die DM-Ansicht zeigt dafür je einen beschrifteten Rahmen. Steht am Rahmen „berechnet“, ist keine Tischanzeige verbunden.

Die Links stehen auch auf der Startseite bei jeder Kampagne. Auf den Anzeigen einmal „Vollbild“ wählen (Schaltfläche erscheint bei Mausbewegung).

Kalibrierung des Spieltisches

  1. Unter TV-Kalibrierung Auflösung, Bildformat und Diagonale (oder Breite/Höhe der Bildfläche) eintragen.
  2. Auf dem TV das Testmuster öffnen und die 10-Felder-Linie nachmessen (Soll: 25,4 cm).
  3. Gemessenen Wert eintragen – der Korrekturfaktor wird berechnet und nach dem Speichern sofort übernommen.

Tastenkürzel in der Kartenansicht

V Auswahl · T TV-Ausschnitt · F Nebel aufdecken · H Nebel verdecken · K Token · L Licht · A Zauberradius · D Zeichnen · E Radierer · M Messen · P Ping · Entf Auswahl löschen · Esc Abbrechen

Entwicklung

npm run dev   # Server mit automatischem Neustart
npm test      # Unit-Tests

Aufbau: server/ (Express, Socket.IO, JSON-Persistenz je Kampagne), shared/ (Zustandsoperationen und Kalibrierung, von Server und Browser genutzt), public/ (Oberfläche ohne Build-Schritt).

Bildnachweis

Die Porträts unter public/portraits/orchidrabbit/ stammen aus „Fantasy Character Portraits vol.1“ von orchidrabbit (remy ripple), https://orchidrabbit.itch.io/portraitsvol1, lizenziert unter CC BY 4.0. Die Bilder sind unverändert (nur umbenannt).

Auf GitHub ansehen → · Projektseite →