9f19fed8a1
Submodule bump: 6129375 -> 1a984b0 Pulls in the firmware build fixes pushed to github.com/electron-rare/ESP32_ZACUS branch fix/build-arduino-esp32-3.20014 (PR pending review). The firmware now compiles cleanly and survives boot on the Freenove ESP32-S3 dev board (verified flash + 30 s monitor: SD mounted, LittleFS ready, no panic, 90 k UI frames). Once the upstream PR is merged to main, the parent pointer can be re-bumped to ESP32_ZACUS@main without changes. CLAUDE.md refresh (init-deep follow-up): - frontend-v3/apps/atelier/CLAUDE.md (new, 61 lines): layout map, store responsibilities, lazy-chunk pattern, dev-only window hooks, build with --base, anti-patterns. - desktop/CLAUDE.md (+8 lines): Tests section + npm test command + --ignore-scripts install hint. - tests/CLAUDE.md (+1 line): list test_firmware_bundle.py alongside test_runtime3_routes.py. All nested CLAUDE.md remain within the 30-80 line target (longest is atelier at 61).
3.8 KiB
3.8 KiB
Atelier
Scratch-like authoring studio: Blockly editor (left/center) + R3F 3D simulation stage (right) + validation console (bottom). Live-diff: edit a block → 500 ms debounce → stale badge → click Run → simulation reloads via simStore.loadScenario(yaml).
Design doc: docs/superpowers/specs/2026-05-01-v3-fusion-atelier-design.md.
Layout
src/
main.tsx # ReactDOM root, StrictMode
App.tsx # useLiveDiff() + <Layout/>; dev hooks on window
main.css # Shell + pane styles
vite-env.d.ts # Vite client types
components/
Layout.tsx # PanelGroup tree, ⌘B stage toggle
EditorPane.tsx # Lazy(BlocklyWorkspace) + register blocks + validate on change
StagePane.tsx # Lazy(RoomScene + mode HUDs) + Run button
ConsolePane.tsx # Mode tabs + validation entries list
BlocklyWorkspace.tsx # forwardRef wrapper around Blockly.inject
toolbox.ts # XML toolbox config
YamlPreview.tsx # Syntax-highlighted YAML rendering
blocks/
{puzzle,npc,flow}-blocks.ts # Block definitions + YAML generators
index.ts # registerAllBlocks (idempotent)
scene/ # R3F 3D scene (RoomScene, RtcPhone, PuzzleStations, NpcBubble)
puzzles/ # P1Sound, P5Morse, P6Symbols, P7Coffre (3D widgets)
modes/ # SandboxMode, DemoMode, TestMode HUDs
stores/ # editor / runtime / sim / validation (zustand)
lib/
yaml-export.ts # workspace -> YAML
yaml-import.ts # YAML -> workspace
validator.ts # 6-rule schema check (ScenarioYaml -> ValidationResult)
useLiveDiff.ts # debounce 500 ms then setPendingIr
Patterns
- Lazy chunks via
React.lazy+ Suspense for both Blockly (~700 kB gzip) and R3F+three (~1 MB gzip). Initial shell stays under 80 kB. VitemanualChunksinvite.config.tsenforces the split. - Stores stay focused:
editorStore= blocklyJson string ;runtimeStore= pending/current IR + isStale ;simStore= mode + engine instance + npcMood ;validationStore= entries withseverity+source(schema|compile|runtime|test). - Mode is sim concern, not editor↔stage sync — lives in
simStore. ConsolePane reads from there. - Run button in
StagePaneis the only commit point: it callssimStore.loadScenario(pendingIr)thenruntimeStore.commitPendingIr(). - Tailwind classes are not configured — use inline styles or
main.cssclasses (atelier-pane,atelier-mode-tab,atelier-resizer--*). Tailwind in legacy simulation HUDs was rewritten as inline styles during P4. - Dev-only window hooks:
App.tsxexposes stores onwindow.__atelierStores,Layout.tsxexposeswindow.__atelierToggleStage,EditorPane.tsxexposeswindow.__atelierBlockly.getWorkspace(). All gated byimport.meta.env.DEV. E2E specs drive workflow through them instead of relying on real DnD.
Build
pnpm exec vite build --base=/atelier/ # for prod deployment with prefix
pnpm exec vite build # for dev / desktop bundle (root path)
pnpm --filter @zacus/atelier build -- --base=... does NOT pass --base correctly through the script chain — call vite directly via cd apps/atelier && pnpm exec vite ....
Anti-patterns
- Putting
modeback intoruntimeStore— it belongs tosimStore. - Calling
voiceWsConnect()or any lwip-touching code at boot without a network-ready guard (matches the ESP32_ZACUS bug fix from this session). - Hardcoding
/atelier/as base path — the dev server uses root, only the deployed prod build uses the prefix. - Adding deps to root
frontend-v3/package.json— atelier deps live here. - Bypassing the Run button to mutate
simStore.enginedirectly — breaks the live-diff contract.