Develop

Sneaker Builder sample overview

Updated: May 10, 2026

Overview

This sample demonstrates interactive 3D product customization in mixed reality using WebXR, Three.js, and an Entity-Component-System (ECS) architecture. Sneaker Builder lets users grab, scale, and customize a sneaker model by selecting parts and colors through spatial UI panels, showcasing patterns for hand-tracked interaction, spatial audio feedback, and real-time material updates in a WebXR application.

What you will learn

  • Implement grab-and-hold interactions using proximity-based bounding box checks and controller re-parenting
  • Build a spatial product configurator with multi-part selection and material swapping
  • Structure a WebXR application using the elics ECS framework with components and systems
  • Create follow-behavior UI panels that track objects and the user’s head in 3D space
  • Integrate spatial audio feedback and haptic pulses for interaction confirmation

Requirements

  • Meta Quest headset with passthrough support
  • Development environment with Node.js and npm
For dependency installation and build instructions, see the sample README.

Get started

Clone the webxr-showcases repository and navigate to the sneaker-builder directory. After installing dependencies and starting the development server (see the sample README for setup details), open the local URL in your Quest browser. When you enter the WebXR session via the “Customize in MR” button, the sneaker appears in your space ready for customization.

Explore the sample

FileWhat it demonstratesKey concepts
ECS architecture setup and system registration
Component and system registration order, BVH raycasting acceleration
Proximity-based grab interaction with controllers
Bounding box checks in local space, attach() for world-transform-preserving re-parenting
Multi-part product model with material swapping
12 customizable parts, primary/secondary/stitching material structure
Spatial UI for part selection and color picking
Ray-based selection, color swatch generation, emissive highlighting, haptic feedback
Surface-triggered sizing mode with scale animation
Height-based activation, US shoe size lookup table, lerp/slerp animation
Generic follow behavior for UI panels
FollowComponent with lerp smoothing and distance threshold
Spatial audio feedback system
howler.js integration, 3D positional audio relative to player head
Custom claw pointer with ray/grab mode switching
Trigger-driven claw animation, pointer mode transitions, controller model masking
WebXR session and Three.js renderer configuration
PMREMGenerator for EXR environment maps, frame rate targeting, DRACO and KTX2 loaders
Product data and color palettes
12 leather colors, 6 rubber colors, 4 prefab presets, shoe part definitions
Asset pipeline for glTF compression
gltf-transform with Draco mesh compression and KTX2 texture compression

Runtime behavior

When you run this sample, you see a 3D sneaker model floating in your mixed reality space with a welcome panel instructing you to grab it. Reach out and squeeze the trigger when your hand is near the sneaker to attach it to your controller. Once grabbed, the welcome panel disappears and a configuration panel follows the sneaker, showing the currently selected part. Use your free hand’s ray pointer to select a shoe part (it glows with emissive highlighting), then pick a color from the swatch grid. Each selection triggers a spatial audio click and haptic pulse. Lower the sneaker near the floor to activate sizing mode, where a horizontal panel appears with size controls. Release the sneaker on the surface to anchor it, adjust the size using the up/down ring controls, then grab it again to continue customizing.

Key concepts

ECS architecture with elics

The sample uses the elics ECS framework to separate data (components) from behavior (systems). Five components store state: GlobalComponent holds singleton scene references, PlayerComponent tracks controller and head positions, GrabComponent manages per-sneaker grab state, FollowComponent defines follow behavior parameters, and SoundEffectComponent triggers one-shot audio. Nine systems process this data each frame in registration order. This architecture keeps concerns separated and makes systems reusable. See src/index.js for the complete setup.

Proximity-based grab interaction

The grab system uses a proximity check against the sneaker’s bounding box in local space. Each frame, the system tests whether the controller’s world position falls within the box when transformed to sneaker space. On select-start within range, the system calls targetRaySpace.attach(sneaker) to re-parent the sneaker under the controller while preserving its world transform. On select-end, it detaches back to the scene root. See src/grab.js for the bounding box test and attach logic.

Multi-part material swapping

The sneaker model has 12 customizable parts (backtab, collar, eyestay, heel_counter, lace, midsole, outsole, quarter, quarter_overlay, tip, tongue, vamp), each with a primary material and optional secondary and stitching sub-materials. When you select a color swatch, the sample copies material properties onto the shoe part:
shoePart.material.color = material.color;
shoePart.material.roughness = material.roughness;
shoePart.material.metalness = material.metalness;
Leather parts offer 12 color options; rubber parts offer 6. Four prefab presets apply coordinated color schemes across all parts at once. See src/sneaker.js and src/configUI.js.

Spatial UI follow behavior

Configuration and welcome panels use the FollowComponent to track targets smoothly. The config panel follows the sneaker, and the welcome panel follows a head anchor positioned 0.5 meters ahead. Each frame, the FollowSystem lerps the panel’s position toward the target and calls lookAt() to face the player when the distance exceeds a threshold of 0.05 units. See src/follow.js.

Surface-triggered sizing mode

When the sneaker’s Y position drops below 0.5 units, the sizing system activates. A horizontal sizing panel appears attached to the shoe, displaying the current size as 3D text with up/down ring controls. Releasing the sneaker near the surface animates it to Y=0 via lerp for position and slerp for rotation. The size controls map US sizes 4-14 to centimeter measurements via a lookup table, scaling the sneaker mesh uniformly by the ratio of the new size to the base size. See src/size.js.

Spatial audio and haptic feedback

The sample uses howler.js to play four preloaded sound effects (confirm, click, maximize, minimize) with 3D positional audio positioned relative to the player’s head. The AudioSystem reads SoundEffectComponent entities, plays the sound, and destroys the entity. Haptic feedback pulses fire on part selection and color swatch selection. See src/audio.js.

Extend the sample

  • Add more parts: Expand the sneaker model in Blender with additional components (laces, aglets, eyelets), register them in SHOE_PART_CONFIG_OPTIONS, and regenerate the compressed glTF using content/compress.mjs.
  • Implement texture presets: Define pattern textures (stripes, polka dots, camouflage) and add a texture picker panel alongside the color picker. Apply via the material’s map property while preserving color tint.
  • Add persistence: Serialize the current configuration (part colors, size) to localStorage on change and restore it on session start, or encode the configuration in a URL parameter for sharing.