Getting Started with WebXR

Updated June 2026
This guide walks you through setting up a WebXR development environment, building your first VR scene, handling controller input, testing on real hardware, and deploying your game to the web. By the end, you will have a working VR experience that anyone can access through a URL.

Getting a WebXR project running involves a few setup decisions that are different from typical web development. The most important one is that WebXR requires HTTPS, even during local development. The browser will not expose the navigator.xr API on an insecure connection, so you need to handle certificates before writing any XR code. Beyond that, the workflow is familiar: pick a framework, set up a project, write code, test, and deploy.

Step 1: Set Up Your Development Environment

Start by installing Node.js (version 18 or later) if you do not already have it. You will need it to run a local development server and manage dependencies. Choose a WebXR framework based on your needs. For this guide, we will reference both Babylon.js and Three.js patterns, since they are the two most popular choices for WebXR game development.

For a Babylon.js project, create a new directory, initialize it with npm init, and install the Babylon.js packages: @babylonjs/core, @babylonjs/loaders, and @babylonjs/materials. You will also want a bundler like Vite or Webpack. Vite is the simpler choice for new projects, and it generates self-signed HTTPS certificates automatically when you run it with the --https flag.

For a Three.js project, the setup is similar. Install three via npm, set up Vite as your dev server, and enable HTTPS. Three.js includes its WebXR helpers in the main package, so there are no additional XR-specific packages to install.

If you do not want to use a bundler, you can load Babylon.js or Three.js from a CDN via script tags and serve your HTML file from any HTTPS server. This is a valid approach for prototyping, though production projects benefit from bundling for tree-shaking and dependency management.

Install the WebXR Emulator browser extension for Chrome. This extension simulates a VR headset and controllers in your desktop browser, letting you test WebXR code without wearing a headset. It adds a panel to DevTools where you can move the virtual headset and controllers, press virtual buttons, and trigger input events. This is essential for rapid iteration during development.

Step 2: Create Your First VR Scene

A minimal WebXR scene needs four things: a 3D rendering context, some geometry to look at, a light source, and a way to enter VR mode. The frameworks handle the boilerplate differently, but the concepts are the same.

In Babylon.js, you create an Engine, a Scene, and a Camera. Add a ground plane with CreateGround, a few box or sphere meshes to serve as objects, and a HemisphericLight for ambient illumination. Then call scene.createDefaultXRExperienceAsync() and Babylon.js sets up everything: the VR session, the "Enter VR" button overlay, controller models, teleportation, and the stereoscopic render loop. This single method call is why many developers prefer Babylon.js for WebXR projects.

In Three.js, you create a WebGLRenderer, a Scene, and a PerspectiveCamera. Add geometry using BoxGeometry or SphereGeometry with MeshStandardMaterial, and add a DirectionalLight. To enable WebXR, set renderer.xr.enabled = true, then add the VRButton.createButton(renderer) element to your page. The VRButton handles session creation, and your render loop uses renderer.setAnimationLoop() instead of requestAnimationFrame() so that Three.js can hook into the XR frame callback.

In both cases, the framework provides a visible "Enter VR" button that the player clicks to start the immersive session. The browser then prompts for permission, transitions to VR mode, and begins calling your render function at the headset's refresh rate. When the player exits VR (by pressing the headset's menu button or removing the headset), the session ends and the page returns to its normal state.

Start with simple geometry, not loaded models. Boxes, spheres, and planes render instantly and let you verify that your VR session, tracking, and rendering pipeline work correctly before introducing the complexity of asset loading.

Step 3: Add Controller Input

Once you can see your scene in VR, the next step is letting the player interact with it. WebXR reports connected input devices through the XRSession's inputsources array, and both frameworks provide abstractions for working with them.

In Babylon.js, the default XR experience automatically loads 3D controller models, sets up ray pointers from each controller, and enables teleportation on the ground mesh. You can listen for trigger presses, grip squeezes, and thumbstick movements through the WebXR input source's motionController property. To make objects interactive, add action managers or pointer observables to your meshes.

In Three.js, you get controller references from renderer.xr.getController(0) and renderer.xr.getController(1). These are Object3D instances that track the controller positions. You add event listeners for "selectstart", "selectend", "squeezestart", and "squeezeend" events. For visual feedback, add a line geometry to each controller to show the pointing ray, and use raycasting to detect intersections with scene objects.

The most important controller events for game interaction are the trigger (select event), which functions like a primary click, and the grip (squeeze event), which functions like a secondary action. Thumbstick input comes through the gamepad API attached to each input source, providing x and y axis values for movement controls.

Test your input handling with the WebXR Emulator first. The emulator lets you trigger select and squeeze events from the keyboard, which is much faster than putting on a headset every time you change your input code.

Step 4: Test on Desktop and Headset

Desktop testing with the WebXR Emulator catches most logic errors, but you must test on a real headset before considering your game ready. The emulator cannot replicate the actual performance characteristics, display resolution, controller ergonomics, or physical comfort of wearing a headset.

To test on a Meta Quest, connect the headset to your development machine via USB and enable developer mode in the Oculus app. Use ADB port forwarding to make your localhost server accessible from the headset: run "adb reverse tcp:5173 tcp:5173" (adjusting the port to match your dev server). Then open the Quest Browser and navigate to https://localhost:5173. Alternatively, find your development machine's local IP address and navigate to https://192.168.x.x:5173 directly, though you may need to accept a certificate warning.

To test on a PC-tethered headset, just open Chrome on your desktop with SteamVR running. Navigate to your local dev server, click Enter VR, and the headset takes over. This is the simplest testing setup since everything runs on one machine.

During headset testing, pay attention to frame rate stability (any drops will be obvious as visual stuttering or discomfort), text readability (text that looks fine on a monitor may be too small in VR), interaction distances (objects should be within comfortable reaching range), and audio spatialization if you have any sounds. Take notes while in the headset, because the issues you notice while immersed are often different from what you catch on a flat screen.

Step 5: Deploy to the Web

Deploying a WebXR game is the same as deploying any static website. Run your build command (vite build, webpack, or your bundler's equivalent) to produce optimized output files. Upload these files to any web server or static hosting service that supports HTTPS. Services like Cloudflare Pages, Netlify, Vercel, GitHub Pages, and AWS S3 with CloudFront all work well.

Configure your server to set appropriate cache headers. JavaScript and CSS files with content hashes in their names should have long cache durations (max-age=31536000). Your index.html should have a short cache or no-cache directive so updates are picked up immediately. 3D model files (glTF, textures) should be cached aggressively since they are typically the largest assets.

Ensure your server sends the correct MIME types for 3D assets. glTF files should be served as model/gltf+json, GLB files as model/gltf-binary, and texture files as their appropriate image types. Incorrect MIME types can cause loading failures in some browsers.

Once deployed, share the URL. That is the entire distribution story for WebXR: no app store submission, no platform approval, no install. The player clicks the link, the game loads, they click Enter VR, and they are playing. Updates are instantaneous since you just upload new files, and every player gets the latest version on their next visit.

Key Takeaway

Getting started with WebXR requires HTTPS for local development, a framework like Babylon.js or Three.js for scene management, and the WebXR Emulator extension for rapid desktop testing. Start with simple geometry, add controller input, test on a real headset, and deploy to any HTTPS web host. The entire workflow from first line of code to live VR game runs through standard web tooling.