hz-iwsdk-webxr — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited hz-iwsdk-webxr (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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:
PanelUIBrowser
This 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:
typed component storage and query-driven systems
session lifecycle so app code can focus on content
PanelUI, PanelDocument, andUIKitDocument for in-world and screen-space UI
pointers, and grabbing
turning features
AssetManager
IWSDK 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-projectIf you are starting from the official create flow, it can also install dependencies and initialize git for you.
npm installIf 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 devThe 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:
quick desktop iteration
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.jsonimport { 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.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 theruntime control surface
secure contexts
@iwsdk/vite-plugin-dev and Quest Browser validation, then layerin emulator/dev browser workflows for faster iteration
recently
capture all input, comfort, and performance issues
hardware
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.