Development #
Use Node.js 22+. Run node serve.mjs with no build step. For formatting, npm ci installs pinned Prettier, then npm run format or npm run format:check. Vendor modules, lookup grids, textures, and user settings are excluded.
Avatar-specific code lives behind the module contract. Keep tracking and the host independent of individual rigs. Add registry entries rather than avatar conditionals in the app.
Source map #
| File | Responsibility |
|---|---|
| serve.mjs | Static HTTP, pose SSE, source endpoints, settings actions |
| phone-tracker.mjs | UDP validation, centering, pose mapping, acknowledgment |
| native-controller.mjs / xinput.ps1 | Background Windows controller input |
| tracking-settings.mjs | Normalization and atomic persistence |
| dist/app.mjs | UI, scene, local/hosted input, render loop |
| dist/controls.mjs | Pose, stick mapping, deadzone, smoothing |
| dist/deformation.mjs (ghost) | Head, sliding eyes, sheet/hat springs |
| dist/ornament-physics.mjs (ghost) | Fixed-step pendulums, contacts, pom bounds |
| dist/appearance.mjs | Materials, ornament geometry, reflection probes |
| dist/pom-settings.mjs | Shared pom defaults/limits |
| tests/ | Automated input, rig, material and physics checks |
| ios/ | SwiftUI/ARKit sender |
| blender/ | Full-detail rig and export recipes |
dist/ is maintained source, not disposable output; commit it. Keep vendor notices. Do not commit data/, Xcode user state, signing products, personal device IDs, credentials, or development logs.
Additional avatar files: dist/avatar-definitions.mjs (manifest), dist/avatars/ (factories), dist/avatar-host.mjs (lifecycle), dist/avatar-ui.mjs (generated controls), avatar-settings.mjs and avatar-api.mjs (local persistence/relay).
Checks #
Run node scripts/test.mjs. It executes tests/test-*.mjs files sequentially and stops on failure. Tests use isolated settings files and an ephemeral UDP port, so they can run beside the live server. Restricted environments must permit local sockets and temporary-file renames.
Coverage includes controller mappings, malformed packets, real UDP acknowledgment, persistence, actual GLB eye/sheet/hat deformation, material/fiber restoration, and physics constraints at multiple render rates. One pom fixture uses 24° to isolate solver behavior; it is not the factory default.
Automated checks do not replace physical iPhone, GPU, or OBS testing. Inspect neutral pose, blinks, fast reversals, settled motion, and alpha output after renderer changes. Test multiple subscribers, source switching, stale input, and Release phone after networking changes. For hosted code, test ?demo=1 with no local APIs.
Limits #
The ghost adapter is character-specific. Other avatars can implement their own rig mapping. Extreme gaze can look odd. Sheet collisions are approximate planes, not fabric self-collision. Long stalls are capped and teleports reset physics. Dense geometry and reflection probes can be costly on modest/mobile GPUs. Browser gamepad behavior varies; native background input is Windows-only. The LAN protocol has no encryption or authentication.