[Foundry] Bidirectional integration — architecture & design reference #24
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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.mdbecause the architecture spans every Foundry phase and informs each of those issues.Phase issues & milestones
actor_to_member· #8 member-list syncnpc_to_actor+ Send to Foundry · #10genericadapterjournal_to_entry· #14member_to_actorwriteback · #15 more system adaptersOverview
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.
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 APIadapters/base.py— abstract base class / protocol defining the interfaceadapters/pf2e.py— first concrete adapteradapters/generic.py— raw JSON passthrough for unknown systemsregistry.py— maps system identifier strings to adapter classesAdapter interface
Each method optional; return
Noneto declare the operation unsupported:actor_to_member(foundry_actor)— pull actor data onto a CampaignMembermember_to_actor(campaign_member)— push a member's sheet back to Foundrynpc_to_actor(generated_npc)— push a Quest Board-generated NPC to Foundryjournal_to_entry(lore_entry)— push a lore entry to a Foundry journal pageitem_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 pushImplementation notes
genericadapter enables passthrough for systems without a named adapter; it is not a substitute for a real adapter.BOT_API_KEY. Mirror the existingBOT_API_KEYstorage pattern inapp_settingsrather than introducing a new encryption scheme just for this.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
character_sheet_url/character_sheet_notesfields on CampaignMember[Foundry] Bidirectional integration — architecture & design referenceto [Foundry] Bidirectional integration — architecture & design reference