Handles Vite + TypeScript frontend, canvas display rendering, keyboard/mouse input, controls UI, browser persistence, and emulator integration.
NOTE: Startup and cleanup are handled by worker-base. This skill defines the WORK PROCEDURE.
Use for features involving:
Read the feature description, preconditions, expectedBehavior, and verificationSteps. Read AGENTS.md for boundaries and conventions. Read .factory/library/ files for architecture and environment details. Read research docs if needed (QEMU_WASM_RESEARCH.md, QEMU_WASM_DISPLAY_RESEARCH.md).
Write Vitest unit tests BEFORE implementation:
Run tests — they MUST fail initially (red). Then implement to make them pass (green).
Follow the feature's expectedBehavior precisely. Key patterns:
For Emscripten integration:
Module['mainScriptUrlOrBlob'] for Web Worker URLFor display rendering:
setInterval at ~30ms (NOT requestAnimationFrame — rAF is hijacked by PROXY_TO_PTHREAD)Module._qemu_display_data(), _qemu_display_width(), _qemu_display_height()new Uint8ClampedArray(Module.HEAPU8.buffer, fbPtr, width * height * 4)For keyboard input:
keydown and keyup on the canvas containerKeyboardEvent.code to QEMU scancodes (PS/2 Set 1)Module._qemu_input_send_key(scancode, isDown ? 1 : 0)preventDefault() for F-keys, Escape, and other interceptable shortcutsdocument.activeElement)blur event), release all currently held keysFor mouse input:
mousemove, mousedown, mouseup on canvasModule._qemu_input_send_mouse(dx, dy, buttons)For controls UI:
For persistence (OPFS/IndexedDB):
navigator.storage.getDirectory()beforeunloadnavigator.storage.persist() to reduce eviction riskFor COOP/COEP headers (Vite config):
// vite.config.ts