Skip to Content
API ReferenceBindingBuilder

BindingBuilder

A design-time helper component for authoring objectBindings and sceneConfig in the browser. Load a GLB, GLTF, OBJ, FBX, USDZ, STL, or PLY asset, inspect its mesh nodes, edit binding fields, configure the scene, preview the result live, and export as JSON or TypeScript.

Try the public editor at react-immersive.liveroom.dev/editor .

Usage

import "@liveroom-tech/react-immersive/binding-builder.css"; import { BindingBuilder } from "@liveroom-tech/react-immersive/binding-builder"; export default function App() { return <BindingBuilder licenseKey="your_license_key" />; }

Props

type BindingBuilderProps = { licenseKey: string; dracoDecoderPath?: string | false; ktx2TranscoderPath?: string | false; meshopt?: boolean; };

licenseKey is required and is validated the same way as ModelViewer’s, see Licensing & plan tiers below. While the key is being checked, BindingBuilder renders a “Verifying license…” placeholder; if the key is invalid, it renders an error message instead of the editor.

The decoder props are forwarded to the editor preview. Built-in defaults support Meshopt, DRACO, and KTX2; override them with self-hosted directories or false. See the ModelViewer decoder setup.

Capabilities

Object tab

  • Upload a .glb, standalone/data-URI .gltf, .obj, .fbx, .usdz, .stl, .ply, or .zip bundle. ZIP bundles may contain GLTF dependencies, OBJ + MTL/textures, or FBX external textures; USDZ is uploaded directly
  • Traverse renderable mesh nodes and generate starter bindings automatically
  • For an object without texture coordinates (STL, most PLY), the Material image map fields are turned off with a note, and the starter actions leave out Change Material (see STL and PLY)
  • Edit binding fields: identity, label, type, status, booleans, style, actions, metrics, metadata, and saved camera state
  • Add decals from the Decals panel: upload an image or add text to place it automatically at the centre of the camera-facing surface. Set its size, rotation, and opacity; Move lets you drag it across the object’s surface. Release to save, or press Escape to cancel. The Position arrows move the decal in small steps on the visible surface relative to the camera; click for a fine adjustment or hold an arrow to keep moving. Each step can be undone. Uploaded images are exported under materials/ with the bindings
  • Move and rotate the selected object with a geometry-centered pivot, World or Local axes, numeric position/rotation fields, and restore-to-authored-transform support
  • Author a full per-object material in the Material panel, a one-click preset gallery (wood, metal, chrome, glass, plastic, fabric, ceramic, concrete, etc.) plus collapsible sub-panels for PBR maps, roughness, emission, opacity, normal & bump, displacement, ambient occlusion, clearcoat, sheen, anisotropy, transmission & volume, and faces rendering. Each sub-panel has an enable toggle, and every field maps to a style.material override (see ObjectBindingMaterial)
  • Undo/redo the current bindings (toolbar buttons, or Cmd/Ctrl+Z / Cmd/Ctrl+Shift+Z while the Object tab is active), rapid edits like slider drags coalesce into a single undo step
  • Import a previously exported objectBindings.json and merge it back onto the current model (matched by modelObjectId, so re-imports survive hand edits or partial files)
  • Export the current bindings as JSON or TypeScript

Model ZIPs are limited to 128 MiB compressed, 1,024 entries, 128 MiB per expanded entry, 256 MiB expanded in total, and a 200:1 per-entry compression ratio. Every GLTF dependency must be included in the archive: absolute, root-relative, and other external asset URLs are rejected. data: URIs are allowed.

Scene tab

In Annotations, edit a marker’s title, description, category, image URLs and alt text, and link URLs and labels. Capture current view saves the preview camera, Preview recalls it, and Clear view uses automatic tour framing. New markers use automatic close-up zoom until you explicitly capture a custom view. Optional minimum and maximum distances hide markers outside the chosen range (scene units); blank fields mean no limit. These fields persist in exported sceneConfig.annotations.

  • Configure scene-wide settings (lighting, environment, background, ground shadows, wireframe, post-processing, annotations, per-clip animation options, and a cinematic camera path), the same SceneConfig shape consumed by ModelViewer’s sceneConfig prop
  • Configure scene auto-rotation and speed. These values are exported as sceneConfig.model.autoRotate and sceneConfig.model.autoRotateSpeed
  • Isolate a node from the Scene Nodes list (the button at the end of its row) to see it on its own in the preview while you edit it. This is only for editing and isn’t exported
  • Set up a section cut under General → Section Cut (axis, position, and which side stays), exported as sceneConfig.section. The preview has the section toolbar and a plane you can drag
  • Build style rules in the Rules sub-tab: pick the objects (all, a group, tag, type, or one object), the conditions (metric ranges, status, metadata values), and the look (colour, opacity, glow, a colour scale from a metric, or a pulse). The form suggests the model’s own groups, tags, metric names, and metadata keys, shows how many objects each rule matches, and the preview updates as you edit. Exported as sceneConfig.styleRules; see Style rules
  • Check your changes with Compare above the preview: a divider across the preview shows the project as it was opened on its left and as it is now on its right. Drag it (or focus it and use the arrow keys) to sweep between them; orbiting either side moves both. Pin, on the “Before” label, makes the current state the “before”, to compare the next round of changes with it. The preview stays live while comparing, and the “before” side is view only. It is the same slider as CompareViewer
  • Pick which of the model’s glTF material variants (KHR_materials_variants) the scene starts with (General, one select per option group, such as Paint and Wheels), exported as sceneConfig.model.activeVariants. The preview’s swatch rows change the same setting
  • Position and rotate directional, point, and spot lights with transform gizmos; spot lights also expose angle and penumbra controls
  • Switch the model renderer between PBR, Matcap, and UV Checker. UV Checker overlays a numbered directional chart to diagnose stretching, seams, rotation, texel-density differences, and missing UV0 coordinates
  • Author a cinematic camera path visually in the Cinematic sub-tab: frame the model in the preview, click Add waypoint from current view to capture the camera pose, then set its segment duration, reorder, fly-to-preview (📍), or delete waypoints. Toggle Enable / Loop / Auto-play and the overall glide Duration. The path is stored on sceneConfig.cinematic and replayed by ModelViewer’s cinematic prop
  • Undo/redo the scene config independently of the Object tab’s bindings history
  • Import a previously exported sceneConfig.json, merged by top-level section so a partial file doesn’t wipe sections it doesn’t include
  • Export the current scene config as JSON or TypeScript

Preview

  • Live preview of the selected node in an embedded ModelViewer, including loading progress and orbit/pointer-lock camera modes

Autosave and restoring a session

BindingBuilder keeps your work in the browser, so a reload or a closed tab doesn’t lose it:

  • Once you change something, the session is saved shortly after each edit, and again when the tab is hidden or closed. A session is the model, its object bindings, and the scene settings. An uploaded model file is saved with it, so it doesn’t need uploading again.
  • Restore last session (in the ”⋯” menu above the preview) reopens the saved session. One session is kept per browser, and each save replaces the last.
  • While there are edits on screen, leaving or reloading the page asks for confirmation first. Loading or restoring a model without changing it doesn’t.
  • Sessions live in this browser’s IndexedDB, in a database named react-immersive:binding-builder. They aren’t shared across browsers or devices, and private browsing may discard them. If the browser refuses to store a session, usually for lack of space, BindingBuilder says so; export your work to keep it.

Autosave is a safety net, not a way to keep or share work: export JSON or TypeScript to keep bindings and scene settings with your application.

Moving and rotating objects

Open the Move & Rotate panel in the Object tab, then:

  1. Turn on Transform gizmo. Camera controls pause while editing is enabled.
  2. Select a bound mesh in the preview or object list.
  3. Drag an arrow to move on one axis, a plane handle to move on two axes, or a colored ring to rotate. Move and rotate handles are always shown together.
  4. Choose World to keep the handles aligned with the scene, or Local to align them with the selected object’s current orientation.
  5. Use the horizontal X, Y, and Z fields for precise values. Rotation fields display degrees; the exported binding stores radians.

The pivot is placed at the center of the selected object’s renderable geometry, so rotation happens around the object itself even when the source node’s authored origin is elsewhere. This authoring pivot does not rewrite the GLB/GLTF origin.

Both gizmo and numeric edits are saved to the selected binding’s local-space transform.position and transform.rotation. Changing World/Local axis space only changes the direction of the gizmo handles; it does not change the saved position. Use Restore original position & rotation to remove those overrides and return to the model-authored transform.

Exporting and Reusing Files

BindingBuilder has separate toolbars for bindings and scene settings, so export the data from the tab that owns it:

  1. Load your model first. The import and export controls become available once BindingBuilder has inspected its nodes.
  2. Open the Object tab to work with objectBindings. In that tab’s toolbar, use Export → JSON or Export → TypeScript.
  3. Open the Scene tab to work with sceneConfig. Its toolbar has the same Export menu, producing sceneConfig.json or sceneConfig.ts.
  4. Choose TypeScript for a file you will import into your application. Choose JSON for a portable snapshot that you want to bring back into BindingBuilder later.

We recommend keeping TypeScript exports alongside the viewer route, for example:

src/immersive/objectBindings.ts src/immersive/sceneConfig.ts public/model.glb public/materials/... (when the export includes uploaded textures)

The TypeScript bindings export already wraps the record in defineObjectBindings, so TypeScript validates the complete file without widening its keys or literal IDs. Import the named exports directly and pass them to ModelViewer:

import { useState } from "react"; import { ModelViewer } from "@liveroom-tech/react-immersive"; import { objectBindings as initialObjectBindings } from "./objectBindings"; import { sceneConfig } from "./sceneConfig"; export default function ProductViewer() { const [objectBindings, setObjectBindings] = useState(initialObjectBindings); return ( <ModelViewer modelUrl="/model.glb" licenseKey="your-license-key" objectBindings={objectBindings} sceneConfig={sceneConfig} onObjectBindingsChange={setObjectBindings} /> ); }

Importing Back into BindingBuilder

Use the Import button in the same toolbar as the matching export:

  • Object tab → Import accepts an objectBindings.json file. Load the model first; incoming records are matched by modelObjectId, so bindings for nodes absent from the current model are safely skipped.
  • Scene tab → Import accepts a sceneConfig.json file. Included top-level sections are merged into the current scene config, which lets you restore a partial scene preset without resetting the other settings.

TypeScript exports are deliberately for your application source code, not for the editor’s import button. Keep a JSON export whenever you expect to reopen or share the configuration in BindingBuilder.

Picking a texture map stores the durable path materials/<filename> in the binding (this is what’s exported), and shows the image immediately in the live preview via an in-memory blob: URL, so you can author without first copying files into public/.

Exporting bundles the files automatically: if any material field was filled by uploading a file, clicking Export downloads a .zip instead of a single .json/.ts, containing the export file plus a materials/ folder with every uploaded image. Unzip it into your app’s public/ folder and the exported bindings resolve as-is. Two different uploads that happen to share a filename are kept distinct (materials/wood.jpg, materials/wood-2.jpg, …) rather than one overwriting the other. If nothing was uploaded, Export downloads a plain .json/.ts file exactly as before.

Licensing & plan tiers

BindingBuilder validates licenseKey the same way ModelViewer does, and additionally gates some editor features by the license’s plan tier:

TierUnlocks
freeBase color, metalness/roughness sliders, basic scene settings
starter+ Texture maps, the specular workflow, reflectivity, environment lighting, environment backgrounds, wireframe preview, animation configuration, annotations, cinematic camera paths, style rules, decals
growth+ Post-processing effects

A locked feature is shown in place (not hidden) with a message naming the required plan, so the feature stays discoverable while editing. Get a license key at the React Immersive Console .

Typical Workflow

  1. Mount <BindingBuilder /> in a dev-only route (e.g. /dev/bindings)
  2. Upload your .glb, .gltf, .obj, .fbx, .usdz, .stl, .ply, or .zip
  3. Select mesh nodes in the sidebar, edit their binding fields, move or rotate them as needed, or apply a material preset
  4. Configure scene-wide settings in the Scene tab
  5. Preview the interactive result in the embedded viewer
  6. Click Export → JSON or Export → TypeScript to download the bindings (and, if you uploaded any textures, a .zip with them included)
  7. Drop the exported file (and any materials/ folder) into your app as the initial objectBindings / sceneConfig state