Retail · Furniture & Interiors
3D & AR configurators for furniture and interior brands.
Interactive WebGL configurators and room-scale AR without a native app. Rendered once, sold everywhere — Shopify, WooCommerce or your custom stack.

What we build
Six pieces of the configurator, engineered together.
WebGL Product Configurator
Interactive 3D on the product page — rotate, zoom, swap fabric, change wood tone, resize. Powered by Three.js and GLTF, streamed with Draco compression so mobile still loads under 3s.
Room-Scale AR Quick-Look
iOS Quick Look (USDZ) and Android Scene Viewer (GLB). Customer points their phone at the room and drops the sofa in scale — no app install, no friction.
Materials, Finishes & Dimensions
Every SKU option — fabric, leather, wood stain, metal finish, size variant — mapped to configurator states. Rules engine hides invalid combinations before the customer hits them.
Shareable Configuration URLs
Every saved combination becomes a stable URL. Customer shares with spouse, designer, or WhatsApps the sales team. Reopens with the exact same state and price.
Headless Commerce Sync
Configurator state maps to Shopify/WooCommerce variants or a custom cart. Price recalculates live from your ERP. Sales team sees the same configuration in the back-office order.
Mobile-First Performance Budget
Hard budgets on model size, texture resolution and draw calls. LOD (level of detail) switches automatically on lower-end devices. If it doesn't work on a mid-range Android in India, it doesn't ship.
The commercial case
Why the return rate is the real ROI.
A furniture return is not a customer service problem — it's a logistics, warehousing and margin problem. A sofa returned from Bengaluru to Mumbai isn't just a refund: it's re-transit, damage risk, restocking, resale as B-grade. Most furniture brands price for a return rate they hate. Reducing it is worth more than any CRO tweak on a checkout page.
The strongest reduction we see comes not from the 3D view but from the AR quick-look. Customers who drop the sofa into their real living room — actual scale, actual wall — order with confidence. The ones who don't order? Also useful — they saved you a return.
The second reduction is about specification errors. Fabric shade, leg finish, dimensions. When the customer chose it themselves in the configurator, and the sales team sees the exact same configuration in the order admin, there's no more "I meant the darker one" on delivery day.

Rendered once, sold everywhere
"One optimised 3D model replaces dozens of product shots — every colour, every angle, every finish becomes a render, not a photo shoot."
The pattern
Three.js configurator boilerplate
~120 lines. GLTF loader with Draco compression, orbit controls, live material swap. Wire the returned API into your configurator UI — swatches, dropdowns, share button.
// Three.js configurator boilerplate — GLTF load, material swap, orbit controls.
// Runs in ~120 lines with Draco compression. Drop into any React component.
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
type ConfiguratorOpts = {
container: HTMLElement;
modelUrl: string; // /models/sofa-cloud.glb
onLoaded?: () => void;
};
export function createConfigurator({ container, modelUrl, onLoaded }: ConfiguratorOpts) {
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xf5f2ed);
const camera = new THREE.PerspectiveCamera(
35, container.clientWidth / container.clientHeight, 0.1, 100,
);
camera.position.set(3.2, 1.4, 3.4);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
container.appendChild(renderer.domElement);
// Lighting — studio-style three-point.
scene.add(new THREE.AmbientLight(0xffffff, 0.35));
const key = new THREE.DirectionalLight(0xffffff, 1.4);
key.position.set(5, 8, 5);
scene.add(key);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.minPolarAngle = Math.PI / 6;
controls.maxPolarAngle = Math.PI / 2;
// Draco compression cuts model size ~10×.
const draco = new DRACOLoader();
draco.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.7/');
const loader = new GLTFLoader().setDRACOLoader(draco);
const materialsByName = new Map<string, THREE.MeshStandardMaterial>();
loader.load(modelUrl, (gltf) => {
gltf.scene.traverse((child) => {
if ((child as THREE.Mesh).isMesh) {
const mesh = child as THREE.Mesh;
const mat = mesh.material as THREE.MeshStandardMaterial;
materialsByName.set(mesh.name, mat);
}
});
scene.add(gltf.scene);
onLoaded?.();
});
function tick() {
requestAnimationFrame(tick);
controls.update();
renderer.render(scene, camera);
}
tick();
// Public API — the configurator UI calls these on user interaction.
return {
swapFabricColor(meshName: string, hex: number) {
const mat = materialsByName.get(meshName);
if (mat) mat.color.setHex(hex);
},
swapTexture(meshName: string, textureUrl: string) {
const mat = materialsByName.get(meshName);
if (!mat) return;
new THREE.TextureLoader().load(textureUrl, (tex) => {
tex.colorSpace = THREE.SRGBColorSpace;
mat.map = tex;
mat.needsUpdate = true;
});
},
dispose() {
renderer.dispose();
draco.dispose();
container.removeChild(renderer.domElement);
},
};
}What it changes
What furniture brands see a quarter after launch.
Furniture returns driven by 'looks different in my room' fall meaningfully when customers place products in AR before ordering. Same effect at every rollout.
Dwell time on the product page 3–5× the flat-image baseline. Sessions that engage the configurator convert at multiples of sessions that don't.
One interior brand we built for cut incoming 'can you show me this in walnut?' calls by pushing the answer into the configurator itself — sales team freed for closing.
One 3D model replaces dozens of product shots — every color, every angle, every finish is a render, not a photo shoot. Time and cost move sharply in your favour.
Directional patterns from furniture and interior brands in our portfolio. Actual impact depends on catalogue mix, current return rate and how the configurator is placed in the funnel.
FAQ
Questions brand owners ask.
Do we need to remodel our entire catalogue in 3D?
No — you start with your top 10–15 SKUs, the ones that drive the majority of your revenue and the majority of your returns. That's usually enough to change the numbers. From there we expand at whatever pace makes commercial sense. Existing product photography stays live for the rest of the catalogue.
How does this integrate with our Shopify or WooCommerce store?
The configurator is a mounted React/Vue component on the product page (Shopify sections or WooCommerce blocks). Configuration state maps to product variants or a metadata field on the cart line. Sales team sees the customer's exact selection in the order admin, no manual translation.
Where do the 3D models come from?
Two paths. If you have CAD/Rhino/SolidWorks source from manufacturing, we optimise those into web-ready GLTF/GLB with Draco compression — fastest path. If not, we work with a 3D artist to model from your existing furniture (photos + dimensions + fabric swatches). Budget per SKU depends on complexity.
How does AR work without a custom app?
iOS uses Apple Quick Look (a USDZ file) and Android uses Google Scene Viewer (a GLB file). Both are native OS features — no app install, no permissions dialog beyond camera. Customer taps the AR button on your product page and the 3D model opens in their real environment through their default browser.
How long from kick-off to a live configurator?
4–6 weeks for the first configurator with 3–5 SKUs, assuming clean product data. Adding SKUs after the platform is live takes 2–5 days per model, depending on complexity. AR support is included in the first launch — no separate phase needed.
A configurator that pays for itself.
Send us your top-10 SKU list and your current return rate. We'll come back with a scoped first-phase build and a projection based on brands we've shipped for.