npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@chestnutlabs/gcode-model-renderer

v0.15.0

Published

Three.js presentation renderer for source models (STL/3MF) — clean thumbnails/cards, distinct from toolpath inspection (DD-018).

Readme

@chestnutlabs/gcode-model-renderer

Three.js presentation renderer for source models — draws an .stl or .3mf mesh as a clean, studio-lit thumbnail. It answers "what object is this?", and is deliberately separate from the toolpath renderer, which answers "how does this print/cut run?" (design: DD-018).

Peer dependency: three (supported range ^0.178.0) — install it alongside this package.

Two presentation thumbnails: a neutral gray STL part (materials: unavailable) beside a red/amber/green three-object 3MF (materials: known)

Use it for file-browser thumbnails, library cards, and "what's in this file" previews — the picture a slicer shows of a part, not the toolpath. For inspecting the actual moves (layers, travel, seams, color modes, live progress), use @chestnutlabs/gcode-renderer-three instead.

  • STL and 3MF — a bare STL is a single object with no declared material; a 3MF brings its own multi-object structure, per-object transforms, and per-object / per-triangle material colors, including files that use the 3MF Production Extension (p:path external parts).
  • Production multicolor — real Bambu Studio / OrcaSlicer files paint per-region color with a proprietary paint_color facet attribute and keep the palette in project_settings.config, not in standard 3MF materials. The renderer decodes that facet-paint format (clean-room, see RR-005) and reads the filament_colour palette itself, so a designer's multicolor model renders in its true colors without slicing.
  • Capability-honest color — when the source declares colors — standard 3MF basematerials, or paint_color + a filament palette — the render uses them and reports materials: 'known' ('approximated' when a handful of multi-color facets are flattened). When it declares none — a plain STL, or a paint format with no palette present — it draws a neutral default and reports materials: 'unavailable'. It never invents a source color.
  • Fixed presentation pose — framed at a 3/4 angle on the shared render "stage" from @chestnutlabs/gcode-renderer-three, under a neutral studio light rig, on a transparent (default) or solid background you can composite onto a card.
  • Headless stillrenderModelStill mirrors the toolpath side's renderStill: hand it bytes, get back a canvas plus a stable cacheKey and the materials confidence for that render. Runs in any Chromium-class WebGL2 context (an OffscreenCanvas in a Worker, or headless Chromium).
  • Interactive viewercreateModelViewer is the live analogue of the still: orbit, zoom, and pan the same STL / 3MF (including production multicolor) in a browser <canvas>, with camera presets, a serializable camera state, and an event stream for readiness and errors.
  • Three-free public typesModelScene / ModelObject / MeshGeometry are plain typed arrays, so the package's surface never leaks three; the renderer builds three meshes internally.
import { renderModelStill } from '@chestnutlabs/gcode-model-renderer';

// In a Worker with an OffscreenCanvas, or headless Chromium:
const { canvas, objectCount, materials, cacheKey } = await renderModelStill(
  { kind: '3mf', bytes },                        // or { kind: 'stl', bytes }
  { canvas: new OffscreenCanvas(512, 512), background: 'transparent' }
);
// materials === 'known'  → the render used colors the file declared
// materials === 'unavailable' → the file carried none; a neutral default was used (never faked)
const blob = await canvas.convertToBlob();

Already hold a corrected or richer filament palette (e.g. re-rendering a sliced file)? Pass filamentPalette (hex per 0-based slot) to renderModelStill / parse3mf to override the one read from project_settings.config. Optional — the renderer reads the file's own palette without it.

Interactive viewer

For a live surface a user can orbit — a "View in 3D" for a source model, as opposed to a static thumbnail — createModelViewer drives the same scene under the shared camera and orbit controls the toolpath renderer uses:

import { createModelViewer } from '@chestnutlabs/gcode-model-renderer';

const viewer = createModelViewer(canvas);           // a real <canvas> in the page
viewer.onEvent((e) => {
  if (e.type === 'ready') {
    // e.info.materials === 'known' | 'approximated' → showing the file's true colors
    // e.info.materials === 'unavailable'            → neutral render; don't claim "true colors"
    console.log(e.info.objectCount, e.info.materials, e.info.bounds);
  }
  if (e.type === 'renderer-unsupported') {
    // No WebGL — fall back to a renderModelStill image or a static thumbnail
  }
});

await viewer.setSource({ kind: '3mf', bytes });     // or { kind: 'stl', bytes }; parse → build → frame
viewer.setView('front');                            // 'iso' | 'top' | 'front' | 'back' | 'left' | 'right' | 'bottom'
// ...on unmount:
viewer.dispose();

Drag to orbit, scroll to zoom, right-drag to pan. getCameraState() / setCameraState() persist and restore a pose (the same serializable CameraState as the toolpath renderer), resize(w, h) matches a ResizeObserver, and setInteractionQuality('auto') trades detail for smoothness while orbiting. New source formats become viewable by registering a ModelLoader for a new kind, with no change to the viewer's API (design: DD-021).

Prefer to build your own scene? parseStl / parse3mf return a three-free ModelScene, and both the still and the viewer accept a pre-built ModelScene directly.

Determinism (stills): same input + same environment ⇒ identical output. Cross-GPU/driver pixel identity is not promised — cache by the returned cacheKey.

Part of Chestnut Labs G-code Preview · MIT