10 parallel research agents (R1-R10) investigated whether MCP can save scenes as saveable entities that the user later opens in the editor — rather than injecting via a dev-only window.__pascalScene hook. Key findings: - Editor is already backend-agnostic via onLoad/onSave callbacks (R2,R7) - Current persistence is localStorage-only, single key (R1) - Zero dynamic routes and no backend code yet — env declared (R4,R5) - File import exists as "Load Build" but lacks Zod validation (R6) - MCP-written scenes load cleanly into the editor today (R6, Casa del Sol test already proved this) - Best path: filesystem-handoff this week, Supabase in weeks 2-4, Supabase Realtime for live mode in Q2. Skip Yjs for now. (R8) - 4-5 weeks to private beta, 10-14 to GA (R9) - 10 high-value ideas ranked; "photo -> scene" is the unblocker (R10) SYNTHESIS.md pulls all 10 reports together with the recommended implementation plan. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2.6 KiB
2.6 KiB
R1 — Persistence layer
TL;DR
- Scene data: single-key localStorage,
pascal-editor-scene, shape{ nodes, rootNodeIds }. Written by the autosave hook with 1 s debounce; flushed onbeforeunload. - UI preferences, viewer prefs, audio: three separate Zustand-persist stores, each with its own localStorage key.
- Asset binaries (textures): IndexedDB via
idb-keyval, keysasset_data:<uuid>. - Backend persistence: NONE in this repo. No Supabase calls, no API routes for scenes, no database integration.
- Scene identity / listing: NONE. One scene per origin per browser.
Write pathways
| When | What | Where |
|---|---|---|
| 1 s after any scene mutation | { nodes, rootNodeIds } → onSave callback (if provided) else localStorage['pascal-editor-scene'] |
packages/editor/src/hooks/use-auto-save.ts:104–135 |
| Every UI state mutation | pascal-editor-ui-preferences |
Zustand persist in use-editor.tsx:372–607 |
| Every viewer state mutation | viewer-preferences |
Zustand persist in use-viewer.ts:81–220 |
| Every audio state mutation | pascal-audio-settings |
use-audio.tsx:22–43 |
On beforeunload |
Final scene snapshot | use-auto-save.ts:137–147 |
Read pathways
- Editor mount (
editor/index.tsx:765–796):- If host supplied
onLoad→await onLoad() - Else →
loadSceneFromLocalStorage() - Apply via
useScene.setScene(nodes, rootNodeIds)
- If host supplied
- Selection hydration —
syncEditorSelectionFromCurrentScene()(lib/scene.ts:251–332) - Zustand persist hydrates UI/viewer/audio stores automatically on first subscriber
What's NOT persisted
- Undo/redo history (
useScene.temporal— in-memory only) - Active tool state (
movingNode,editingHole,curvingWall) - Camera position/rotation
- Collections (stored in nodes array but not in the persist partialize)
- Three.js mesh/material cache
Multi-scene support
- Single global key
pascal-editor-scene. No scene id, name, thumbnail, version. projectIdprop scopes UI selection (building/level/zone) but NOT scene data.- No listing, no metadata, no per-project isolation of the scene itself.
Gap to "MCP writes → user opens saved scene"
Needs:
- Scene entity layer: id, name, projectId, created_at, thumbnail_url.
- Backend table (or filesystem for local dev).
- MCP tools for scene lifecycle (
save_scene,list_scenes,load_scene,delete_scene). - Editor route
/scene/[id]that reads scene by id on mount. - Host-app
onLoad(() => fetchScene(sceneId)).
Foundation is solid — SceneGraph type + applySceneGraphToEditor are production-ready; only the entity layer is missing.