← All @molecule/* packages · App templates
@molecule/app-three-viewer-reactFeature · three-viewer · App (browser) · v1.0.1 · Apache-2.0
WebGL 3D model viewer wrapping three.js — supports GLTF/GLB, OBJ, STL with orbit controls + lighting presets
npm install @molecule/app-three-viewer-react@molecule/app-three-viewer-react is a ready-made three-viewer feature for the app (browser) side. It composes the core interfaces it needs, so it works with whichever providers your app has bonded.
import { ThreeViewer } from '@molecule/app-three-viewer-react'
function ModelPage() {
// Inline callbacks/arrays are safe — they do not tear down WebGL.
return (
<div style={{ height: 480 }}>
<ThreeViewer
src="/models/duck.glb"
lighting="studio"
autoRotate
onLoad={() => console.log('loaded')}
/>
</div>
)
}Works with: @molecule/app-react, @molecule/app-ui, @molecule/app-ui-react
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
3D model viewer wrapping three.js.
Exports <ThreeViewer> — a React component that renders GLTF/GLB,
OBJ, or STL models with orbit controls, lighting presets
(studio/sunset/flat), auto-fit camera, and full GPU resource
cleanup on unmount — plus the resolveFormat() and
disposeObject3D() helpers and the prop types.
import { ThreeViewer } from '@molecule/app-three-viewer-react'
function ModelPage() {
// Inline callbacks/arrays are safe — they do not tear down WebGL.
return (
<div style={{ height: 480 }}>
<ThreeViewer
src="/models/duck.glb"
lighting="studio"
autoRotate
onLoad={() => console.log('loaded')}
/>
</div>
)
}
feature
npm install @molecule/app-three-viewer-react @molecule/app-react @molecule/app-ui @molecule/app-ui-react react three
npm install -D @types/react @types/three
ThreeViewerPropsProps for the {@link ThreeViewer} component.
interface ThreeViewerProps {
/** URL or path to the 3D model file. */
src: string
/**
* Model format. If omitted, inferred from the `src` extension. Falls back
* to `'gltf'` for unknown extensions.
*/
format?: ThreeViewerFormat
/** Lighting preset. Defaults to `'studio'`. */
lighting?: ThreeViewerLighting
/** Optional CSS background colour for the canvas (CSS string or hex). */
background?: string
/** Slowly rotate the camera around the model. Defaults to `false`. */
autoRotate?: boolean
/**
* Override the orbit camera target (world-space x/y/z). When omitted, the
* target is automatically set to the centre of the model's bounding box.
*/
cameraTarget?: [number, number, number]
/** Fired when the model has loaded into the scene. */
onLoad?: () => void
/** Fired when loading fails. */
onError?: (error: Error) => void
/** Extra classes merged onto the outer wrapper. */
className?: string
}
ThreeViewerFormatSupported 3D model formats.
type ThreeViewerFormat = 'gltf' | 'glb' | 'obj' | 'stl'
ThreeViewerLightingLighting presets — drive the scene's light rig.
type ThreeViewerLighting = 'studio' | 'sunset' | 'flat'
disposeObject3D(root)Walk an Object3D tree and dispose every geometry, material, and texture so three.js does not leak GPU resources when the viewer unmounts or swaps models.
function disposeObject3D(root: Object3D<Object3DEventMap>): void
root — The root node to dispose.resolveFormat(src, explicit)Resolve a model format from an explicit prop or the file extension on src.
function resolveFormat(src: string, explicit?: ThreeViewerFormat): ThreeViewerFormat
src — The model URL.explicit — The explicit format prop, if provided.Returns: The resolved format.
ThreeViewer(props)3D model viewer wrapping three.js.
Supports GLTF/GLB, OBJ, and STL inputs, orbit controls, and a small set of
lighting presets. The camera auto-fits to the model's bounding box on
load. All three.js GPU resources (geometry, materials, textures, the
renderer itself) are disposed on unmount or when the model source
(src/format) or scene structure (lighting/background) changes.
The heavy setup (renderer creation + model download) depends ONLY on those
inputs; onLoad, onError, cameraTarget, and autoRotate are routed
through refs, so passing them inline (fresh arrows / [x,y,z] literals) does
NOT tear down the WebGL context or re-download the model on a parent
re-render.
function ThreeViewer(props: ThreeViewerProps): JSX.Element
props — Component props.Returns: The rendered viewer.
Peer dependencies:
@molecule/app-react ^1.0.1@molecule/app-ui ^1.0.1@molecule/app-ui-react ^1.0.1react ^18.0.0 || ^19.0.0@molecule/app-react
@molecule/app-ui
@molecule/app-ui-react
react
three
Ships a REAL pinned three dependency — a substantial bundle-size
add. Lazy-load the importing route/component (React.lazy / dynamic
import) so non-3D pages do not pay for it.
The heavy setup effect (renderer creation + model download) depends
ONLY on src/format (and lighting/background, which restructure
the scene). onLoad, onError, cameraTarget, and autoRotate are
routed through refs + light sync effects, so passing them inline (fresh
arrows / [x,y,z] literals) does NOT tear down the WebGL context or
re-download the model on a parent re-render. Changing src/format
reloads the model; changing cameraTarget's value re-aims the camera
in place.
The wrapper is width/height: 100% with min-height: 240px — give
the PARENT an explicit height or the canvas collapses to 240px.
Requires WebGL in a real browser: do not render during SSR and do not expect it to work under jsdom tests. Model URLs must be same-origin or CORS-enabled.
format is inferred from the src extension (unknown extensions
fall back to gltf); pass it explicitly for extension-less URLs.
Must render inside the app's i18n provider and with a ClassMap bond
wired (loading/error overlays use useTranslation()); translations
ship in @molecule/app-locales-feature-three-viewer.