[Foundry] Bidirectional integration — architecture & design reference #24

Open
opened 2026-06-24 04:21:51 +00:00 by rbrooks · 0 comments
Owner

Purpose

This is the architecture / design reference for the FoundryVTT bidirectional integration. It is not a work item — the actionable slices are tracked in the phase issues and milestones below. It's migrated here from the now-deleted docs/ENHANCEMENTS.md because the architecture spans every Foundry phase and informs each of those issues.

Phase issues & milestones

  • v4.0.0 — Phase 1 Foundation: #4 install/validate · #5 connection settings · #6 health check · #7 adapter scaffolding + actor_to_member · #8 member-list sync
  • v4.1.0 — Phase 2 NPC Push: #9 npc_to_actor + Send to Foundry · #10 generic adapter
  • v4.3.0 — Phase 3 Lore Sync: #13 journal_to_entry · #14 member_to_actor writeback · #15 more system adapters
  • Backlog: #16 Phase 4 ops hooks · #17 Matrix / Element parity
  • Milestones: https://git.rhoving.com/rbrooks/Quest-Board/milestones

Overview

Quest Board already stores character sheet URLs and notes, but groups using Foundry still manage those links manually and have no way to push content the other direction. A proper bidirectional integration lets Quest Board pull live character data into the member list, push AI-generated NPCs into Foundry, sync lore entries to Foundry journals, and eventually trigger scene or playlist changes from session events — all without leaving Quest Board.

Because tabletop systems vary enormously, the integration is built around a per-campaign system adapter so PF2e, Honey Heist, Ryuutama, and the Discworld RPG can each be wired in on their own terms without touching shared code.

Quest Board data model
        ↕  (adapter interface)
System adapter (pf2e / generic / …)
        ↕  (HTTP + API key)
foundryvtt-rest-api module on the Foundry instance

Each campaign stores a Foundry server URL, an API key, and a system identifier. The system identifier selects an adapter that translates between Quest Board's internal representation and the target system's Foundry actor/journal schema. Unimplemented adapter operations return None; the UI hides the corresponding buttons rather than showing disabled controls.

Proposed backend package — webapp/backend/app/foundry/

  • client.py — authenticated HTTP calls to the Foundry REST API
  • adapters/base.py — abstract base class / protocol defining the interface
  • adapters/pf2e.py — first concrete adapter
  • adapters/generic.py — raw JSON passthrough for unknown systems
  • registry.py — maps system identifier strings to adapter classes

Adapter interface

Each method optional; return None to declare the operation unsupported:

  • actor_to_member(foundry_actor) — pull actor data onto a CampaignMember
  • member_to_actor(campaign_member) — push a member's sheet back to Foundry
  • npc_to_actor(generated_npc) — push a Quest Board-generated NPC to Foundry
  • journal_to_entry(lore_entry) — push a lore entry to a Foundry journal page
  • item_to_item(item) — push a generated item (treasure, custom gear, spells) to Foundry's Items directory; needed when the item doesn't already exist in a compendium and can't be resolved by name during an NPC or loot push

Implementation notes

  • All system-specific logic must stay behind the adapter boundary. No system-specific branches in API routes or the campaign model.
  • The generic adapter enables passthrough for systems without a named adapter; it is not a substitute for a real adapter.
  • Foundry is often hosted locally or behind a VPN. The per-campaign URL field is intentional — every group's network setup will differ.
  • The Foundry API key is a credential. Store it encrypted at rest, never log it, and never include it in API responses — treat it the same as BOT_API_KEY. Mirror the existing BOT_API_KEY storage pattern in app_settings rather than introducing a new encryption scheme just for this.
  • The foundryvtt-rest-api module has historically been sensitive to Foundry core version upgrades. Document the tested module + core version pair and flag compatibility as a maintenance concern when either is updated.
  • Phases 3 and 4 depend on operating experience with the Phase 1/2 surface. Do not commit to their scope until Phase 2 is stable.

Critical sequencing for Phase 1

Do #4 (install module) and #6 (connection health check) first and against the real production Foundry instance, before writing adapter code (#7). The REST module is documented as version-sensitive — confirm it works on the actual target instance before sinking adapter time.

Dependencies

  • Existing character_sheet_url / character_sheet_notes fields on CampaignMember
  • ThreeHats/foundryvtt-rest-api module installed and reachable from the backend
  • NPC generation feature (for Phase 2)
  • Lore entry storage (for Phase 3)
## Purpose This is the **architecture / design reference** for the FoundryVTT bidirectional integration. It is **not** a work item — the actionable slices are tracked in the phase issues and milestones below. It's migrated here from the now-deleted `docs/ENHANCEMENTS.md` because the architecture spans every Foundry phase and informs each of those issues. **Phase issues & milestones** - v4.0.0 — Phase 1 Foundation: #4 install/validate · #5 connection settings · #6 health check · #7 adapter scaffolding + `actor_to_member` · #8 member-list sync - v4.1.0 — Phase 2 NPC Push: #9 `npc_to_actor` + Send to Foundry · #10 `generic` adapter - v4.3.0 — Phase 3 Lore Sync: #13 `journal_to_entry` · #14 `member_to_actor` writeback · #15 more system adapters - Backlog: #16 Phase 4 ops hooks · #17 Matrix / Element parity - Milestones: https://git.rhoving.com/rbrooks/Quest-Board/milestones --- ## Overview Quest Board already stores character sheet URLs and notes, but groups using Foundry still manage those links manually and have no way to push content the other direction. A proper bidirectional integration lets Quest Board pull live character data into the member list, push AI-generated NPCs into Foundry, sync lore entries to Foundry journals, and eventually trigger scene or playlist changes from session events — all without leaving Quest Board. Because tabletop systems vary enormously, the integration is built around a **per-campaign system adapter** so PF2e, Honey Heist, Ryuutama, and the Discworld RPG can each be wired in on their own terms without touching shared code. ``` Quest Board data model ↕ (adapter interface) System adapter (pf2e / generic / …) ↕ (HTTP + API key) foundryvtt-rest-api module on the Foundry instance ``` Each campaign stores a Foundry server URL, an API key, and a system identifier. The system identifier selects an adapter that translates between Quest Board's internal representation and the target system's Foundry actor/journal schema. Unimplemented adapter operations return `None`; the UI hides the corresponding buttons rather than showing disabled controls. ## Proposed backend package — `webapp/backend/app/foundry/` - `client.py` — authenticated HTTP calls to the Foundry REST API - `adapters/base.py` — abstract base class / protocol defining the interface - `adapters/pf2e.py` — first concrete adapter - `adapters/generic.py` — raw JSON passthrough for unknown systems - `registry.py` — maps system identifier strings to adapter classes ## Adapter interface Each method optional; return `None` to declare the operation unsupported: - `actor_to_member(foundry_actor)` — pull actor data onto a CampaignMember - `member_to_actor(campaign_member)` — push a member's sheet back to Foundry - `npc_to_actor(generated_npc)` — push a Quest Board-generated NPC to Foundry - `journal_to_entry(lore_entry)` — push a lore entry to a Foundry journal page - `item_to_item(item)` — push a generated item (treasure, custom gear, spells) to Foundry's Items directory; needed when the item doesn't already exist in a compendium and can't be resolved by name during an NPC or loot push ## Implementation notes - All system-specific logic must stay behind the adapter boundary. **No system-specific branches in API routes or the campaign model.** - The `generic` adapter enables passthrough for systems without a named adapter; it is not a substitute for a real adapter. - Foundry is often hosted locally or behind a VPN. The per-campaign URL field is intentional — every group's network setup will differ. - The Foundry API key is a credential. Store it encrypted at rest, never log it, and never include it in API responses — treat it the same as `BOT_API_KEY`. **Mirror the existing `BOT_API_KEY` storage pattern in `app_settings`** rather than introducing a new encryption scheme just for this. - The foundryvtt-rest-api module has historically been sensitive to Foundry core version upgrades. Document the tested module + core version pair and flag compatibility as a maintenance concern when either is updated. - Phases 3 and 4 depend on operating experience with the Phase 1/2 surface. Do not commit to their scope until Phase 2 is stable. ## Critical sequencing for Phase 1 Do #4 (install module) and #6 (connection health check) **first and against the real production Foundry instance**, before writing adapter code (#7). The REST module is documented as version-sensitive — confirm it works on the actual target instance before sinking adapter time. ## Dependencies - Existing `character_sheet_url` / `character_sheet_notes` fields on CampaignMember - ThreeHats/foundryvtt-rest-api module installed and reachable from the backend - NPC generation feature (for Phase 2) - Lore entry storage (for Phase 3)
rbrooks changed title from [Foundry] Bidirectional integration — architecture & design reference to [Foundry] Bidirectional integration — architecture & design reference 2026-06-24 04:21:59 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rbrooks/Quest-Board#24
No description provided.