Use when adding or modifying WebXR, AR placement, VR immersion, headset controller input, or XR rendering modes in Tiny World Builder.
69
83%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Tiny World uses a pinned global THREE r185 compatibility bundle (vendor/three/tinyworld-three.r185.min.js), not runtime module imports or ARButton/VRButton addons. Keep WebXR integration vanilla and single-file inside tiny-world-builder.html.
Platform split — WebXR covers "Google" AR (Android Chrome / Quest, via immersive-ar + hit-test), but Apple devices have no WebXR. iOS/iPadOS web AR is AR Quick Look only: an <a rel="ar"> pointing at a .usdz opens the system viewer, which finds a surface, places the model, and lets the user walk around it. So both paths must exist for full coverage.
Patterns:
For Apple AR, export the live world to USDZ on demand with THREE.USDZExporter from the r185 global bundle. USDZExporter only understands MeshStandardMaterial, so snapshot worldGroup into a fresh group, convert each Lambert/Basic/Shader material to a Standard equivalent (preserving colour/emissive/map), recentre on the origin with the base at y=0, and scale to a tabletop size. Wrap the resulting Uint8Array in a model/vnd.usdz+zip Blob → object URL, and launch via an <a rel="ar"> that contains a single <img> child (Safari's requirement) clicked programmatically.
Gate the Apple AR button on document.createElement('a').relList.supports('ar'); gate the WebXR buttons on navigator.xr support. Show the XR panel if either is available so iOS users see just the Apple AR button.
Enable WebXR with renderer.xr.enabled = true and drive the main loop with renderer.setAnimationLoop(animate) so desktop and headset frames share one path.
Keep headset transforms on xrWorldRoot, a scene-level parent for board/runtime meshes. Do not scale/move worldGroup alone; hover, selection, clouds, weather, smoke, crop duster, and previews must stay in the same local world space.
Keep controllers/reticles in scene, not xrWorldRoot; they are physical XR-space objects.
For AR desk mode, request immersive-ar with required hit-test, optional anchors, and a domOverlay root. Use the reticle pose to set xrWorldRoot and use anchors when available, but gracefully fall back to the last hit-test pose.
For floating mode, prefer immersive-ar, then fall back to immersive-vr; place the mini board in front of the current XR camera.
For inside mode, use immersive-vr with local-floor and leave xrWorldRoot at meter scale (scale = 1) so one tile is walkable room scale.
When picking tiles from controllers, raycast against worldGroup.children, then convert h.point through xrWorldRoot.worldToLocal() before deriving tile-local offsets. Desktop pointer picking can keep using screen-space raycasts.
Restore scene.background, xrWorldRoot transform/visibility, reticle state, and UI state on XR session end or failure.
Validation:
npm test and the inline script node --check must pass.f21f84b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.