~/posts/shopify-configurators/

A 3D Product Configurator Is Mostly a State Problem

Why Liquid data contracts, variant identity, asynchronous loads, bundle semantics, and mobile behavior matter more than the model itself.

tutorialshopifyfrontendcommerce

The 3D model was not the state model

A product configurator can look like a graphics feature while most of its correctness lives somewhere else.

The scene has to display the customer’s current choices, but Shopify still owns products, variants, availability, prices, and cart lines. If the rendered bottle looks right while the selected merchandise is unavailable or the cart receives the wrong variant, the most impressive part of the interface becomes evidence that the state model is broken.

I treated the 3D layer as one projection of commerce state. The same selection object drove option controls, model materials and nodes, price totals, availability messages, and the final cart request.

Liquid became the data bridge

The theme already had the authoritative Shopify objects at render time.

Liquid serialized the relevant products, variants, media, metafields, and availability into a compact client-side payload. JavaScript did not scrape text from the DOM or duplicate product definitions by hand. It began with the same catalog data that powered the storefront.

That bridge needed discipline. Payloads had to escape safely, distinguish display labels from stable identifiers, and include only the fields the configurator required. A smaller explicit contract made client state easier to reason about and reduced the chance that a merchant edit would break an assumed DOM shape.

Map selections to both catalog and scene

One customer choice often affects two different systems.

A selected option can resolve to a Shopify variant or bundle item while also changing a GLTF node, visibility group, texture, or material in the scene. I kept those mappings explicit rather than deriving them from human-readable titles. Stable handles make renaming copy less likely to break cart or rendering behavior.

The reducer-like update path recalculated derived state after every selection: active options, price, availability, scene changes, and whether the configuration could be added. That prevented event handlers from each owning a partial version of the truth.

Asynchronous loads need identity

A customer can change options faster than a model or texture finishes loading.

Without a guard, an older request can resolve last and overwrite the scene with stale content. I associated loads with the current selection token and ignored results that no longer matched. Parsed assets were cached where reuse was safe, while per-configuration state remained separate.

The same principle applies beyond 3D. Any asynchronous response that updates interactive state should prove it still belongs to the current request before committing the result.

The cart needed a coherent bundle

Adding several selected pieces as unrelated cart lines loses the configuration the customer made.

The cart request grouped the selected items with line-item properties that described the shared configuration. Availability was checked before submission, button state communicated when the build was incomplete, and the success path updated the existing cart experience instead of creating a separate checkout flow.

This kept the configurator inside Shopify’s commerce model. The scene could be custom, but inventory, cart behavior, and checkout remained native. That boundary reduced risk and made the feature maintainable inside a theme rather than a parallel storefront application.

Mobile changed the interaction, not the product

A desktop scene with tiny controls is not a mobile configurator.

The layout, camera defaults, control density, loading treatment, and touch behavior needed explicit mobile decisions. Model optimization and asset reuse mattered more on constrained devices, but so did keeping the commerce state visible when the scene occupied less space.

The broader lesson was that the 3D layer should earn its place by clarifying the product. When state, availability, cart semantics, and mobile behavior are correct, the model becomes a useful interface. Without those foundations, it is only animation next to a buy button.