--- title: Background catalogue with thumbnail previews type: feat date: 2026-10-24 topic: background-catalog artifact_contract: ce-unified-plan/v1 execution: code status: requirements-only related_spike: https://github.com/adamsloane/digitalwalls/pull/57 --- > Status: Implemented in PR #57 (cursor/background-catalog-b773). This document is the scoping record; prefer the shipping PR for behavior.
Background catalogue with thumbnail previews — Plan
Status: Requirements / design only — do not treat as approved to ship UI until Adam locks open questions. Audience: Adam (approve / course-correct), coding agent (implement after approval). Constraint: Parity with sprite catalog UX where it fits; keep Wall Setup for non-background atmosphere. Match Option B / soft-elevated language — no generic purple AI aesthetic.
Related spike: #57 already implements a close cousin of this plan (Setup → Browse backgrounds, reuse #catalogPage, CSS swatches for classic materials, DW portrait canvas). Treat #57 as a prototype to validate against this plan, not as product authority. Prefer merging a revised #57 (or a follow-on PR) only after Adam locks §9.
---
1. Product goal + success criteria
Goal
Wall owners pick a background / room surface from a visual catalogue (thumbnail grid + categories), the same way they pick sprites today — not by scanning a text <select> of material ids.
Problem frame
Today Setup → Material (#materialSelect in public/index.html) is a flat list of labels (hearth, smoke-*, dw-*, brick, etc.). Soft rooms and DW rooms are image-backed; classic materials are CSS gradients/patterns. Without thumbnails, people cannot tell soft Hearth from classic Hearth room, or preview a DW loft before committing. Sprites already solve “see it, then Add” via #catalogPage / renderCatalog.
Success criteria
1. Every selectable background shows a recognizable thumbnail (real room image or honest CSS swatch). 2. Categories make Soft rooms / Design-system rooms / Classic surfaces scannable in ≤ one scroll on desktop. 3. Applying a background updates the live wall and persists (wallConfig.material + existing lighting heuristics), with clear current / selected affordance. 4. Setup still owns location, lighting, window placement, and window view; background is no longer a blind dropdown. 5. Object catalog (Add) remains unchanged; backgrounds do not pollute the sprite grid unless Adam explicitly wants a dock shortcut. 6. Desktop and ~390px mobile: catalog usable; no horizontal page overflow; thumbnails readable at card size. 7. E2E that today drive #materialSelect still can change material (hidden sync select, test helpers, or updated selectors).
---
2. What counts as a “background” entry
A background is one value of wallConfig.material that paints the wall canvas. Three kinds exist today:
| Kind | Material ids | How the wall paints | Window pane |
|---|---|---|---|
| Soft rooms | smoke-hearth, smoke-garden, smoke-moonroom | Full-bleed JPG blanks under public/assets/backgrounds/smoke-*-blank.jpg | Overlay supported (painted aperture); placement none keeps painted view |
| Design-system rooms (DW) | dw-sunlit-apartment, dw-creative-loft, dw-modern-gallery | Full-bleed PNGs; source art is portrait (~4:5) | Baked into image — pane hidden (MATERIALS_WITHOUT_WINDOW_PANE) |
| Classic surfaces | hearth, light, greenhouse, brick, concrete, gallery, plaster, wood | Mostly CSS gradients/patterns; greenhouse uses garden-terminal-room.png | Composable pane (except greenhouse hides architecture) |
Greenhouse is hybrid: image-backed like a room, but historically grouped with classic Garden Terminal. Recommendation: keep it under Classic surfaces (Studio / Garden Terminal lineage), with a real PNG thumb — same as #57.
Thumbnail strategy (recommended)
| Kind | Thumbnail source | Notes |
|---|---|---|
| Soft rooms | Production JPG (smoke-*-blank.jpg) via background-image: cover | Honest; blank rooms look empty by design — that is correct |
| DW rooms | Production PNG (dw-*.png) via cover + center | Prefer portrait crop in the card if cards stay landscape; optional later: dedicated square thumbs |
| Classic CSS-only | CSS preview classes mirroring wall material gradients (e.g. .thumb-material-brick) | No new raster assets for v1 |
| Greenhouse | garden-terminal-room.png | Same as soft/DW path |
Do not screenshot the live wall with placed items for catalog thumbs (noisy, privacy, stale). Thumbs are empty surface / room only.
Portrait DW note: Live canvas should use a portrait frame for DW materials so background-size: cover does not landscape-crop the room (spike: 900×1125 vs default 1200×800). Catalog thumbs can stay square/card-sized; canvas framing is a separate correctness fix bundled with S1 if still needed on main.
---
3. Placement — where the picker lives
Recommendation (v1)
| Surface | Role |
|---|---|
| Setup | Primary entry: show current thumb + label + “Browse backgrounds”. Hide #materialSelect (keep in DOM for sync / tests / design-language defaults). |
| Add (object catalog) | Objects only. Do not mix backgrounds into sprite categories in v1. |
| Dock / Visit | No new dock button in v1. |
Rationale: Backgrounds are atmosphere (Setup), objects are placement (Add). Closing Setup when opening the background catalog is fine — apply returns to the wall; user can reopen Setup for lighting/windows.
Alternatives rejected for v1
- Replace Setup entirely with catalog only (loses location/lighting/windows grouping).
- Dual entry Add + Setup (extra chrome; easy to confuse with sprites).
- Keep visible dropdown + catalog (defeats the product goal).
Setup retains: design language, showcase, location, lighting, window placement, window view.
---
4. Categories
Align nav chips with sprite catalog pattern (catalog-nav-chip):
| Chip key | Label | Contents |
|---|---|---|
all | All | Full list |
soft | Soft rooms | smoke-hearth, smoke-garden, smoke-moonroom |
rooms | Design system | dw-sunlit-apartment, dw-creative-loft, dw-modern-gallery |
classic | Classic | hearth, light, greenhouse, brick… wood |
Section headings inside the grid mirror the groups (same as sprite sections). Order soft → rooms → classic so elevated language leads.
---
5. Active / selected state and Apply behavior
Selected state
- Card for current
wallConfig.material: visual selected ring + meta “Current” + button Selected (disabled) or equivalent. - Setup row always shows the current thumb + label after apply or design-language default swap.
Apply behavior — recommendation: instant apply
Match sprite catalog: one primary action (Use {label}) → update material (+ existing lighting heuristics for soft/hearth) → save → close catalog → show wall.
| Option | Pros | Cons |
|---|---|---|
| Instant (recommended) | Same muscle memory as Add sprite; fewer steps | Preview-before-commit needs undo (already have Undo) |
| Confirm / Apply in Setup | Safer for “browsing only” | Extra friction; breaks catalog parity |
Preserve existing lighting auto-adjust when entering soft rooms / hearth (updateWallConfig / applyBackground heuristics). Design language changes that set material should also refresh the Setup thumb.
---
6. Mobile vs desktop
| Concern | Approach |
|---|---|
| Catalog chrome | Reuse #catalogPage dialog + existing mobile catalog CSS (styles.css ~3520+) |
| Cards | Same catalog-object-grid / minmax(170px, 1fr); background previews use cover, not live DOM samples |
| Setup picker | Thumb ~88px + Browse button; stack to single column if Setup gets tight |
| DW portrait canvas | Fit/pan logic must use material-aware wallSize() so mobile edit/visit do not assume 1200×800 |
| Visit | Backgrounds only editable in Arrange (unchanged) |
---
7. Out of scope (v1)
- Window views catalog — keep
#windowViewSelectin Setup; separate future “Outside scenes” catalog if desired. - Lighting catalog / thumbnails — remain a Setup
<select>. - User-uploaded custom backgrounds.
- Merging backgrounds into Add / Icon Catalog as a category.
- Server schema changes — materials already validated in
server/validation.js. - Studio page redesign — Studio remains reference; wall picker is product UI.
- New raster thumb pack for classic CSS materials (swatches suffice).
- Play-earn / shop backgrounds.
Bundled correctness that is in scope if still missing on `main`: DW portrait canvas sizing (so thumbs and live wall match intent). Session fix for New wall same-origin redirect is orthogonal — ship separately if possible (#56 / part of #57).
---
8. Implementation approach
Reuse vs new dialog
Reuse `#catalogPage` with a catalogKind of objects | backgrounds (or equivalent). Same header/nav/grid shell; swap title/lede, nav chips, and card renderer.
| Pros | Cons |
|---|---|
| One modal to maintain; known a11y/mobile behavior | Kind state must reset on close / Add click |
| Matches “like sprites” ask | Slightly denser wall.js |
New `#backgroundCatalogDialog` only if reuse fights object catalog too hard (unlikely for v1).
Data model (client)
Introduce a single catalog table, e.g. WALL_BACKGROUNDS[]:
{ id, label, category: soft|rooms|classic, thumb?: url, thumbClass?: string }
id===wallConfig.material(no parallel naming).- Keep
#materialSelectoptions in sync (hidden) sosetDesignLanguage/updateWallConfigkeep working. - Server allow-list already includes all ids — no API change.
Thumbnail rendering
- Image entries:
preview.style.backgroundImage = url(thumb). - CSS entries: add
thumbClasson preview / Setup thumb. - Do not mount a mini
.wallDOM for v1 (expensive, brittle).
Files likely touched (after approval)
public/index.html— Setup background picker chrome; catalog lede idpublic/wall.js—WALL_BACKGROUNDS,renderBackgroundCatalog,applyBackground, Setup sync; optionalwallCanvasSizepublic/styles.css— Setup picker, selected card, thumb swatches; DW canvas if neededtests/e2e/*.spec.ts— material change via Browse or hidden select
Pattern to follow
Sprite path: Add → setView("catalog") → renderCatalog → createCatalogCard → action closes to wall. Backgrounds: Setup → Browse → catalogKind = backgrounds → Use … → applyBackground → wall.
---
9. Open questions for Adam
1. Entry points: Confirm Setup-only Browse for v1 (no Add/dock shortcut)? 2. Apply: Instant Use (recommended) vs select-then-confirm back in Setup? 3. Greenhouse grouping: Classic surfaces (recommended) vs Design-system rooms? 4. Classic Hearth (`hearth`) vs Soft Hearth (`smoke-hearth`): Keep both visible, or soft-only + collapse classic hearth? 5. Closing Setup when browsing: OK to close Setup on Browse (spike behavior), or keep Setup open behind the catalog? 6. DW portrait canvas: Approve 900×1125 (or similar) when DW material active, knowing item coordinates may feel different across aspect changes? 7. Window views: Explicitly defer thumbnail catalog (recommended)? 8. #57: Review as prototype and either (a) revise to match this plan then merge, or (b) hold and implement cleanly from this plan after answers?
---
10. Build slices
S1 — Background catalog MVP (recommended first ship)
Goal: Replace the Setup material dropdown UX with thumbnail browsing; soft + DW use production images; classic use CSS swatches; instant apply; selected state; Setup keeps location/lighting/windows.
Includes:
WALL_BACKGROUNDS+ Setup thumb + Browse- Reuse
#catalogPagein backgrounds mode - Categories Soft / Design system / Classic
- Hidden
#materialSelectsync - Lighting heuristics preserved
- E2E update for material pick
- DW portrait canvas if still broken on
main(correctness for DW thumbs)
Does not include: Window-view catalog, dock entry, new classic PNGs, dedicated dialog.
S2 — Polish + discovery
- Optional dock or Setup-adjacent shortcut if Adam wants second entry
- Dedicated square thumb assets for classic materials (if swatches feel weak)
- Portrait-aware card framing for DW thumbs
- Optional “Outside scenes” catalog for window views (same pattern)
- Collapse/hide low-priority classic materials if catalog feels long
- Visual regression / Studio cross-links for new backgrounds
---
Assumed defaults (until Adam answers)
Use these if implementing under time pressure without reply — still prefer locking §9 first:
1. Setup-only entry; no Add mixing. 2. Instant Use. 3. Greenhouse → Classic. 4. Keep both hearth variants labeled clearly (“Hearth soft” vs “Hearth room”). 5. Close Setup when opening background catalog. 6. DW portrait canvas when DW material selected. 7. Window views stay Setup selects. 8. Prefer revising #57 against this plan over a parallel rewrite if the spike is still green.
---
Current code anchors
| Concern | Location |
|---|---|
| Material dropdown | public/index.html #materialSelect / #setupDialog |
| Apply + lighting heuristics | public/wall.js updateWallConfig, openSetup |
| Soft / full-room sets | SOFT_ROOM_MATERIALS, MATERIALS_WITHOUT_WINDOW_PANE |
| Sprite catalog UX | renderCatalog, createCatalogCard, #catalogPage |
| Material paint | public/styles.css .wall.material-* |
| Server allow-list | server/validation.js wallConfig.material choice list |
| Background assets | public/assets/backgrounds/ |
| Window assets (OOS) | public/assets/windows/ |