[Design] Scenes become first-class and reusable across sessions, and pairable with a Foundry map #689

Open
opened 2026-09-18 00:54:29 +00:00 by claude-bot · 2 comments
Collaborator

Owner decision, 2026-09-17, taken while scoping lane 4 of the mockups (#659). A design record, not a commitment to build it now — recorded so the redesign is drawn with it in mind rather than drawn twice.

What a scene is today

There is no scene table. shelf_cards.scene is a single nullable Text column, and SessionShelf.jsx:115 says so outright:

"A 'scene' is just a free-text tag on a card (card.scene) — there is no scene table. Creating one is tagging a card; a scene stops existing when its last card leaves it."

The scene bar is derived client-side from the distinct non-empty values across the board. So a scene cannot be empty, cannot be renamed, cannot be deleted, and cannot exist outside the session whose cards carry the string.

That was a deliberate and defensible simplification, not an oversight. #244 asked for "bundle cards into named scenes during prep and swap the shelf's active scene in one tap during play", and the implementing commit spent its effort on the part that mattered at the table — not moving the GM's cards:

  • filtering hides cards and never moves them, so a hidden card's stored x/y is untouched and swapping back restores the exact layout (#235's "spatial layout is sacred" guardrail, which the brainstorm called unanimous)
  • number keys 1–9 and the stage's prev/next walk the visible scene
  • a staged card stays staged across a swap
  • a Ctrl-K hit from another scene swaps the board to that scene, so the stage always has a board card behind it

It shipped as a 244-line frontend change with no migration. For "swap the context in one tap", the tag was the right call.

What the decision changes

A scene becomes a real entity, scoped to the campaign rather than the session, and reusable across sessions.

Two things the owner wants that a per-session string cannot do:

  1. A scene that exists before it has cards. #235's premise was bundling during prep; today you cannot make a scene and then fill it, because a scene with no cards does not exist. An empty scene has to become an ordinary state.
  2. A scene that outlives its session. The docks are the docks in March and in July. Today scene lives on shelf_cards, which are per-session, so the string can repeat but nothing connects the two.

And the reason it must be an entity, not a string: Foundry

"When we add Foundry integrations, I'd like the ability to pair maps in Foundry with scenes in Quest Board — so if I switch to a new map in Foundry, Quest Board can automatically pull up the content I have associated with that map, or vice-versa."

#16 already anticipates half of this — "trigger a Foundry macro when a session is marked started (auto-load scene…)" and "pull active scene or combat state into the session dashboard" — but as one-directional speculative Phase 4 hooks with nothing on the Quest Board side to pair against. A free-text tag on a per-session card cannot hold a stable Foundry map id; a campaign-level scene row can, and the pairing then works in both directions:

  • switch the map in Foundry → Quest Board brings up that scene's cards
  • open the scene in Quest Board → Foundry loads the paired map

That upgrades IS-266/IS-267 from "speculative hooks" to "hooks with an obvious attachment point", and it is the argument that settles tag-versus-table.

Shape (not a spec)

  • a scenes table, campaign-scoped, with at minimum a name; shelf_cards.scene_id replaces the text column
  • an empty scene is legal — that is the point of prep-time bundling
  • rename and delete become real operations, rather than retyping a string on every card and hoping nothing is left behind half-renamed
  • an optional Foundry map reference on the scene, which is where #16's Phase 4 work attaches
  • migration: distinct (session, scene) strings become scene rows; identical names in different sessions of the same campaign are the interesting case and probably want merging, with the GM asked

What must not regress

The reason the tag won in the first place. Any implementation keeps: filtering hides, never moves; stored positions untouched across a swap; the number keys and stage walking the visible set; a staged card surviving a swap; Ctrl-K from another scene swapping the board. Those are #235's guardrails and they are the good part of what exists.

Where it lands in the redesign

  • TABLE-1 (Table mode: GM face) — the scene bar, and where a scene is switched
  • PREP-1 (Prep sheet) — where a scene is built, which is the half that does not exist today
  • CAMP-16 (Settings: Foundry) — where a campaign's Foundry connection lives, and so where map pairing is configured

Lane 4 (#659) will be drawn with scenes as real objects, since drawing the tag would mean drawing it again later.

Relates to

#235 (the shelf epic, where "scene packs" was the original premise), #244 (what shipped), #16 (Foundry Phase 4 hooks), #5/#6 (Foundry connection and test, which this depends on).

**Owner decision, 2026-09-17**, taken while scoping lane 4 of the mockups (#659). A design record, not a commitment to build it now — recorded so the redesign is drawn with it in mind rather than drawn twice. ## What a scene is today There is **no scene table**. `shelf_cards.scene` is a single nullable `Text` column, and `SessionShelf.jsx:115` says so outright: > *"A 'scene' is just a free-text tag on a card (`card.scene`) — there is no scene table. Creating one is tagging a card; a scene stops existing when its last card leaves it."* The scene bar is derived client-side from the distinct non-empty values across the board. So a scene cannot be empty, cannot be renamed, cannot be deleted, and cannot exist outside the session whose cards carry the string. **That was a deliberate and defensible simplification**, not an oversight. #244 asked for "bundle cards into named scenes during prep and swap the shelf's active scene in one tap during play", and the implementing commit spent its effort on the part that mattered at the table — not moving the GM's cards: - filtering **hides** cards and never moves them, so a hidden card's stored x/y is untouched and swapping back restores the exact layout (#235's "spatial layout is sacred" guardrail, which the brainstorm called unanimous) - number keys 1–9 and the stage's prev/next walk the *visible* scene - a staged card stays staged across a swap - a Ctrl-K hit from another scene swaps the board to that scene, so the stage always has a board card behind it It shipped as a 244-line frontend change with no migration. For "swap the context in one tap", the tag was the right call. ## What the decision changes **A scene becomes a real entity, scoped to the campaign rather than the session, and reusable across sessions.** Two things the owner wants that a per-session string cannot do: 1. **A scene that exists before it has cards.** #235's premise was bundling *during prep*; today you cannot make a scene and then fill it, because a scene with no cards does not exist. An empty scene has to become an ordinary state. 2. **A scene that outlives its session.** The docks are the docks in March and in July. Today `scene` lives on `shelf_cards`, which are per-session, so the string can repeat but nothing connects the two. ## And the reason it must be an entity, not a string: Foundry > *"When we add Foundry integrations, I'd like the ability to pair maps in Foundry with scenes in Quest Board — so if I switch to a new map in Foundry, Quest Board can automatically pull up the content I have associated with that map, or vice-versa."* **#16 already anticipates half of this** — "trigger a Foundry macro when a session is marked started (auto-load scene…)" and "pull active scene or combat state into the session dashboard" — but as one-directional speculative Phase 4 hooks with **nothing on the Quest Board side to pair against**. A free-text tag on a per-session card cannot hold a stable Foundry map id; a campaign-level scene row can, and the pairing then works in both directions: - switch the map in Foundry → Quest Board brings up that scene's cards - open the scene in Quest Board → Foundry loads the paired map That upgrades `IS-266`/`IS-267` from "speculative hooks" to "hooks with an obvious attachment point", and it is the argument that settles tag-versus-table. ## Shape (not a spec) - a `scenes` table, **campaign-scoped**, with at minimum a name; `shelf_cards.scene_id` replaces the text column - an **empty scene is legal** — that is the point of prep-time bundling - **rename and delete become real operations**, rather than retyping a string on every card and hoping nothing is left behind half-renamed - an optional **Foundry map reference** on the scene, which is where #16's Phase 4 work attaches - migration: distinct `(session, scene)` strings become scene rows; identical names in different sessions of the same campaign are the interesting case and probably want merging, with the GM asked ## What must not regress The reason the tag won in the first place. Any implementation keeps: **filtering hides, never moves**; stored positions untouched across a swap; the number keys and stage walking the visible set; a staged card surviving a swap; Ctrl-K from another scene swapping the board. Those are #235's guardrails and they are the good part of what exists. ## Where it lands in the redesign - **`TABLE-1`** (Table mode: GM face) — the scene bar, and where a scene is switched - **`PREP-1`** (Prep sheet) — where a scene is *built*, which is the half that does not exist today - **`CAMP-16`** (Settings: Foundry) — where a campaign's Foundry connection lives, and so where map pairing is configured Lane 4 (#659) will be **drawn with scenes as real objects**, since drawing the tag would mean drawing it again later. ## Relates to #235 (the shelf epic, where "scene packs" was the original premise), #244 (what shipped), #16 (Foundry Phase 4 hooks), #5/#6 (Foundry connection and test, which this depends on).
Author
Collaborator

Split (owner, 2026-11-06). The Quest Board half goes to v4.8.0 as #1347: a scenes table scoped to the campaign, empty scenes allowed, reuse across sessions, real rename and delete, and the migration from the text tags.

This issue keeps only the Foundry map pairing, for v5.1:

  • the scene's foundry_map_ref (left empty by #1347);
  • switching the map in Foundry brings up the scene in Quest Board;
  • opening the scene in Quest Board loads the paired map in Foundry.

It depends on the v5.0 connection (#143, #5, #6).

**Split (owner, 2026-11-06).** The Quest Board half goes to v4.8.0 as #1347: a `scenes` table scoped to the campaign, empty scenes allowed, reuse across sessions, real rename and delete, and the migration from the text tags. This issue keeps **only the Foundry map pairing**, for v5.1: - the scene's `foundry_map_ref` (left empty by #1347); - switching the map in Foundry brings up the scene in Quest Board; - opening the scene in Quest Board loads the paired map in Foundry. It depends on the v5.0 connection (#143, #5, #6).
Author
Collaborator

Correction to the 2026-11-06 split: #1347 is closed. Its whole scope (campaign-wide scenes, empty scenes, rename, delete with Undo, reuse, and the migration with D114's automatic merge) already shipped in 4.5.0 (#731). This issue stays as the Foundry map pairing only, for v5.1, which adds the one column D113 left out.

**Correction to the 2026-11-06 split:** #1347 is closed. Its whole scope (campaign-wide scenes, empty scenes, rename, delete with Undo, reuse, and the migration with D114's automatic merge) already shipped in 4.5.0 (#731). This issue stays as the Foundry map pairing only, for v5.1, which adds the one column D113 left out.
Sign in to join this conversation.
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#689
No description provided.