@sushindustries/product-viewer

0.1.0

Runtime material swapping and geometric zone tinting for a single GLB product. Framework-free.

pnpm add @sushindustries/product-viewer
1 min read
View as Markdown

A 3D product viewer, framework-free half. Everything here is plain three.js — no React, no renderer, no assumption that a browser is running one.

That is what lets the same code validate a catalogue at build time and drive a viewer at runtime.

Install

pnpm add @sushindustries/product-viewer three
shell

Use

import { loadProductModel, applyVariant } from "@sushindustries/product-viewer";

const model = await loadProductModel({ url: "/models/chair.glb" });

applyVariant(model, "walnut");
ts

Optional peers stay optional

Two dependencies are deliberately kept out of the main entry point:

SubpathPeerFor
/schemazodvalidating a product catalogue
/zoned-materialthree-custom-shader-materialper-zone tinting on a single mesh

A consumer who only renders models installs neither and ships neither. Importing either subpath is the moment you opt in — which is the whole reason they are not re-exported from the root.

What it does

ExportDoes
loadProductModel / disposeProductModelload a GLB, and free the GPU memory again
applyVariant / listVariants / missingVariantsGLB material variants, and telling you which ones a model is missing
defineZoneScheme / computeZoneAttributesplit one mesh into tintable zones
threeDModelJsonLd3DModel structured data for the page the model sits on

missingVariants exists because a catalogue and a model drift apart quietly. Asking the model which variants it actually has, at build time, turns that into a failed build instead of a beige sofa.

Disposal is not optional

three.js does not garbage-collect GPU memory. loadProductModel has a matching disposeProductModel, and a viewer that mounts and unmounts without calling it leaks until the tab is closed.