Skip to content

fix(compose): keep the scene background instead of losing it on refresh - #25

Merged
github-actions[bot] merged 1 commit into
mainfrom
fix/persist-scene-background
Aug 28, 2026
Merged

fix(compose): keep the scene background instead of losing it on refresh#25
github-actions[bot] merged 1 commit into
mainfrom
fix/persist-scene-background

Conversation

@catomean

Copy link
Copy Markdown
Collaborator

The bug

The scene background — the place the figures stand in — was held only in a URL.createObjectURL blob in React state. It was never uploaded and compositions.background_url was never written, even though the column, the backgrounds/ storage folder, and an authorized, versioned /api/compositions route all already existed. Nothing in the app called that route.

Two consequences:

  1. Reopen the project and the canvas is bare black — the background is gone.
  2. The export silently ships that. handleExportPng renders the Konva stage as it finds it, so it produces panel files with no scene in them and still reports Print-ready — N panel files at 200 DPI. Same failure shape as the baked-in guides in fix(export): produce a file the print shop can actually use #20: a confident success message on an artifact nobody re-checks before it reaches the print shop.

The fix

  • useComposition / useSaveComposition (matching the useSurface idiom) wire the existing endpoint up.
  • Background upload goes to storage (backgrounds/, already supported by getStoragePath; insert is still permitted after fix(storage): take delete and update away from the anon key #24) and the path to the composition row, so it reloads with the project.
  • Loaded via crossOrigin = 'anonymous', the same as FigureLayer — that is what keeps the stage untainted so the export can still read pixels back out.
  • The image is derived from the saved path rather than stored, so a stale background can't be painted (and no setState in an effect).
  • Export and the background button are disabled while a save is in flight; exporting then would print the bare canvas.

Only background_url is written. Figure placement already lives on the figures rows — copying it into layout would give it a second home.

Regression guard

An orphaned endpoint is what made this invisible. wired.test.ts fails if any route family has no caller in the app. Mutation-verified: removing the new hook fails it on /api/compositions, and it passes with the hook restored.

Verify

  • lint: 0 errors, 8 warnings (all pre-existing)
  • tsc: clean
  • tests: 78 pass · 0 fail (was 73)

🤖 Generated with Claude Code

https://claude.ai/code/session_014opKWKa65PXxn2MiWSKwwh

The background is the scene — the place the figures stand in. The editor
collected it into a URL.createObjectURL blob in React state and stopped
there: it was never uploaded, and compositions.background_url was never
written, even though the column, the storage folder and an authorized,
versioned /api/compositions route all already existed.

So the background survived exactly one page view. Reopen the project the
next day and the canvas is bare black — and the export takes the stage as
it finds it, renders the panels from it and reports "print-ready" for a
file with no scene in it at all. Same failure shape as the baked-in guides
in #20: a confident success message on an artifact nobody re-checks before
it goes to the print shop.

The upload now goes to storage and the path to the composition row, so the
background reloads with the project. Export refuses to run while it is
still in flight rather than printing the bare canvas.

Only background_url is written. Figure placement already lives on the
figures rows, and copying it into layout would give it a second home.

An orphaned endpoint is what made this invisible, so wired.test.ts fails
if any route family has no caller in the app — verified by removing the
new hook, which fails it on /api/compositions.

verify: lint 0 errors (8 pre-existing warnings) · tsc clean · 78 tests pass

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014opKWKa65PXxn2MiWSKwwh
@github-actions
github-actions Bot merged commit 6d000c6 into main Aug 28, 2026
1 check passed
@github-actions
github-actions Bot deleted the fix/persist-scene-background branch August 28, 2026 04:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant