The browser API that hands your code a position in the real room, sixty to ninety times a second.
WEBXR DEVICE APIWebXR is the browser API that replaced WebVR, and its core job is exactly one thing: give your code a POSE every single frame — where the headset or phone is, expressed in a coordinate system the real room agrees with. Everything else you see in a browser-based AR demo is built on top of that one guarantee.
The most common misreading is that WebXR draws things. It does not. It is a device API, not a renderer. WebXR hands you matrices; WebGL or Three.js still has to turn those matrices into pixels.
You request a session and declare which mode you want. VR replaces the world; AR composites over the camera feed of the real one.
This defines what the origin MEANS: the device itself, wherever it started, the floor beneath it, or a room outline you may actually walk around in.
Every frame you ask the session for the current pose and draw from it. Miss a frame and the world lags behind the head that moved.
How a virtual object lands on your actual table: cast a ray from the screen, and the browser returns where it met a real surface it detected.
HTTPS and wait for a real user gesture — pose data is effectively a room scan, so the browser refuses to start one on page load.navigator.xr.requestSession('immersive-ar'). If the browser cannot do that mode, you find out here, not later.local-floor if objects should sit on the ground; bounded-floor if the user will walk.XRFrame; ask it for the viewer pose in your reference space.This is a hard real-time budget with a physiological penalty. At 90Hz you have about 11 milliseconds to produce two eyes' worth of image. Blowing that budget does not merely look janky the way a slow web page does — the mismatch between what the inner ear reports and what the eyes see makes people nauseated within minutes. A dropped frame here costs you the user's body, not just their patience.
immersive-vr straight from a browser tab.Support is genuinely uneven. iOS Safari still does not ship immersive-ar — so a WebXR AR demo that works on an Android phone can be simply unavailable on an iPhone, and no amount of polyfilling gives you real surface detection there.
Always feature-detect with navigator.xr.isSessionSupported() before you promise the user a button, and design a non-XR path that is a real experience rather than an apology.
local-floor instead of local changes where a virtual object appears — and when bounded-floor is the only correct choice.
Hint: the reference space defines what the origin means, not how the object is drawn.
Take any WebXR scene you can run and cap your frame budget at 8 milliseconds — deliberately tighter than 11. Then see what you are forced to cut: shadow quality, polygon count, post-processing, physics steps. The list of things you sacrifice at 8ms is the honest specification of what your experience can contain.