# How to Parameterize STEP Models with .step.js Sidecar Modules in text-to-cad

> Learn to parameterize STEP models using .step.js sidecar modules in text-to-cad. Add UI controls and animations to your CAD without regeneration.

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

---

**Create a hidden JavaScript sidecar file next to your STEP geometry to add interactive UI controls, animations, and parameter-driven features without regenerating the underlying CAD model.**

The *text-to-cad* repository supports **[`.step.js`](https://github.com/earthtojake/text-to-cad/blob/main/.step.js) sidecar modules**—JavaScript files that live alongside STEP geometry files and export declarative manifests describing how the geometry should behave in the CAD Viewer. This pattern lets you transform static STEP artifacts into live, configurable components while keeping geometry and logic cleanly separated.

---

## What Is a .step.js Sidecar Module?

A sidecar module is a JavaScript file that pairs with a STEP file using a strict naming convention. The sidecar contains no geometry itself; instead, it exports a **manifest object** that tells the viewer:

- Where to find the STEP file
- What UI controls to render (sliders, toggles, selects)
- Which geometric features those controls manipulate
- Optional animation timing and keyframes

The viewer loads the STEP once, then applies parameter changes dynamically through the sidecar—no re-export required.

---

## Sidecar Naming and Discovery

Sidecars must follow a dot-prefix naming pattern to be automatically detected.

### Naming Convention

| STEP File | Sidecar File |
|-----------|--------------|
| `gearbox.step` | [`.gearbox.step.js`](https://github.com/earthtojake/text-to-cad/blob/main/.gearbox.step.js) |
| `robot_arm.stp` | [`.robot_arm.step.js`](https://github.com/earthtojake/text-to-cad/blob/main/.robot_arm.step.js) |

The stem must match exactly. The leading dot makes the file hidden on Unix systems, keeping your model directories clean.

### Discovery Implementation

In `packages/cadjs/src/common/stepSidecars.mjs`, the helper `isInlineStepParameterPath` validates sidecar paths:

```javascript
// stepSidecars.mjs lines 13-16
export function isInlineStepParameterPath(path) {
  const basename = path.split('/').pop();
  return basename.startsWith('.') && basename.endsWith('.step.js');
}

```

To compute a sidecar path from a STEP source, use `stepParameterPathForStepSource`:

```javascript
// stepSidecars.mjs lines 40-43
export function stepParameterPathForStepSource(sourcePath) {
  const dir = dirname(sourcePath);
  const base = basename(sourcePath);
  const stem = base.replace(/\.(step|stp)$/i, '');
  return join(dir, `.${stem}.step.js`);
}

```

The viewer's directory scanner (`viewer/src/server/catalog/cadDirectoryScanner.mjs`) uses these helpers to find and serve sidecars at runtime URLs like `/models/<folder>/.<stem>.step.js?v=<hash>`.

---

## The Manifest Contract

Every sidecar must export a default object with a `manifest` key. The manifest structure is versioned and strictly validated.

### Required Fields

| Field | Type | Description |
|-------|------|-------------|
| `manifest.schemaVersion` | `number` | Always `1` in current versions |
| `manifest.step.path` | `string` | Workspace-relative path to the STEP file |
| `manifest.parameters` | `array` | UI control definitions |

### Parameter Definition Schema

Each parameter in the `parameters` array needs:

- `id` – snake_case identifier used in code
- `type` – `"number"`, `"boolean"`, or `"select"`
- `label` – Human-readable display name
- `default` – Initial value
- `featureId` – Stable reference to a STEP feature (prefixed with `#`)

Optional fields include `min`, `max`, `step`, and `unit` for numeric controls.

---

## Minimal Sidecar Example

Create [`.gearbox.step.js`](https://github.com/earthtojake/text-to-cad/blob/main/.gearbox.step.js) next to `gearbox.step`:

```javascript
// models/mechanisms/.gearbox.step.js
export default {
  manifest: {
    schemaVersion: 1,
    step: {
      path: "models/mechanisms/gearbox.step"
    },
    parameters: [
      {
        id: "gear_ratio",
        type: "number",
        label: "Gear Ratio",
        default: 2,
        min: 1,
        max: 10,
        step: 0.1,
        featureId: "#gear_pair"
      }
    ]
  }
};

```

**Critical details:**
- `path` is **workspace-relative**—no leading slash or `..` segments
- `featureId` references a feature that must exist in the STEP metadata
- The filename [`.gearbox.step.js`](https://github.com/earthtojake/text-to-cad/blob/main/.gearbox.step.js) matches `gearbox.step` exactly

---

## Animation-Enabled Sidecars

Add `durationSeconds` to enable timeline controls in the viewer:

```javascript
// models/robots/.arm.step.js
export default {
  manifest: {
    schemaVersion: 1,
    step: { path: "models/robots/arm.step" },
    durationSeconds: 4,
    parameters: [
      {
        id: "joint_travel",
        type: "number",
        label: "Elbow Travel",
        unit: "deg",
        default: 0,
        min: -90,
        max: 90,
        step: 1,
        featureId: "#elbow_joint"
      }
    ]
  }
};

```

When `durationSeconds` is present, the viewer renders a playback bar with play/pause and scrub functionality. Parameters can be keyed to animation time or remain as manual overrides.

---

## Accessing Sidecar Manifests Programmatically

Python skills in the repository can consume sidecars by evaluating them through Node.js:

```python
from pathlib import Path
import json
import subprocess

def load_step_manifest(step_path: Path):
    sidecar_path = step_path.with_name(f".{step_path.stem}.step.js")
    if not sidecar_path.is_file():
        raise FileNotFoundError(f"No sidecar for {step_path}")
    
    # Evaluate the JS module and extract the manifest

    result = subprocess.check_output([
        "node", "-e",
        f"import('{sidecar_path}').then(m=>console.log(JSON.stringify(m.default.manifest)))"
    ], text=True)
    
    return json.loads(result)

# Usage

manifest = load_step_manifest(Path("models/mechanisms/gearbox.step"))
print(manifest["parameters"][0]["id"])  # → "gear_ratio"

```

Production skills use the `snapshot` pipeline rather than direct subprocess calls, but the evaluation pattern remains: import the module, access `default.manifest`, and operate on the resulting JSON.

---

## Parameter Naming Conventions

Per [`skills/cad/references/parameters.md`](https://github.com/earthtojake/text-to-cad/blob/main/skills/cad/references/parameters.md), follow these rules for maintainable sidecars:

- Use **snake_case** for all parameter IDs
- Prefix related parameters with a common noun (`motor_speed`, `motor_torque`)
- Keep IDs stable—changing them breaks saved configurations
- Document physical units explicitly in the `unit` field

Feature IDs in `manifest.features` (referenced by `featureId`) should use descriptive names tied to the CAD model's semantic structure.

---

## Summary

- **Sidecar files** use the pattern `.<stem>.step.js` and live adjacent to their STEP geometry
- **Discovery helpers** in `stepSidecars.mjs` power automatic detection by the viewer
- **Manifest schema** requires `schemaVersion: 1`, a workspace-relative `step.path`, and parameter definitions
- **Animation support** activates when `durationSeconds` is present in the manifest
- **Zero regeneration**—the viewer manipulates loaded geometry rather than re-exporting CAD

---

## Frequently Asked Questions

### What happens if I rename my STEP file?

You must rename the sidecar to match. The viewer uses `stepParameterPathForStepSource` to compute the expected sidecar name, and `isInlineStepParameterPath` will reject files that don't follow the dot-prefix convention. Mismatched pairs are ignored during directory scanning.

### Can a single STEP file have multiple sidecars?

No. The one-to-one naming convention enforces a single sidecar per STEP file. For alternative configurations, create separate model directories or use conditional logic within one sidecar's manifest.

### How do I reference features that don't exist yet in my STEP?

Feature IDs must be stable identifiers embedded in the STEP metadata during generation. If using *build123d* or similar tools, assign explicit labels to geometric entities; these become the `#`-prefixed feature IDs available to sidecar parameters.

### Does the sidecar support TypeScript?

The current implementation expects JavaScript modules. TypeScript sidecars would require a build step or on-the-fly transpilation, which the viewer's dynamic import loader does not currently perform. Write plain JavaScript with JSDoc comments for type hints if needed.