# Snapshot Generation and Visual Validation Workflows for CAD in text-to-cad

> Generate PNG/GIF snapshots from implicit CAD definitions using the text-to-cad pipeline. Automate visual validation with regression tests for robust CAD development.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: how-to-guide
- Published: 2026-08-03

---

**The text-to-cad repository provides a complete pipeline for generating PNG/GIF snapshots from implicit CAD definitions and validating them through automated visual regression tests.**

This open-source toolset enables both programmatic image generation and human review of CAD outputs. The system combines a headless Chromium rendering engine, a CLI wrapper for command-line workflows, and comprehensive test suites that ensure visual fidelity across releases.

## Core Snapshot Engine Architecture

The rendering pipeline is organized into three layers: the **snapshot engine** handles low-level rendering, the **CLI wrapper** exposes user-friendly commands, and the **visual validation tests** enforce correctness. This separation allows the system to serve both automated agents (CI pipelines, downstream ML models) and interactive designers.

### Snapshot Options and Rendering ([`snapshot.js`](https://github.com/earthtojake/text-to-cad/blob/main/snapshot.js))

The core logic resides in [`viewer/packages/implicitjs/src/lib/implicitCad/snapshot.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/src/lib/implicitCad/snapshot.js). This module normalizes rendering parameters and orchestrates the headless browser execution.

Key functions include:

- **`snapshotImplicitCadOutputOptions`** — Merges job-level and output-level configurations, applying defaults for dimensions, camera position, appearance themes, and graphics quality ([source](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/src/lib/implicitCad/snapshot.js#L23-L44))
- **`snapshotImplicitCadModel`** — Executes the render with merged options, returning path, dimensions, MIME type, and PNG data-URL ([source](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/src/lib/implicitCad/snapshot.js#L46-L65))
- **`snapshotImplicitCadModelToDataUrl`** — Convenience wrapper returning only the data-URL string ([source](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/src/lib/implicitCad/snapshot.js#L67-L70))

The engine uses **Playwright** to launch Chromium, load a minimal HTML page ([`snapshot-runtime/render.html`](https://github.com/earthtojake/text-to-cad/blob/main/snapshot-runtime/render.html)), execute the implicit CAD module, and capture canvas output.

## CLI Wrapper for Snapshot Generation

The command-line interface in `viewer/packages/implicitjs/scripts/snapshot.mjs` transforms user-friendly flags into structured render jobs.

### Key CLI Components

| Component | Responsibility | Source Location |
|-----------|---------------|----------------|
| `helpText()` | Documents all flags and usage patterns | [L71-L79](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/scripts/snapshot.mjs#L71-L79) |
| `parseSnapshotArgs()` | Parses `process.argv`, validates inputs, applies defaults | [L25-L100](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/scripts/snapshot.mjs#L25-L100) |
| `withSnapshotTimeout()` | Enforces configurable render timeouts to prevent hung processes | [L701-L708](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/scripts/snapshot.mjs#L701-L708) |

### Command-Line Examples

Generate a static PNG with explicit camera and dimensions:

```bash
node viewer/packages/implicitjs/scripts/snapshot.mjs \
  --input models/implicit-cad/gear.implicit.js \
  --output snapshots/gear.png \
  --camera iso \
  --width 1600 --height 1200 \
  --appearance workbench

```

Generate an animated orbit GIF (mode defaults automatically for `.gif` extension):

```bash
node viewer/packages/implicitjs/scripts/snapshot.mjs \
  --input models/implicit-cad/gear.implicit.js \
  --output snapshots/gear-orbit.gif

```

The CLI automatically appends UTC timestamps to output filenames (e.g., `gear_20260527T163012Z.png`) unless a complete filename is specified.

## Visual Validation Test Suite

The repository includes rigorous Jest-style tests in `viewer/packages/implicitjs/scripts/snapshot.test.mjs` that verify snapshot generation correctness. These tests exercise:

- CLI flag-to-job transformation
- Camera JSON parsing
- Timestamped output naming conventions
- Multi-output packet handling
- Animation mode defaults (`orbit` / `animate`)

### Multi-Output Validation Test

This test confirms that a single render job can produce multiple view snapshots with correct timestamp suffixes:

```js
test("render job packet supports multi-output review snapshots", () => withTempImplicitModel(({ root }) => {
  const packet = resolveRenderJobPacket({
    input: "models/implicit-cad/orb.implicit.js",
    render: { frameMargin: 1.55 },
    outputs: [
      { path: "tmp/orb-iso.png",  camera: "iso"   },
      { path: "tmp/orb-front.png", camera: "front", width: 900, height: 700 },
      { path: "tmp/orb-top.png",   camera: "top"   },
    ],
  }, { cwd: root, timestamp: "20260527T163012Z" });

  const job = packet.jobs[0];
  assert.deepEqual(
    job.outputs.map(o => path.basename(o.path)),
    ["orb-iso_20260527T163012Z.png", "orb-front_20260527T163012Z.png", "orb-top_20260527T163012Z.png"]
  );
}));

```

[Full test source](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/scripts/snapshot.test.mjs#L31-L66)

## Runtime Perspective Snapshots for Validation

The CAD viewer runtime in [`viewer/src/client/components/ImplicitCadViewer.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/ImplicitCadViewer.js) supports **deterministic visual regression testing** through camera state capture and replay.

### Capturing Perspective State

```js
function perspectiveSnapshot(runtime, modelKey = "") {
  if (!runtime?.camera || !runtime?.controls) return null;
  const { camera, controls } = runtime;
  return {
    implicit: true,
    cameraVersion: IMPLICIT_CAMERA_VERSION,
    modelKey: String(modelKey),
    position: [camera.position.x, camera.position.y, camera.position.z],
    target:   [controls.target.x, controls.target.y, controls.target.z],
    up:       [camera.up.x, camera.up.y, camera.up.z],
    fov:      camera.fov,
  };
}

```

[Source: L57-L66](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/ImplicitCadViewer.js#L57-L66)

### Reapplying Captured State

```js
function applyPerspectiveSnapshot(runtime, perspective, modelKey = "") {
  if (!runtime?.camera || !runtime?.controls || !perspective?.implicit) return false;
  // Sets position, target, up vector, FOV, then requests render
}

```

[Source: L74-L92](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/ImplicitCadViewer.js#L74-L92)

These helpers enable **reproducible camera angles** across sessions—critical for comparing renders before and after code changes. Unit tests in [`packages/cadjs/src/common/perspective.test.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/perspective.test.js) verify round-trip fidelity.

## Programmatic Snapshot Generation

For integration into Node.js applications or ML pipelines:

```javascript
import { snapshotImplicitCadModel } from
  "viewer/packages/implicitjs/src/lib/implicitCad/snapshot.js";
import * as THREE from "three";

// Load implicit CAD module
const model = await import("./models/implicit-cad/gear.implicit.js");

// Generate snapshot
const result = await snapshotImplicitCadModel(THREE, model.default, {
  width: 1200,
  height: 900,
  camera: "front",
  appearance: "workbench",
});

// Extract and save PNG
const base64 = result.dataUrl.split(",")[1];
require("fs").writeFileSync(
  `snapshots/${result.path}`,
  Buffer.from(base64, "base64")
);

```

[Reference implementation](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/src/lib/implicitCad/snapshot.js#L46-L65)

## CI/CD Visual Regression Workflow

A typical continuous integration setup:

1. Run `snapshot.mjs` against golden model files
2. Compare generated outputs against reference images or checksums
3. Fail builds on pixel divergence exceeding threshold

The existing test suite in `snapshot.test.mjs` demonstrates this pattern. Adding new validation cases requires only extending the `resolveRenderJobPacket` calls with new model paths.

## Summary

- **Snapshot generation** is handled by [`snapshot.js`](https://github.com/earthtojake/text-to-cad/blob/main/snapshot.js) with configurable dimensions, cameras, and appearance themes
- **CLI access** via `snapshot.mjs` supports PNG/GIF output with automatic timestamping
- **Visual validation** tests verify job construction, multi-output handling, and naming conventions
- **Perspective snapshots** enable deterministic camera reproduction for regression testing
- **Programmatic API** allows integration into ML pipelines and automated workflows

## Frequently Asked Questions

### How does text-to-cad handle rendering timeouts?

The `withSnapshotTimeout()` utility in the CLI wrapper enforces a configurable duration for Chromium renders. If the snapshot exceeds this limit, the process surfaces a clear error rather than hanging indefinitely [L701-L708](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/implicitjs/scripts/snapshot.mjs#L701-L708).

### What camera options are available for CAD snapshots?

The system accepts preset strings (`iso`, `front`, `top`, etc.) or full JSON camera objects specifying position, target, up vector, and field of view. The `parseSnapshotArgs()` function normalizes both formats into the internal camera representation used by the rendering engine.

### Can I generate multiple views from a single CAD model?

Yes. The `outputs` array in a render job packet supports multiple camera angles and dimensions. The CLI's `--output` flag can be invoked repeatedly, or the programmatic API accepts an array of output specifications—each receiving independent timestamped filenames.

### How does perspective snapshot validation ensure visual consistency?

The `perspectiveSnapshot` and `applyPerspectiveSnapshot` functions in [`ImplicitCadViewer.js`](https://github.com/earthtojake/text-to-cad/blob/main/ImplicitCadViewer.js) serialize complete camera state including position, target, up vector, and FOV. Unit tests in [`perspective.test.js`](https://github.com/earthtojake/text-to-cad/blob/main/perspective.test.js) verify that captured states restore identical viewpoints, enabling pixel-perfect comparison across code versions.