Skip to content

Repository files navigation

🛰️ Farhold OS

A real-time, self-hosted operating system for long-form tabletop RPG campaigns

Live in-fiction chat · AI-driven NPCs · GM console · Shared campaign wiki · Ambient audio sync

License: MIT Node.js Self-hosted Status CI

Features · What's in this repo · Quick Start · Architecture · Roadmap


What is this?

Farhold OS is a browser-based companion app that runs alongside your tabletop session — not a replacement for your VTT, but a persistent, always-on layer for everything that happens between the dice rolls: in-character messages, NPC replies, shared lore, mission tracking, and ambient audio, all synced live between the GM and every player at the table.

It was built and battle-tested over a long-running Mongoose Traveller 2E campaign, session after session. It's system-agnostic — nothing in the engine is Traveller-specific.


✨ Features

This is the full feature set the architecture supports and was designed around — see What's actually in this repo below for exactly what ships out of the box versus what you build using the same patterns.

Core engine

  • Real-time state sync — any panel, tracker, or dashboard can read/write shared state with automatic race-condition protection (GM and players editing concurrently never silently overwrite each other)
  • Token-based player auth — each PC gets a private link, no accounts or passwords to manage
  • Live presence tracking — see who's online, what page they're on, auto-detect disconnects

RPOS — in-fiction communications

  • Real-time chat — Player↔Player and Player↔NPC messaging with typing indicators
  • AI-driven NPCs — NPCs reply on their own (draft-for-review or full-auto mode), with full thread-history context
  • GM impersonation console — approve, edit, or override any AI-generated reply; manual impersonation always available with quick-preset NPCs
  • Mail system — in-fiction correspondence between PCs, NPCs, and factions, with full history and MJ broadcast tools
  • Hidden PCs — support for secret/late-joining characters, invisible to other players until a narrative reveal

Antinet — campaign wiki

  • Zettelkasten-style linked notes (CRUD, backlinks, graph view)
  • [[wiki-link]] syntax shared with the AI session-recap generator, so AI-written notes plug straight into your wiki
  • MJ-gated — separate auth layer since this is where your spoilers live

GM toolkit (build-your-own, patterns included)

The architecture supports building a full GM toolkit on top of the core engine and RPOS/Antinet — this is what a mature Farhold OS deployment looks like in practice:

  • Campaign dashboard — live overview: session/chapter counters, group funds, faction reputation, moral tracker, quick links to every tool
  • Combat tracker — auto-initiative, HP/status/radiation tracking, synced projection to player screens (a working example ships in this repo — see below)
  • Encounter generator — quick NPC/encounter rolls with notes and projection
  • Interactive star map — travel journal auto-logging jumps/emergences, exportable as markdown
  • Session-live toolkit — narrative timers, pause overlays, public shared dice rolls, quick votes, a shared player notebook, an NPC bank generator, AI session-recap generation (player narrative + GM structured notes), auto-snapshots, and a replay timeline
  • PDF export — printable player-facing session recaps
  • Ambient audio bridge — scene-based music/SFX triggers piped to Discord via Kenku FM

📦 What's actually in this repo

Full transparency on scope, since the feature list above is broad:

Included Not included (build with the same patterns)
✅ Core state-sync engine ⬜ Campaign dashboard
✅ RPOS (chat, mail, AI NPCs, GM console) ⬜ Encounter generator
✅ Antinet (linked notes, backlinks, graph) ⬜ Interactive star map / travel journal
✅ One working example: combat tracker (examples/demo-campaign/) ⬜ Session-live toolkit (timers, votes, snapshots, replay...)
✅ Campaign config system (3-tier, see docs/ARCHITECTURE.md) ⬜ PDF export
✅ Nginx reference config, Docker deployment ⬜ Ambient audio bridge integration

The GM toolkit tools were purpose-built for one campaign's exact workflow and are too tightly coupled to that campaign's content to publish generically as-is (they're mostly markdown/HTML generators wired to specific narrative data). Rather than ship something you'd have to gut and rebuild anyway, this repo gives you the engine, the messaging/wiki layer, and one clean worked example (the combat tracker) demonstrating the config-driven pattern — see docs/ARCHITECTURE.md for how to extend it into your own dashboard, encounter tools, or whatever your table needs.


📸 Screenshots

GM Hub dashboard
GM Hub — campaign dashboard with live status, quick actions, and system modules (from the original deployment this engine was extracted from)

(Add your own screenshots to docs/screenshots/ as you build.)


🚀 Quick Start

git clone https://github.com/yourname/farhold-os.git
cd farhold-os
cp .env.example .env        # fill in your API keys and data path
docker compose up -d

Before your first real session, create your own campaign config — see docs/INSTALL.md for the full walkthrough (campaign roster, tokens, environment variables, Nginx setup, Dockge deployment).

Then open examples/demo-campaign/combat.html to see the config-driven pattern in action — this is the template to follow for any new tool you build.


🏗️ Architecture

The engine is built around a few core patterns worth knowing before you dig in:

  • Three-tier campaign config — server narrative data, server messaging/tokens, and client display config are kept in separate files so the engine ships with zero campaign content and boots with a safe demo roster out of the box
  • State sync — every write reloads server state first before saving, to avoid stale in-memory overwrites when GM and players act concurrently
  • Key resolution — GM and player pages must resolve the same campaign storage key, or GM content silently becomes invisible to players

Full technical writeup, including the debugging lessons that shaped these patterns: docs/ARCHITECTURE.md


📁 Repo structure

farhold-os/
├── docker-compose.yml # Two services: farhold-api + nginx, ready to run
├── .env.example        # Copy to .env and fill in before first run
├── .github/
│   └── workflows/ci.yml # Syntax + secret-audit checks on every push/PR
├── server/           # Express API, sync engine, RPOS + Antinet modules
├── html/              # GM console, player pages, RPOS client, shared overlays
├── examples/
│   └── demo-campaign/ # Working combat tracker example (config-driven pattern)
├── tools/              # Audit/inventory scripts — run before every push
├── docs/              # Install guide, architecture notes
├── nginx.conf          # Reference reverse-proxy config
└── .gitignore

🗺️ Roadmap

Tracked as GitHub Issues so they're easier to pick up and discuss — see the issue tracker for the current list (genericized dashboard/encounter-generator examples, per-character dossier access, adventure manager tooling, optional Obsidian export module).


🤝 Contributing

Issues and PRs welcome — especially genericized versions of the GM toolkit tools listed above. See CONTRIBUTING.md for the workflow and docs/ARCHITECTURE.md for the patterns to follow.

🔒 Security

Self-hosted, home-use threat model — see SECURITY.md before exposing this beyond your own network, and for how to report a vulnerability.

📜 License

MIT — see LICENSE


Built for a Mongoose Traveller 2E campaign, designed to work with any system.

About

Self-hosted companion OS for long-form tabletop RPG campaigns — real-time chat, AI-driven NPCs and GM tools

Topics

Resources

Contributing

Security policy

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages