> ## Documentation Index
> Fetch the complete documentation index at: https://invariant-cad.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Author, evaluate, inspect, and export a parameterized mounting plate.

This walkthrough builds a plate with a parameterized rectangular outline and a
circular hole. The same immutable document is evaluated first with the default
Manifold backend for STL and then with stock OCCT for exact STEP export.

## Run the complete workflow

```ts theme={"system"}
import {
  EvaluatedSolid,
  createEvaluator,
  design,
  mm,
  plane,
  vec2,
} from "invariantcad";
import { createOcctKernel } from "invariantcad/kernels/occt";

const cad = design("mounting-plate", {
  metadata: { description: "Parameterized plate with one mounting hole" },
});

const width = cad.parameter.length("width", mm(80), {
  min: mm(20),
  max: mm(200),
  description: "Overall plate width",
});
const height = cad.parameter.length("height", mm(50), { min: mm(10) });
const thickness = cad.parameter.length("thickness", mm(6), { min: mm(1) });
const holeRadius = cad.parameter.length("holeRadius", mm(4), { min: mm(1) });

const profile = cad.sketch("plate-profile", plane.xy(), (sketch) => {
  const outline = sketch.rectangle("outline", { width, height });
  const hole = sketch.circle("hole", {
    center: vec2(width.mul(0.25), mm(0)),
    radius: holeRadius,
  });
  return sketch.profile(outline, { holes: [hole.loop()] });
});

const solid = cad.extrude("plate-solid", profile, {
  distance: thickness,
  symmetric: true,
});
const part = cad.part("plate", solid, {
  partNumber: "PLATE-001",
  description: "Machined mounting plate",
});
cad.output("plate", part);

const document = cad.build();
const parameters = {
  width: 100,
  holeRadius: 5,
};

async function evaluateDefaultMesh() {
  const evaluator = await createEvaluator();
  try {
    const result = await evaluator.evaluate(document, {
      parameters,
      outputs: ["plate"],
    });
    if (!result.ok) {
      throw new Error(
        result.diagnostics.map((item) => item.message).join("\n"),
      );
    }

    try {
      const plate = result.value.output("plate");
      if (!(plate instanceof EvaluatedSolid)) {
        throw new Error("Expected the 'plate' output to be a solid part");
      }
      return {
        volume: plate.measure().volume,
        stl: plate.export("stl"),
      };
    } finally {
      result.value.dispose();
    }
  } finally {
    evaluator.dispose();
  }
}

async function exportExactStep() {
  const kernel = await createOcctKernel();
  let evaluatorOwnsKernel = false;
  try {
    const evaluator = await createEvaluator({ kernel });
    evaluatorOwnsKernel = true;
    try {
      const result = await evaluator.evaluate(document, {
        parameters,
        outputs: ["plate"],
      });
      if (!result.ok) {
        throw new Error(
          result.diagnostics.map((item) => item.message).join("\n"),
        );
      }

      try {
        const plate = result.value.output("plate");
        if (!(plate instanceof EvaluatedSolid)) {
          throw new Error("Expected the 'plate' output to be a solid part");
        }
        return {
          volume: plate.measure().volume,
          step: plate.export("step"),
        };
      } finally {
        result.value.dispose();
      }
    } finally {
      evaluator.dispose();
    }
  } finally {
    // A rejected caller-supplied kernel remains caller-owned.
    if (!evaluatorOwnsKernel) kernel.dispose();
  }
}

const defaultMesh = await evaluateDefaultMesh();
const exact = await exportExactStep();

export const mountingPlateSummary = {
  defaultVolume: defaultMesh.volume,
  defaultStlBytes: defaultMesh.stl.byteLength,
  exactVolume: exact.volume,
  stepBytes: exact.step.byteLength,
  stepHeader: new TextDecoder().decode(exact.step.subarray(0, 32)),
};
console.log(mountingPlateSummary);
```

The example is a complete executable module. `build()` returns a deeply frozen
current-version document; builder references such as `profile`, `solid`, and
`part` never enter the serialized data.

Parameter override numbers use base units: millimetres for length, radians for
angle, unitless scalar values, and kilograms per cubic millimetre for mass
density.

## Understand the ownership boundary

Each successful `evaluate()` call owns every native shape created for that
evaluation, so its `EvaluatedDesign` is disposed in a `finally` block. Each
evaluator is also disposed in `finally`.

The exact path has one additional edge: `createOcctKernel()` returns a
caller-owned kernel, while a successfully created evaluator adopts it. If
`createEvaluator({ kernel })` rejects before that transfer, the caller still
disposes the kernel. The example's `evaluatorOwnsKernel` guard covers both
paths without relying on a partially created evaluator.

Exports are detached JavaScript values. The returned STL and STEP
`Uint8Array`s remain usable after their evaluated designs and evaluators have
been disposed.

## Save the results

The runtime example deliberately performs no filesystem writes. A Node.js
application can persist its detached values:

```ts theme={"system"}
import { writeFile } from "node:fs/promises";
import { stringifyDocument } from "invariantcad";

await writeFile(
  "mounting-plate.invariantcad.json",
  stringifyDocument(document, { pretty: true }),
);
await writeFile("mounting-plate.stl", defaultMesh.stl);
await writeFile("mounting-plate.step", exact.step);
```

`stringifyDocument()` canonicalizes values according to the document protocol.
Use `parseDocument()` when loading untrusted text; do not cast parsed JSON to a
`DesignDocument`.

Read [kernels](/evaluation/kernels) before assuming every feature or topology
history guarantee is identical between Manifold, stock OCCT, and the optional
owned facade.

## What to learn next

<CardGroup cols={2}>
  <Card title="Expressions and parameters" icon="variable" href="/modeling/parameters-and-expressions">
    Build dimension-safe formulas and understand evaluation overrides.
  </Card>

  <Card title="Sketches and constraints" icon="pen-tool" href="/modeling/sketches-and-constraints">
    Author reusable profiles with explicit loops and holes.
  </Card>

  <Card title="Assemblies and BOMs" icon="boxes" href="/modeling/assemblies">
    Define reusable parts, nested occurrences, materials, and quantities.
  </Card>

  <Card title="Diagnostics" icon="triangle-alert" href="/evaluation/diagnostics-and-limits">
    Handle structured failures, cancellation, and resource limits.
  </Card>
</CardGroup>
