# Deploying on Meta Quest 3 (WebXR)

## 1. Host the files
**One-click pilot host:** `deploy/start-windows.bat` or `deploy/start.sh` (Node ≥ 18) — vendors libraries for offline use, creates a LAN certificate and serves HTTPS on :8443. Full step-by-step for the developer: **`docs/QUEST3_TEST_GUIDE.md`**.

For production copy the project folder to any HTTPS web server on the academy network (nginx/IIS/Caddy). WebXR requires **HTTPS** (a self-signed or internal-CA certificate works if installed on the headsets). Keep the folder structure; no build step.

Required MIME types: `.js → text/javascript`, `.glb → model/gltf-binary`, `.json → application/json`, `.png → image/png`, `.wasm → application/wasm`, `.woff2 → font/woff2`.
Libraries: three.js `0.184.0`, PeerJS, React (portal) are loaded from `vendor/` (created by `deploy/setup.mjs`); PeerJS falls back to the CDN if the vendored copy is missing.

## 2. Open on the headset
Quest 3 → **Meta Quest Browser** → `https://<server>/Academy%20Portal.dc.html` → sign in → join a session → **Enter session** → **Enter MR (passthrough)**.
Grant hand tracking when prompted (Settings → Movement tracking → Hand & body tracking on).

## 3. Colocation
Print `xr/marker.png` at **20 × 20 cm** and fix it on the bench (arrow toward the back). Each participant presses **Set room origin** in the HUD, touches the marker centre and pinches, then touches the arrow tip and pinches. Where the browser exposes WebXR image tracking (Chrome Android; Quest when enabled), alignment happens automatically when the marker is in view.

## 4. Multiplayer
* **Same-device demo**: open two browser tabs (instructor + trainee) — sync via BroadcastChannel.
* **Headsets on LAN**: create the session with *WebRTC P2P*. Signaling defaults to the public PeerJS broker for pilots; for on-prem run `npx peer --port 9000 --path /jda` behind HTTPS and set on each device (portal Settings or dev console):
  `localStorage.setItem('jda.peer.opts', JSON.stringify({ host: 'lms.academy.local', port: 9000, path: '/jda', secure: true }))`.
  Media/data stays peer-to-peer on the LAN; add a coturn TURN server only if headsets sit on different VLANs.

## 5. Performance budget (Quest 3 browser)
Scenario assets ≤ 150k triangles total, ≤ 8 materials, textures ≤ 2048² PoT, GLB with embedded textures (see `HU60 CG trader/REPORT.md` pipeline). Scenario 02 ships the Quest-optimised engine (`Engine_Animated_Quest.glb`, 67k tris, 4 MB) plus its cutaway (45k) for x-ray. The effects layer (`xr/fx.js`) is budgeted for the headset: ≤ 560 particles as GPU points, one environment map (RoomEnvironment PMREM), one spotlight + one point light, no shadow maps, no post-processing, canvas-textured UI. Target 72–90 fps.

## 5a. Hands-first interaction (Learn → Do)
Designed for Quest 3 hand tracking: pinch to grab, index-finger poke for controls and tablet buttons, gaze-dwell to inspect, wrist rotation while holding the wrench to turn the B-nut (ratchet haptics need controllers — hands get visual/subtitle feedback only). Controllers work everywhere as a fallback (trigger = pinch, grip = grab).

### Fluid budget
The fuel stream is a two-pass metaball fluid: a depth-only pre-pass of the occluders (meshes on layer 3) + additive blob accumulation into a half-float render target the size of the XR framebuffer, then one full-screen composite per eye. Plus a 256² floor-film map updated on the CPU at ~12 Hz. On Quest 3 keep `FluidParticles` max ≤ 1600 and the film map at 256²; if frame time exceeds budget, first drop the occluder pre-pass to the engine meshes only (layer 3 assignment in `FX.markOccluders`). Target ≤ 2 ms for fluid + film combined.

## 6. Browser feature matrix used
`immersive-ar` + `local-floor` (required) · `hand-tracking`, `hit-test`, `anchors`, `image-tracking` (optional, feature-detected) · `immersive-vr` fallback · desktop 3D fallback with mouse.
