skills/hz-iwsdk-webxr/SKILL.md
Builds WebXR experiences for Meta Quest and Horizon OS using the Immersive Web SDK (IWSDK) — ECS architecture, Three.js integration, spatial UI. Use when creating web-based VR/MR apps for Quest Browser.
npx skillsauth add meta-quest/agentic-tools hz-iwsdk-webxrInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build immersive WebXR experiences for Meta Quest using Meta's Immersive Web SDK (IWSDK). This skill covers the current package layout, ECS architecture, Three.js integration, spatial UI development, XR input handling, and the recommended Vite-based development loop.
Use this skill when you need to:
PanelUIThis skill applies to all Meta Quest headsets with Quest Browser.
The Immersive Web SDK (IWSDK) is Meta's framework for building WebXR experiences. It provides:
PanelUI, PanelDocument, and
UIKitDocument for in-world and screen-space UIAssetManagerIWSDK runs in the browser via the WebXR Device API. Applications are standard web pages that are usually served by Vite during development and opened in Quest Browser for on-device validation.
These details are important because older pre-release guidance is now wrong:
@iwsdk/corenpm create @iwsdk@latest@iwsdk/vite-plugin-devvite-plugin-mkcert>=20.19.0@iwsdk/core re-exports @iwsdk/xr-input and @iwsdk/locomotornpm create @iwsdk@latest my-project
cd my-project
If you are starting from the official create flow, it can also install dependencies and initialize git for you.
npm install
If you are setting up manually, use @iwsdk/core, three,
@iwsdk/vite-plugin-dev, and vite-plugin-mkcert instead of the old
@meta-quest/iwsdk package.
npm run dev
The standard IWSDK Vite setup gives you a secure local dev server, hot module
replacement, and an emulator/dev browser workflow through
@iwsdk/vite-plugin-dev.
There are two normal validation paths:
Quest Browser testing requires HTTPS. If the app works on desktop but will not enter XR on-device, confirm that the dev server URL is secure and headset reachable.
IWSDK is a strong fit for coding agents because the development loop is already web-native: edit source, reload the page, observe behavior, and iterate.
Recommended loop:
If you are pairing a Quest-native frontend with a host-side coding agent, keep the frontend thin. Let the host machine own the repository, file edits, dependency installs, tests, build steps, and metavr tool calls.
A typical IWSDK project looks like this:
my-project/
src/
index.ts # Entry point: World.create, scene setup, XR controls
systems/ # Optional ECS systems
movement.ts
components/ # Optional ECS components
velocity.ts
public/
models/ # GLTF / GLB assets
textures/ # Textures and images
audio/ # Audio assets
ui/ # Compiled UIKitML JSON output
ui/
welcome.uikitml # Source UIKitML files
vite.config.ts
package.json
tsconfig.json
import { Types, createComponent } from '@iwsdk/core';
export const Velocity = createComponent(
'Velocity',
{
x: { type: Types.Float32, default: 0 },
y: { type: Types.Float32, default: 0 },
z: { type: Types.Float32, default: 0 },
},
'Linear velocity in meters per second',
);
import { createSystem } from '@iwsdk/core';
import { Velocity } from './components/velocity';
export class MovementSystem extends createSystem({
moving: { required: [Velocity] },
}) {
update(delta: number) {
this.queries.moving.entities.forEach((entity) => {
if (!entity.object3D) {
return;
}
entity.object3D.position.x += Velocity.data.x[entity.index] * delta;
entity.object3D.position.y += Velocity.data.y[entity.index] * delta;
entity.object3D.position.z += Velocity.data.z[entity.index] * delta;
});
}
}
import * as THREE from 'three';
import { Velocity } from './components/velocity';
function spawnCube(world) {
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(0.5, 0.5, 0.5),
new THREE.MeshStandardMaterial({ color: 0x00aaff }),
);
const entity = world.createTransformEntity(mesh);
entity.object3D!.position.set(0, 1.5, -2);
entity.addComponent(Velocity, { x: 0, y: 0, z: 0 });
}
import {
ReferenceSpaceType,
SessionMode,
World,
} from '@iwsdk/core';
const container = document.getElementById('scene-container') as HTMLDivElement;
const world = await World.create(container, {
xr: {
sessionMode: SessionMode.ImmersiveVR,
referenceSpace: ReferenceSpaceType.LocalFloor,
offer: 'none',
},
});
world.registerSystem(MovementSystem);
world.launchXR();
World.create(...) already wires the renderer, core systems, asset loading, and
render loop. Do not teach agents to use new World(), createWorld(),
world.start(), or the older enterXR(...) path.
These are common pitfalls that cause unexpected failures or wasted debugging time when building IWSDK WebXR apps for Quest.
ngrok, a self-signed cert, or the --https flag in Vite to tunnel HTTPS during development.SharedArrayBuffer, certain WebGL2 extensions, and OffscreenCanvas may behave differently or be unavailable. Always test on actual Quest Browser, not just desktop Chrome with the IWER emulator.xrSession.updateTargetFrameRate(90) after session start. Forgetting this is the most common reason a WebXR app feels "sluggish" compared to a native build.requestAnimationFrame vs. XR frame loop -- Once an XR session starts, you must use xrSession.requestAnimationFrame, not window.requestAnimationFrame. Using the wrong one causes the scene to freeze or render at the wrong rate.World.create(...), world.launchXR(), and world.exitXR() as the
runtime control surface@iwsdk/vite-plugin-dev and Quest Browser validation, then layer
in emulator/dev browser workflows for faster iterationtools
Provides the complete metavr (Meta VR CLI) reference for Meta Quest and Horizon OS development — installation, device setup, command discovery, MCP server mode, documentation search, app deployment, device testing setup, audio control, screenshots, and performance analysis. Use when the user needs to install metavr, asks what commands are available, needs CLI syntax help, or wants to know what metavr can do.
development
Guides integration of the Horizon Platform SDK for Meta Quest and Horizon OS Unity/C# apps — achievements, IAP, users, leaderboards, challenges, presence, notifications, abuse reporting, entitlements, asset files, application lifecycle, consent, device integrity, language packs, user age categories, and rate and review. Covers setup, initialization, API usage, data types, error handling, and best practices for all 18 public platform SDK packages.
development
Meta XR Core SDK (com.meta.xr.sdk.core) for Unity XR development. Use when setting up VR/MR projects, configuring OVRManager, adding OVRCameraRig, enabling passthrough, hand tracking, spatial anchors, boundaryless mode, controller input, Scene API, or any Meta Quest XR feature. Covers OVRProjectSetup, AndroidManifest generation, and project configuration for Meta Quest headsets.
development
Build and sideload Android apps for Meta Portal devices (Portal, Portal+, Portal Mini, Portal Go, Portal TV) using metavr. Use when targeting Portal hardware — covers ADB enablement, the no-GMS constraint, manifest/launcher intent-filter requirements, icon density quirks (PNG-only, mipmap-xxxhdpi), the Smart Camera SDK, and the gradle + `metavr adb` build/deploy/debug loop. Auto-load when the user mentions "Portal" device, targets `minSdkVersion` 28-29 for a tabletop/TV form factor, or works with the `com.facebook.portal` package.