agentleFS
mirzaaghazadehmirzaaghazadeh/iwsdk-webxr-skills/skills/custom/quest-browser-webxr/SKILL.md

quest-browser-webxr

Skill1 starsChanged 30 days agoMITView on GitHub

What Meta Quest Browser supports for WebXR and how to use it: a sourced feature matrix with a Meta VR Glasses column (immersive-vr, immersive-ar passthrough, hand-tracking, gaze-tracking, hit-test, anchors, plane and mesh detection, depth sensing, layers, fixed foveation, framebuffer scale, frame rate control, multiview, Space Warp, system keyboard, Touch Pro), session init options, focus and visibility handling, gaze rules for 2D pages, headset testing (adb reverse, chrome://inspect, MQDH, IWER, OVR Metrics, ovrgpuprofiler, RenderDoc, metavr fov-sim) and performance budgets for Quest 2/3/3S and VR Glasses. Use when the user asks "does Quest Browser support X", "does it work on Meta VR Glasses", "how do I request passthrough / hand tracking / plane detection / eye gaze", "set 90 Hz in WebXR", "enable foveation", "my WebXR app stutters on Quest", "debug WebXR on the headset", "Enter VR button missing", or before choosing WebXR features for an IWSDK app.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Before that: 42.x (Feb 2026).

    line 49
  2. Very specific:

    Put everything optional in optionalFeatures.

    line 102
  3. Very specific:

    Gaze without IWSDK: after the session starts, look in session.inputSources (and inputsourceschange) for a source with targetRayMode === …

    line 103
  4. Very specific:

    No headset: IWER inside the IWSDK dev server, or the Immersive Web Emulator extension for Chrome/Edge.

    line 162
  5. Distinctive:

    CPU or GPU bound?: Stop rendering: no change means CPU bound.

    line 189
  6. Distinctive:

    Meta VR Glasses: no WebXR or draw-call budget published.

    line 202

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Quest Browser WebXR: features, session setup, testing, performance

Made by Navid Mirzaaghazadeh · part of iwsdk-webxr-skills · MIT

This is the browser layer under IWSDK, for any WebXR stack (IWSDK, three.js, A-Frame, Babylon, raw WebGL). Hand-offs in this library: IWSDK APIs and feature flags hz-iwsdk-webxr and iwsdk-project-setup; step-by-step headset testing of an IWSDK app iwsdk-quest-device-testing; IWSDK-specific tuning (its renderer defaults, multiview already on) iwsdk-performance; packaging horizon-web-store-publish. Per-feature detail and caveats: references/feature-matrix.md. Profiling recipes: references/performance.md.

Meta's per-feature WebXR pages are mostly undated and older than its 2026-07 web-docs rewrite (the mixed reality page still names only Quest 2 and Quest Pro), and none mentions Meta VR Glasses (checked 2026-10-17). Treat device lists as lower bounds, detect features at runtime, and confirm anything critical with metavr docs search "<feature> webxr" and a headset test. Building for VR Glasses (gaze + pinch, no controllers, 70° × 66° view): load iwsdk-vr-glasses; device facts with sources: docs/meta-reference/web-vr-glasses.md.

Know the browser

  • Chromium-based. Since March 2026 Browser versions follow Chromium milestones: 144 (2026-03-02), 146.0 (2026-04-21, Chromium 146), 149.1, 150.1, 152.1 (2026-10-02) (Browser release notes). Before that: 42.x (Feb 2026).
  • User agent tokens: Quest 2, Quest Pro, Quest 3; Quest 3S reports Quest 3; no token is documented for VR Glasses. Meta says use feature detection, not the UA (browser-specs, 2026-07-21).
  • 2D windows: default 1280 × 670, min 500 × 495, max 2000 × 1070 CSS px; desktop browsing mode by default (viewport meta ignored) (browser-specs). Window sizes on VR Glasses: unverified.
  • Gaze in 2D pages: looking fires no :hover or pointer events (the system draws hover), so no flow may depend on hover; use <button> / <a href> or focusable ARIA roles (a click-only <div> may not be targetable). Targets 56 × 56 CSS px or larger (eyes-best-practices, 2026-10-13; the older 2d-web page, 2026-09-04, still says 48 × 48).
  • WebXR needs a secure context: HTTPS, or localhost through adb reverse.

Feature matrix (summary)

"Glasses" = Meta VR Glasses. No Meta web page covers the device yet, so that column is device specs plus IWSDK's guidance; "unverified" there means "detect at runtime and test when the hardware ships (spring 2027)".

FeatureRequest it withStatus on Quest BrowserGlassesMeta source
VR sessionrequestSession('immersive-vr')SupportedMeta's IWSDK glasses guide uses VR modewebxr-overview; IWSDK get-started-glasses
Passthrough AR'immersive-ar'; clear to transparentSupported (page: Quest 2 grey, Pro colour; Quest 3/3S not listed but IWSDK MR targets them)Device has colour stereo passthrough with depth; WebXR AR unverifiedwebxr-mixed-reality; compare-devices
Hand trackingoptional feature 'hand-tracking'Supported; palm pinch reserved for the systemPrimary input: pinch selectswebxr-hands; bring-your-app-glasses
Eye gazeoptional 'gaze-tracking' (IWSDK also offers the W3C draft 'eye-tracking') → an XRInputSource with targetRayMode === 'gaze'No eye tracking on Quest 3/3S (Quest Pro has the hardware; Browser support unverified)Primary targeting; IWSDK 1.0+ gazeTrackingIWSDK 1.0.1 init/xr.js; horizon-os-input
Hit test'hit-test'Supported; no room scan neededUnverifiedIWSDK ch. 14
Anchors, persistent'anchors'; requestPersistentHandle() / restorePersistentAnchor()Supported; 8 persistent per site; none in private modeUnverifiedwebxr-mixed-reality
Plane detection'plane-detection'; frame.detectedPlanesSupported; needs Space Setup; initiateRoomCapture() once per sessionUnverifiedwebxr-mixed-reality
Mesh detection'mesh-detection'Used by IWSDK scene understanding; device support unverifiedUnverifiedIWSDK ch. 11
Depth sensing'depth-sensing' + usage/format preferencesUsed by IWSDK depth occlusion; Browser 146.0 added experimental depth projection; device list unverifiedDevice has depth sensing; WebXR unverifiedIWSDK ch. 15; release notes; compare-devices
Layers'layers'; XRWebGLBinding, XRMediaBindingSupported (quad, cylinder, equirect, cube, projection, media)Unverified; metavr device fov-sim clips layers only on Horizon OS v209+webxr-layers; field-of-view
Fixed foveation'low'/'medium'/'high-fixed-foveation-level' or XRWebGLLayer.fixedFoveation 0-1SupportedDevice supports FFR and ETFR natively; no public ETFR route for webwebxr-ffr; fixed-foveated-rendering
Frame ratesession.supportedFrameRates, updateTargetFrameRate()Browser 16.4+Display up to 120 Hz; IWER's profile lists 72/90/96/100/120 (emulator data)webxr-frames; compare-devices
MultiviewWebGL2 OCULUS_multiview (OVR_multiview2 behind a flag)Supported, "experimental" labelUnverifiedweb-multiview
Space Warp'layers' + 'space-warp'Draft spec; Browser 24.2+ and chrome://flags only: not usable for Store usersSame caveatwebxr-space-warp
System keyboardfocus an HTML <input>; session.isSystemKeyboardSupportedBrowser 26.1+Unverifiedwebxr-keyboard
Touch Pro controllersprofile meta-quest-touch-pro (fallback oculus-touch-v2)12 gamepad buttons incl. stylus, finger curlTouch Plus only, sold separately; don't assume controllerswebxr-pro-controller; compare-devices
Camera accessMediaDevices (getUserMedia)IWSDK CameraSource; which cameras Browser exposes is unverifiedUnverifiedIWSDK ch. 13
DOM overlay, WebGPU XRn/aNot documented by Meta for Quest WebXR; release notes list experimental WebGPU layers, foveation and Space Warp layers (149.1-152.1)Samerelease notes

Session setup (raw WebXR; IWSDK wraps this)

const mode = 'immersive-vr';                       // or 'immersive-ar' for passthrough
if (!(await navigator.xr?.isSessionSupported(mode))) return showNoXrMessage();
const session = await navigator.xr.requestSession(mode, {
  requiredFeatures: ['local-floor'],
  optionalFeatures: ['hand-tracking', 'layers', 'medium-fixed-foveation-level'],
  // AR extras: 'hit-test', 'anchors', 'plane-detection', 'mesh-detection',
  // 'depth-sensing' with depthSensing: { usagePreference: ['gpu-optimized'], dataFormatPreference: ['float32'] }
  // Eye gaze (VR Glasses): 'gaze-tracking' and 'eye-tracking', always optional
});
  • Put everything optional in optionalFeatures; a missing required feature rejects the session.
  • Gaze without IWSDK: after the session starts, look in session.inputSources (and inputsourceschange) for a source with targetRayMode === 'gaze', cast from its targetRaySpace, and take selection from the hands' select events. That split (gaze aims, pinch commits) is how IWSDK 1.0.1 and IWER model it; whether Browser's gaze source fires select itself is unverified. Keep hand and controller rays working when no gaze source appears (Quest 3/3S). Meta has no web guide that combines gaze and pinch outside IWSDK (bring-your-app-glasses), so test on hardware.
  • requestSession needs a user activation in a tab. In an installed immersive PWA the icon tap counts, so call it on load there only (gate on window.getDigitalGoodsService; see horizon-web-store-publish).
  • Frame rate, after the session starts:
    const rates = session.supportedFrameRates;            // e.g. Float32Array; undefined if unsupported
    if (rates?.includes(90)) await session.updateTargetFrameRate(90);
    console.log('nominal rate', session.frameRate);
    Meta: default is 90 fps on Quest 2 and 72 on "Meta Quest headsets" (an undated page that predates Quest 3; read session.frameRate rather than assuming). VRC Performance.1 allows 72, 80, 90, 96, 100 or 120 Hz (96/100/120 not on all devices) with ≥ 60 fps rendered.
  • Render scale: XRWebGLLayer init framebufferScaleFactor, or three.js renderer.xr.setFramebufferScaleFactor(x) before the session starts (webxr-perf-workflow). Stay ≥ 0.85 for most of the experience (VRC Performance.4, Recommended).
  • Foveation at runtime: session.renderState.baseLayer.fixedFoveation = 0.0-1.0 (three.js: renderer.xr.setFoveation(x)). FFR only applies when rendering straight to the eye buffer: post-processing into an intermediate target, or switching render targets mid-frame, cancels it (and MSAA) (webxr-ffr).

Lifecycle and input focus (VRC Functional.2, Input.4)

XRSession.visibilityState (WebXR spec):

StateRenderingInputWhat to do
visiblenormal rateprocessednormal
visible-blurredmay be throttlednot processedkeep rendering, hide or rest hands and controllers, pause single-player gameplay (Universal Menu is open)
hiddenrAF callbacks stopnot processedpause; save state

Listen on session.addEventListener('visibilitychange', ...); in 2D pages use document.visibilitychange. IWSDK exposes world.visibilityState (hz-new-project-creation web reference). Also handle inputsourceschange (hands ↔ controllers, Input.7) and the reference space reset event (recenter, Functional.9). Hand pinch arrives as select events. Left palm pinch, like the left menu button, "takes the user out of the WebXR session" (webxr-hands), so don't rely on the left menu button for an in-app menu.

Test on a headset

metavr device list                                   # developer mode + USB, see hz-quest-verify-first
metavr adb reverse tcp:8081 tcp:8081                 # headset localhost:8081 -> dev machine
metavr device browser https://localhost:8081         # open it in Browser (IWSDK prints its port)
# DevTools: desktop Chrome -> chrome://inspect/#devices -> inspect the tab
metavr log --level E                                 # device log; hz-vr-debug has filtering recipes
  • Same-network alternative: open https://<LAN-IP>:<port> and accept the local certificate. Corporate networks often block it; use adb reverse or Chrome's port forwarding in chrome://inspect. Full IWSDK walkthrough (certificates, reading the live session's frame rate and features, what only the headset proves): iwsdk-quest-device-testing.
  • Installed PWA instead of a tab: chrome://inspect lists its tab once it runs (pwa-webxr FAQ).
  • No headset: IWER inside the IWSDK dev server, or the Immersive Web Emulator extension for Chrome/Edge; Spector.js works only on desktop (webxr-workflow). Emulators miss performance, comfort and some input; always finish on hardware.
  • VR Glasses before the hardware exists: IWER's metaVRGlasses profile (gaze + hands, view mask; IWER 2.5.0+), and on a Quest 3/3S/Pro metavr device fov-sim enable (70° × 66°; --perceived 58° × 54°; disable afterwards; ask first) (field-of-view, 2026-09-25). Walkthrough: iwsdk-vr-glasses §7.
  • MQDH: ADB over Wi-Fi ("preferred" for Browser debugging), casting, screenshots, and Device Manager > Browser to send a URL (browser-mqdh).
  • Meta's samples: immersive-web.github.io/webxr-samples (bare API, layers, hands, AR); Meta's sample pages: Project Flowerbed, Flap Frenzy, Chairs Etc., RealMeasure, Sneaker Builder, WebXR First Steps (React). Start new projects with npm create @iwsdk@latest.

Performance: budgets and knobs

Frame budgets: 60 fps = 16.6 ms, 72 = 13.7 ms, 90 = 11.1 ms (webxr-perf-workflow). Meta gives no WebXR-specific draw-call or triangle budgets. Use the native targets as an upper bound and expect less: Quest 3 < 200 draw calls and < 1.5M triangles, Quest 2 < 100 and < 750K (device-optimization-comparison, 2026-05-11). Browser adds "a small amount of additional overhead" (webxr-perf-bp), and 1,000 single-triangle draw calls "would likely" drop below 72 fps (webxr-perf-workflow).

Work in this order (details in performance.md; for IWSDK's own renderer settings and feature-flag costs use iwsdk-performance):

  1. Measure on device: OVR Metrics Tool HUD; CPU frame time via chrome://inspect > trace with the xr.debug category; GPU via ovrgpuprofiler; RenderDoc Meta Fork for draw order.
  2. CPU or GPU bound? Stop rendering: no change means CPU bound. GPU bound: set render scale to 0.01; faster means fragment bound, unchanged means vertex bound.
  3. CPU: merge meshes, instancing, multiview (Meta: CPU-bound apps often save 25-50% CPU), fewer state changes, stagger updates across frames; optimize any app logic that takes over 2 ms.
  4. Fragment: front-to-back opaque order (fix sky domes), fewer lights and shadows, cheaper materials off hero objects, KTX2/Basis (or ETC/ASTC) textures, FFR, layers for static backgrounds, video and text, clear to black or white, render scale 0.8-0.9 only as a last resort.
  5. Vertex: LODs, simpler meshes, split big meshes for culling, cull instanced meshes.

Space Warp needs a chrome://flags switch, so Store users won't have it; don't plan a game's budget around it.

Meta VR Glasses: no WebXR or draw-call budget published. Device facts: up to 120 Hz; render scale 1.0 = 1728 × 1760 per eye (Quest 3: 1680 × 1760); steady-state CPU/GPU level 4, no GPU level 5; app memory limit 5.75 GiB PSS like Quest 3/3S; battery saver forces 72 Hz (render-scale 2026-09-01, cpu-gpu-levels 2026-09-11, memory-ram 2026-08-31, battery-saver-mode 2026-04-08). How Browser maps these to WebXR is unverified; start from the Quest 3 numbers and measure.

Sources

Last verified: 2026-10-17

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.