Skip to content

Latest commit

 

History

History
211 lines (171 loc) · 11.1 KB

File metadata and controls

211 lines (171 loc) · 11.1 KB

Chestnut Labs G-code Preview

A worker-based, cross-vendor G-code toolpath stack for the browser: parse .gcode and .gcode.3mf off the main thread, normalize them into a versioned intermediate representation (ToolpathIR), and render an interactive Three.js preview — with first-class Vue, React, and Svelte integrations that are thin adapters over one shared, framework-neutral engine.

Status: published. All ten @chestnutlabs/* packages are on npm (latest v0.2.0, lockstep-versioned with npm provenance). E0–E9 of the master plan are closed; E10 (motion-model correctness) is in progress. Install from npm — see Quick start below.

3DBenchy rendered as tubes with feature coloring in the showcase viewer

What you get

  • Off-thread parsing — a Web Worker session (GcodeParseSession) with streaming input, progressive preview for large files, resource limits, and an adversarial-input corpus behind it.
  • Cross-vendor dialect handling — PrusaSlicer, OrcaSlicer/Bambu Studio, Cura, Klipper, Marlin, and RepRap-flavor annotations (features, objects, bed geometry, thumbnails, multi-tool), each claim capability-tagged as known | inferred | approximated | unavailable — the stack refuses to fabricate what it cannot know.
  • .gcode.3mf container support — zero-dependency, bounded ZIP extraction with multi-plate selection, hardened against adversarial archives.
  • A versioned neutral IR (ToolpathIR) — structure-of-arrays geometry + metadata + source index; the seam between parsing and everything else.
  • A Three.js renderer — layer chunks with decimation disclosure, layer-range clip and segment-level scrub, tube or line geometry with automatic quality fallback, per-file build plates, WebGL context-loss recovery.
  • Honest live progress (for printer telemetry) — a normalized ProgressObservation contract mapped onto the toolpath with tiered confidence: a precise cut + marker when the source position is known, an uncertainty band when it is approximated, stale-signal handling, and user scrub always winning.
  • Three equal framework adapters — each ships a ready-to-use <GcodePreview> component and a lower-level surface, with the same capabilities, options, events, and TypeScript contracts, enforced by a shared behavioral suite that runs against all three in CI.
Honest live progress Layer clipping & scrub
Live-progress overlay: the completed portion rendered in full color, the remaining path as a translucent ghost, and an orange marker at the byte-exact print position 3DBenchy clipped to layer 73 of 174, exposing perimeters and infill with feature coloring
Completed cut + translucent remaining-path ghost + byte-exact position marker (uncertainty band when the signal is approximate) Draw-range layer clipping — no geometry rebuilds; segment-level scrub works the same way

Packages

Package What it is
@chestnutlabs/toolpath-core ToolpathIR, capability model, progress mapping
@chestnutlabs/gcode-parser Worker parse core + session client (streaming, limits, workers)
@chestnutlabs/gcode-dialects Slicer/firmware dialect annotators
@chestnutlabs/gcode-containers .gcode.3mf / ZIP container adapters
@chestnutlabs/gcode-renderer-three Three.js toolpath renderer (peer: three)
@chestnutlabs/gcode-preview-core Framework-neutral preview controller + portable behavioral suite
@chestnutlabs/gcode-preview-vue Vue 3 component + useGcodePreview() composable
@chestnutlabs/gcode-preview-react React component + useGcodePreview() hook
@chestnutlabs/gcode-preview-svelte Svelte component + createGcodePreview() store/action
@chestnutlabs/gcode-preview-element Framework-free <gcode-preview> Web Component (no peer framework)

Quick start

Install the adapter for your framework plus three (the renderer declares three as a peerDependency, range ^0.178.0 — npm ≥ 7 installs it automatically; pnpm/yarn users add it explicitly):

npm install @chestnutlabs/gcode-preview-vue three     # or -react / -svelte

Each adapter has two adoption levels — a complete component, and a lower-level API for building your own controls (composable / hook / store) — documented in its package README.

Vue

<script setup>
import { GcodePreview } from '@chestnutlabs/gcode-preview-vue';
import { shallowRef } from 'vue';
const file = shallowRef(null);
</script>

<template>
  <input type="file" accept=".gcode,.3mf" @change="file = $event.target.files?.[0] ?? null" />
  <div style="height: 70vh">
    <GcodePreview :source="file" @ready="(s) => console.log(`${s.segments} segments`)" />
  </div>
</template>

Lower level: useGcodePreview() — canvas ref, worker parse, controls, reactive state summaries.

React

import { GcodePreview } from '@chestnutlabs/gcode-preview-react';

function Viewer({ file }) {
  return (
    <div style={{ height: '70vh' }}>
      <GcodePreview source={file} onReady={(s) => console.log(`${s.segments} segments`)} />
    </div>
  );
}

StrictMode-safe. Lower level: useGcodePreview() (useSyncExternalStore-backed state, identity-stable handle).

Svelte

<script>
  import GcodePreview from '@chestnutlabs/gcode-preview-svelte/GcodePreview.svelte';
  let file = null;
</script>

<div style="height: 70vh">
  <GcodePreview source={file} on:ready={(e) => console.log(`${e.detail.segments} segments`)} />
</div>

Ships as raw .svelte (your bundler's Svelte plugin compiles it). Lower level: createGcodePreview() — store contract + use: canvas action.

All three components share the same defaulted prop surface — source, parseOptions, buildVolume, quality, colorMode, layerRange, scrub, showTravel, progress, createWorker — with matching events/callbacks. <GcodePreview source={file} /> is the whole thin path; the full viewer is reachable without switching APIs.

Workers: batteries included, escape hatch provided

  • Default (zero setup): the adapters create the batteries worker — every supported dialect adapter plus .gcode.3mf support — via the bundler-native new Worker(new URL(...)) pattern. Vite resolves it out of the box (tested in CI).
  • Custom: pass createWorker for the slim build, custom dialect adapters, other bundlers, or strict-CSP environments. Both paths are documented in the Vue package README (shared across adapters by design).

Format, dialect & capability support

  • Formats: .gcode (plain), .gcode.3mf (sliced-plate container; multi-plate via parseOptions.plate).
  • Dialects: PrusaSlicer, OrcaSlicer/Bambu, Cura, Klipper, Marlin, RepRap-flavor — see the evidence-dated compatibility matrix.
  • Motion commands: which position-affecting G/M-codes are honored — absolute/relative positioning (G90/G91), extruder mode (M82/M83), and the G92 E-datum are modeled (E10 phase 1); arc planes (G17G19) and work-coordinate systems are still in progress — see G-code motion coverage.
  • Build volume: per-file discovered bed geometry with consumer-wins precedence (your configured plate is never silently overridden; discovery is emitted instead).
  • Live progress: the normalized progress signal contract plus consumer notes for wiring real printer telemetry (Moonraker, Bambu, OctoPrint-class sources).
  • Support & deprecation policy: Node/browser/framework matrix and the rolling support window.
  • Headless still render: renderStill — a single non-interactive image from a Worker OffscreenCanvas, Electron hidden window, or headless Chromium (server-side thumbnails).

See it running

  • tools/demo — the showcase: full control panel over the whole pipeline (corpus picker, dialect annotations, quality/color modes, layer clip + scrub, simulated live-progress tiers), plus a Vue-component parity page and the visual-regression harness. npm run dev inside the directory.
  • tools/example-react, tools/example-svelte — complete Vite apps per framework, run the same way. All three apps consume the packages exactly as an external consumer would.

Project status & governance

Docs-first: every architecture-sensitive epic passes a Design Document gate before implementation. The master plan controls direction; the docs index tracks epic status; accepted designs live in docs/design/. Current state: E0–E9 closed and accepted (parser, dialects, containers, renderer, live progress, multi-framework integration, the v0.1.0 release, and v0.2.0's toolpath annotations + renderer options); E10 (motion-model correctness) is in progress — its phase 1 (M82/M83, G90/G91, the G92 E-datum) has shipped, with arc planes and coordinate systems to follow.

Contributions: see CONTRIBUTING.md · security policy: SECURITY.md.

Development

# Node >= 22
npm ci
npm run build            # inherited engine build (rollup)
npm run test             # root suite (IR goldens, manifest validation, adapters)
npm run test:packages    # all workspace package suites
npm run lint && npm run typeCheck && npm run license:check
npm run test:consumer-vue   # tarball consumer fixture
npm run pack:check       # packaged-artifact gate (pack snapshots + publint + attw)

Origin & attribution

This project began as a fork of xyz-tools/gcode-preview (project identity remcoder/gcode-preview) by Remco Veldkamp and contributors, MIT-licensed. Chestnut Labs has since rebuilt it into the worker-based multi-package stack described above; the inherited Git history is preserved, upstream copyright notices are retained in LICENSE, and the full attribution and provenance record lives in NOTICE.md, docs/UPSTREAM_PROVENANCE.md, and the upstream & licensing policy. Upstream changes are adopted deliberately through review, never auto-synced.

License

MIT — inherited code © 2017–2025 Remco Veldkamp and the xyz-tools/gcode-preview contributors; Chestnut Labs additions © 2026 Chestnut Labs.