Develop

Spatial UI Overview

Updated: Sep 4, 2026
IWSDK spatial UI combines a Three.js UI runtime with HTML- and CSS-like authoring. Panels remain part of the 3D scene, receive pointer events, and can be placed in world space or as a browser overlay.

Stack overview

  • UIKit provides Three.js UI components, Yoga layout, MSDF text, and batched rendering.
  • UIKitML is a strict source format parsed by @drawcall/uikitml in the browser.
  • UIKitMLAsset is the placeable Three.js object returned by the asset manager.
  • UIKitDocument exposes element lookup and lifecycle helpers.
  • ScreenSpace positions a document relative to the browser camera outside XR.
  • Follower uses movement thresholds and smoothing for compact in-XR UI.
public/ui/menu.uikitml
        ↓ fetch and parse
UIKit component tree
        ↓ wrap
UIKitMLAsset + UIKitDocument
        ↓ place
World transform, ScreenSpace, or Follower

Runtime source workflow

UIKitML remains a source asset from development through deployment. No UIKitML build plugin or generated JSON counterpart is required.
const assets = {
  menu: {
    type: AssetType.UIKitML,
    url: '/ui/menu.uikitml',
  },
} satisfies AssetManifest;

const world = await World.create(container, {
  assets,
  features: { spatialUI: true },
});

const menu = await world.assets.instantiate<UIKitMLAsset>('menu');
const entity = world.createTransformEntity(menu);
See the complete spatial UI flow.

Author UIKitML

UIKitML supports HTML-like elements, Horizon components, and Lucide icons through the default component sets. Names are case-sensitive, and unsupported tags or properties produce parser errors.
<Panel class="menu">
  <h1>Settings</h1>
  <button id="save-button">
    <ButtonIcon><Settings /></ButtonIcon>
    Save
  </button>
</Panel>
Style markup with kebab-case CSS properties and supported selectors or states.

Choose a placement model

NeedMechanism
Panel belongs to a place or object
Authored world transform or object parent
Browser viewport overlay
ScreenSpace
Compact in-XR UI that follows after a threshold
Follower
Tiny transient marker with exact view alignment
Parent to world.playerHeadEntity
World-space placement is the default for normal XR panels. Read HUD placement before adding viewer-following or head-attached UI.

Access controls

Use the typed asset to retrieve required elements.
const menu = world.requireSceneObject<UIKitMLAsset>('settings-panel');
const saveButton = menu.requireElementById('save-button');

saveButton.addEventListener('click', saveSettings);
The panel’s owning entity must have RayInteractable for browser-pointer and XR-ray events, PokeInteractable for touch events, or both. These interaction tags are required for IWSDK’s pointer stack to dispatch the corresponding UI events.
Keep application state in components or application services. Use UI events to invoke behavior instead of placing game logic inside visual update callbacks.

Learn each layer