Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@
"tools/example-webcomponent"
],
"port": 5204
},
{
"name": "docs-site",
"runtimeExecutable": "node",
"runtimeArgs": [
"tools/docs/serve-site.mjs"
],
"port": 5098
}
]
}
8 changes: 8 additions & 0 deletions .github/workflows/docs-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ on:
- 'packages/**'
- 'typedoc.json'
- 'tools/docs/**'
- 'tools/demo/**'
- 'tools/demo-kit/**'
- 'tools/example-react/**'
- 'tools/example-vue/**'
- 'tools/example-svelte/**'
- 'tools/example-webcomponent/**'
- 'docs/manual/**'
- 'docs/media/**'
- '.github/workflows/docs-pages.yml'
Expand All @@ -39,6 +45,8 @@ jobs:
cache: 'npm'
- run: npm ci
- run: npm run docs:build
# Build the live, interactive demos into the Pages artifact (docs-site/demos/*).
- run: npm run docs:demos
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
Expand Down
67 changes: 46 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@
**Show a 3D print or CNC/laser job in the browser — before, during, or after it runs.**
Drop `.gcode`, `.gcode.3mf`, or Prusa `.bgcode` into a web page and get an interactive toolpath
view: orbit it, clip it to a layer, scrub through it, color it by feature or speed, and overlay
live printer progress. Parsing runs in a Web Worker, so a 250 MB file never freezes your UI.
live printer progress. Or view the **source model** (STL / 3MF) before it's sliced. Parsing runs in
a Web Worker, so a 250 MB file never freezes your UI.

[![npm](https://img.shields.io/npm/v/@chestnutlabs/gcode-preview-react?label=npm&color=cb3837)](https://www.npmjs.com/package/@chestnutlabs/gcode-preview-react)
[![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
[![docs](https://img.shields.io/badge/docs-manual%20%2B%20API-2ea44f)](https://chestnutlabs.github.io/gcode-preview/)
![node](https://img.shields.io/badge/node-%E2%89%A522-339933)

![3DBenchy rendered as extrusion tubes with per-feature coloring — perimeters, infill, and skirt in distinct colors — on a neutral grey build plate](docs/media/viewer-benchy-tubes.png)
![The G-code Preview Feature Lab — a 3DBenchy colored by feature role in the viewport, with the inspector rail (move-visibility toggles, feature-role hide, segment inspection), a color-mode legend, camera controls, a layers/segments/time scrub strip, and honest capability badges](docs/media/app-control-panel.png)

**▶ [Try the live demo](https://chestnutlabs.github.io/gcode-preview/demos/)** — open the interactive **Feature Lab**, or the **React / Vue / Svelte / Web Component** examples, right in your browser. Nothing is uploaded; parsing runs in a Web Worker.

---

## What it is

G-code Preview turns a sliced G-code file into an interactive picture of the actual toolpath. It
reads the file the way the printer will — every move, layer, feature, and tool change — and draws
it with Three.js (or a Canvas 2D fallback for low-GPU devices). It ships as a set of
`@chestnutlabs/*` npm packages with ready-made **Vue, React, Svelte, and Web Component** components,
all built on one shared engine.
G-code Preview covers **both halves** of looking at a print job. **Preview** turns a sliced G-code
file into an interactive picture of the actual toolpath — reading the file the way the printer will,
every move, layer, feature, and tool change, drawn with Three.js (or a Canvas 2D fallback for
low-GPU devices). **Prepare** shows the **source model** (STL / 3MF) before slicing — the object,
its parts, and its material colors. It ships as a set of `@chestnutlabs/*` npm packages with
ready-made **Vue, React, Svelte, and Web Component** components, all built on one shared engine.

One rule runs through the whole thing: **it shows what it can prove and refuses to fake the rest.**
If a slicer didn't record feature types, the viewer says so instead of inventing colors. If live
Expand All @@ -30,7 +34,22 @@ telemetry only reports a percentage, it draws an uncertainty band, not a false-p
npm install @chestnutlabs/gcode-preview-react three # or -vue / -svelte / -element
```

![The demo application: a control panel — corpus picker, layer and time scrub, an honest "54.2 min (slicer estimate)" print time, display toggles — beside a fully rendered 3DBenchy with feature coloring](docs/media/app-control-panel.png)
### Two modes, one SDK — Prepare & Preview

| Prepare — the source model | Preview — the sliced toolpath |
|---|---|
| ![The Feature Lab in Prepare mode: a colored 3MF source model (red, amber, green stacked blocks) with a Source Model panel reporting 3 objects, 3 placements, and materials: known](docs/media/app-prepare.png) | ![The Feature Lab in Preview mode: a 3DBenchy colored by feature role with the inspector rail, feature legend, camera controls, and layer/segment scrub](docs/media/app-control-panel.png) |
| **STL / 3MF** solid model — objects, materials, model controls, honest material-color tier. | **Sliced G-code** — layers, features, speed, travel, retractions, and toolpath controls. |

The controls and capabilities are front-and-centre, not hidden behind a render:

| Color modes, capability-gated | Render diagnostics & capabilities |
|---|---|
| ![The Appearance tab: a color-by selector (single / tool / feature / speed / object / layer height) with the active feature-role legend; modes the file can't support are greyed out](docs/media/app-appearance.png) | ![The Diagnostics tab: capability confidence badges and getRenderStats() output — backend, GPU, geometry mode, segment and draw-call counts, worker pool](docs/media/app-diagnostics.png) |

You can drive all of this yourself in the **[live demos](https://chestnutlabs.github.io/gcode-preview/demos/)**. A cropped beauty render — the same engine, no UI:

![3DBenchy rendered as extrusion tubes with per-feature coloring — perimeters, infill, and skirt in distinct colors — on a neutral grey build plate](docs/media/viewer-benchy-tubes.png)

## Why you'd use it

Expand Down Expand Up @@ -173,14 +192,16 @@ every FDM file is byte-for-byte unchanged. See
### Framework integration

Four adapters over one engine, with matching options, events, and TypeScript types — enforced by a
shared behavioral test suite that runs against all four in CI:
shared behavioral test suite (with a controls/state parity guard) that runs against all four in CI.
Each adapter exposes **both** viewers: the toolpath `<GcodePreview>` from the package root, and the
source-model `<ModelViewer>` from the package's **`/model`** subpath (the Prepare side).

| Adapter | Package | Component + lower-level API |
|---|---|---|
| **Vue 3** | [`@chestnutlabs/gcode-preview-vue`](packages/gcode-preview-vue) | `<GcodePreview>` + `useGcodePreview()` composable |
| **React** | [`@chestnutlabs/gcode-preview-react`](packages/gcode-preview-react) | `<GcodePreview>` + `useGcodePreview()` hook (StrictMode-safe) |
| **Svelte** | [`@chestnutlabs/gcode-preview-svelte`](packages/gcode-preview-svelte) | `<GcodePreview>` + `createGcodePreview()` store/action |
| **Web Component** | [`@chestnutlabs/gcode-preview-element`](packages/gcode-preview-element) | `<gcode-preview>` custom element, no framework peer |
| Adapter | Package | Preview (toolpath) | Prepare (source model, `/model`) |
|---|---|---|---|
| **Vue 3** | [`@chestnutlabs/gcode-preview-vue`](packages/gcode-preview-vue) | `<GcodePreview>` + `useGcodePreview()` | `<ModelViewer>` + `useModelViewer()` |
| **React** | [`@chestnutlabs/gcode-preview-react`](packages/gcode-preview-react) | `<GcodePreview>` + `useGcodePreview()` (StrictMode-safe) | `<ModelViewer>` + `useModelViewer()` |
| **Svelte** | [`@chestnutlabs/gcode-preview-svelte`](packages/gcode-preview-svelte) | `<GcodePreview>` + `createGcodePreview()` | `<ModelViewer>` + `createModelViewer()` |
| **Web Component** | [`@chestnutlabs/gcode-preview-element`](packages/gcode-preview-element) | `<gcode-preview>` (no framework peer) | `<gcode-model-viewer>` |

### Browser & performance architecture

Expand Down Expand Up @@ -244,11 +265,15 @@ const { canvas, materials, cacheKey } = await renderModelStill(
// materials: 'known' when the source carried colors, 'unavailable' when it didn't.
```

Need it live rather than as a thumbnail — a "View in 3D" for the part? `createModelViewer` is the
interactive analogue of the still: it orbits, zooms, and pans the same STL / 3MF (including production
multicolor) with camera presets and the same serializable camera state, over the shared camera and
orbit controls. See the
[model-renderer README](packages/gcode-model-renderer/README.md#interactive-viewer).
Need it live rather than as a thumbnail — a "View in 3D" for the part? Interactive source-model
viewing is a **first-class, declarative half of the SDK**: drop `<ModelViewer source={…} />` from any
framework's **`/model`** subpath (`@chestnutlabs/gcode-preview-{react,vue,svelte}/model`, or
`<gcode-model-viewer>` from the Web Component) and orbit/zoom/pan the same STL / 3MF (including
production multicolor) with camera presets, serializable camera state, per-plate render scope, and the
honest `materials` capability tier — the same parity (props, events, lifecycle, cleanup) as the
toolpath component. It wraps the framework-neutral `createModelPreviewController` over the shared
`createModelViewer` engine. See the [adapters guide](docs/manual/adapters.md) ("Two viewers: Preview
and Prepare") and the [model-renderer README](packages/gcode-model-renderer/README.md).

**Multi-plate, multi-object, or just a subset.** A 3MF project can hold several plates and many
objects. Parse or render **one plate at a time** (`parseOptions.plate`), and a **render scope**
Expand Down Expand Up @@ -452,7 +477,7 @@ row inspects the *toolpath*, the bottom row presents the *source model* (see

Design rationale, boundaries, and the accepted architecture live in
[`docs/design/`](docs/design); the [docs index](docs/README.md) maps the whole set. Fourteen
packages publish to npm in lockstep (currently **v0.20.0**) with npm provenance.
packages publish to npm in lockstep (currently **v0.20.1**) with npm provenance.

## Development

Expand Down
49 changes: 11 additions & 38 deletions RELEASE_REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
parses them literally. Delete rows only for packages that did not change.
-->

# Release review — v0.20.0
# Release review — v0.20.1

**Review version:** v0.20.0
**Changed-capability inventory diffed against:** `v0.19.0`
**Review version:** v0.20.1
**Changed-capability inventory diffed against:** `v0.20.0`

This artifact records the per-release **Public Product + Documentation + Visual** reconciliation:
before the `dev` -> `main` promotion, compare the changed capabilities below against the README,
Expand All @@ -28,45 +28,18 @@ each disposition. Guidance: CLAUDE.md "Public-docs completion check" and

| Package | Changed src files | Changelog summary | Disposition |
|---|--:|---|---|
| `@chestnutlabs/gcode-model-renderer` | 4 | Make interactive **source-model viewing** (STL / 3MF) a first-class, declarative half of the SDK — | Status: reviewed |
| `@chestnutlabs/gcode-preview-core` | 4 | Close the dark-capability gaps so no shipped capability is reachable only through the | Status: reviewed |
| `@chestnutlabs/gcode-preview-element` | 6 | Close the dark-capability gaps so no shipped capability is reachable only through the | Status: reviewed |
| `@chestnutlabs/gcode-preview-react` | 7 | Close the dark-capability gaps so no shipped capability is reachable only through the | Status: reviewed |
| `@chestnutlabs/gcode-preview-svelte` | 6 | Close the dark-capability gaps so no shipped capability is reachable only through the | Status: reviewed |
| `@chestnutlabs/gcode-preview-vue` | 6 | Close the dark-capability gaps so no shipped capability is reachable only through the | Status: reviewed |
| `@chestnutlabs/gcode-renderer-three` | 3 | `CaptureOptions` gains `includeBuildVolume?: boolean` (default `true`). Set it to `false` to exclude | Status: reviewed |
| `@chestnutlabs/gcode-parser` | 2 | Fix a parse-session hang on a double `cancel()`. A second `cancel()` while a cancel was already pending (e.g. the controller cancelling befo | Status: reviewed |
| `@chestnutlabs/gcode-preview-element` | 2 | Fix `<gcode-preview>` connect/disconnect defects: the initial `view` attribute (and a `cameraState` set before connect) are now applied on c | Status: reviewed |
| `@chestnutlabs/gcode-preview-react` | 2 | Fix `<ModelViewer>` / `useModelViewer` (React) leaking its controller on unmount. The hook now disposes the model-preview controller when th | Status: reviewed |
| `@chestnutlabs/gcode-renderer-three` | 4 | Fix `capture()` returning too-dark (linear colour-space) pixels. The interactive capture path rendered into a render target without sRGB out | Status: reviewed |

Set each **Disposition** to one of `Status: reviewed` / `Status: no-change-needed` /
`Status: not-applicable` (never `Status: pending`).

## Global dispositions

- **Product review:** resolved — README / Pages homepage / feature gallery still describe the product accurately for this release.
- **Docs review:** resolved — manual, package READMEs, examples, and quick-start match the shipped API.
- **Visual review:** resolved — every changed user-facing capability is visually documented, or the coverage matrix records why not.
- **Product review:** resolved — v0.20.1 is a correctness patch with **no API or product-surface change**. README / Pages homepage / feature gallery remain accurate; the `docs/README.md` "Current state" now leads with the v0.20.1 patch and its five fixes.
- **Docs review:** resolved — no public API changed, so the manual, package READMEs, examples, and quick-start still match the shipped API. Each fix carries a changeset → per-package CHANGELOG entry, and the deferred/related findings are tracked in issues #430–#435.
- **Visual review:** resolved — no UI/visual change. The app-UI screenshots and capability renders still show the current UI (the demo screenshot harness copies the live sRGB-correct canvas, so it was never affected by the `capture()` colour-space bug this patch fixes), and the live demos build/run on the published SDK. The `capture()` fix is verified in-browser (a `#6d7176` scene round-trips through `capture()` as `#6d7176`, not the previous linear `#272a2e`).

_Resolve each marker above by replacing `pending` with `resolved` once reconciled._

## Reconciliation notes (v0.20.0)

All seven changed packages are the DD-031 consumer-UX / framework-parity pass, reconciled together:

- **Product:** the whole point of this release is consumer-facing surface. `docs/README.md`
"Current state" leads with v0.20.0; the two-viewer (Preview + Prepare) story is accurate. The root
README and Pages homepage remain accurate (they describe the toolpath viewer + source-model
rendering; the new framework model adapters are additive API documented in the canonical adapter
docs). No existing product copy misrepresents the shipped software.
- **Docs:** `docs/manual/adapters.md` gained "Two viewers: Preview and Prepare" + a per-framework
import table; all four adapter READMEs gained a "Model viewing (Prepare side)" section; the
`gcode-model-renderer` README documents `createModelPreviewController` + the `/testing` suite;
`CLAUDE.md`'s parity check now covers both viewer surfaces. `npm run docs:links` passes.
- **Visual:** the interactive model viewer is now demonstrated in the Feature Lab + all four
showcases (Preview/Prepare toggle) and a minimal model page per framework; the coverage matrix
(`docs/VISUAL_FEATURE_COVERAGE.md` §6/§10) records this. Dark **app-UI** screenshots of Prepare
mode were captured for review but are **not yet canonical `docs/media`** — the manifest harness
emits the mid-grey capability presentation, not app chrome; that gap is explicitly recorded and
carried to the next Visual Review. No shipped capability's existing media is now stale.
- **Framework parity:** every new controller/model capability is exposed across Vue, React, Svelte,
and the Web Component (declaratively where it belongs; the `<gcode-model-viewer>` tag and the
`/model` subpath are documented intentional differences), exercised by the portable behavioral
suites with controls/state completeness parity guards for both the toolpath and model surfaces.
_All markers resolved: this patch changes behaviour (bug fixes) with no product/docs/visual surface change; the capture colour fix was validated in a real browser._
Loading
Loading