How to Parameterize STEP Models with .step.js Sidecar Modules

In the earthtojake/text-to-cad repository, you parameterize STEP geometry by creating a JavaScript sidecar module named .<stem>.step.js that exports a manifest defining UI controls bound to specific feature IDs in the STEP file, enabling interactive manipulation without regenerating the underlying CAD artifact.

The text-to-cad project introduces a robust pattern for converting static STEP files into dynamic, interactive components. By pairing each *.step or *.stp geometry file with a .step.js sidecar module, you maintain a clean separation between immutable geometry artifacts and live presentation logic. This architecture allows the CAD Viewer to load geometry once while providing real-time controls for parameters like gear ratios or joint angles, all validated through a standardized manifest schema.

Understanding the Sidecar Architecture

The sidecar pattern relies on specific file naming conventions and a strict manifest contract to bridge static CAD data with interactive JavaScript controls.

Sidecar Naming Convention

A sidecar module must follow the pattern .<stem>.step.js, where <stem> matches the STEP file name exactly. For example, gearbox.step pairs with .gearbox.step.js. The helper function isInlineStepParameterPath in packages/cadjs/src/common/stepSidecars.mjs validates this naming convention, ensuring the viewer can automatically associate sidecars with their geometry sources.

Path Resolution Utilities

The stepSidecars.mjs file provides stepParameterPathForStepSource(sourcePath) to compute the sidecar path from any STEP source path. This utility guarantees consistent path resolution across the workspace, handling the dot-prefix naming automatically.

Manifest Contract Requirements

Every sidecar must export a default object containing a manifest key. The manifest must specify schemaVersion: 1 (currently the only supported version) and include a step block pointing to the STEP file path relative to the workspace root. According to skills/cad/references/parameters.md, the manifest.step.path value should contain no leading slashes or parent directory references.

Parameter Definitions and Feature Binding

Inside the manifest, you define UI controls using the parameters array. Each parameter requires id, type (such as "number" or "select"), label, and binding to a geometry feature via featureId. Feature IDs use stable references like #gear_pair that must exist in the STEP file metadata. The repository enforces snake_case naming conventions for parameter IDs to maintain consistency across the codebase.

Viewer Integration

The CAD Viewer scans model directories using cadDirectoryScanner.mjs located in viewer/src/server/catalog/. The scanner calls isInlineStepParameterPath to identify sidecars and serves them under URLs like /models/<folder>/.<stem>.step.js?v=<hash>. The viewer dynamically imports these modules and instantiates controls based on the exported manifest.

Animation Support

Sidecars may expose a durationSeconds field at the manifest root level. When present, the viewer renders an animation timeline with playback controls. Animation-specific parameters, such as normalized travel values, can reference geometry features just like static parameters, allowing smooth interpolation without STEP regeneration.

Creating Your First .step.js Sidecar Module

Place your sidecar file in the same directory as its corresponding STEP file, using the dot-prefix naming convention.

Minimal Parameterized Sidecar

The following example creates a single slider controlling gear ratio:

// models/mechanisms/.gearbox.step.js
export default {
  manifest: {
    schemaVersion: 1,
    step: {
      // Workspace-relative path to the STEP geometry
      path: "models/mechanisms/gearbox.step"
    },
    // UI controls – one slider controlling the gear ratio
    parameters: [
      {
        id: "gear_ratio",
        type: "number",
        label: "Gear Ratio",
        unit: "",
        default: 2,
        min: 1,
        max: 10,
        step: 0.1,
        // Reference to the feature that will be transformed
        featureId: "#gear_pair"
      }
    ]
  }
};

Key implementation details:

  • The filename .gearbox.step.js matches the gearbox.step source exactly.
  • manifest.step.path uses a workspace-relative path without leading / or .. segments.
  • The featureId #gear_pair must correspond to a feature identifier embedded in the STEP file metadata.

Animation-Enabled Sidecar

Add durationSeconds to enable timeline controls:

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

The viewer automatically generates play/pause and scrubber controls when durationSeconds is present, interpolating the joint_travel parameter over the specified interval.

Accessing Sidecars Programmatically

You can inspect sidecar manifests from Python skills by evaluating the JavaScript module and extracting the JSON structure:

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 module and extract the manifest

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

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

This approach leverages Node.js to parse the ECMAScript module syntax, making the manifest data available to Python-based automation scripts or build pipelines.

Summary

  • Create sidecars using the naming pattern .<stem>.step.js adjacent to your *.step files.
  • Export a manifest with schemaVersion: 1, a workspace-relative step.path, and a parameters array defining UI controls.
  • Bind parameters to geometry using featureId references that match IDs embedded in the STEP file metadata.
  • Enable animations by adding durationSeconds to the manifest root, which triggers the viewer's timeline interface.
  • Discover sidecars automatically through the isInlineStepParameterPath predicate used by the viewer's directory scanner.

Frequently Asked Questions

What is the exact file naming convention for sidecar modules?

Sidecar files must use the pattern .<stem>.step.js where <stem> is identical to the STEP filename without extension. For housing.step, the sidecar must be .housing.step.js. The leading dot hides the file in standard directory listings while the viewer's stepParameterPathForStepSource function in packages/cadjs/src/common/stepSidecars.mjs computes these paths automatically.

How do I reference specific geometry features in the STEP file?

Use the featureId field in your parameter definition with a hash-prefixed identifier like #mounting_hole or #drive_shaft. These IDs must be embedded in the STEP file's metadata during export from your CAD generator (such as build123d). The viewer uses these stable references to apply transformations without modifying the underlying STEP geometry.

Can I animate a model without regenerating the STEP file?

Yes. Include durationSeconds in your manifest root to enable the animation timeline. Define parameters with ranges that represent your animation states (e.g., 0 to 1 for normalized travel). The viewer interpolates between these values client-side, moving or deforming the loaded geometry without calling back to the STEP generator.

How does the CAD Viewer discover sidecar modules automatically?

The viewer uses cadDirectoryScanner.mjs to scan model directories, calling isInlineStepParameterPath from stepSidecars.mjs to identify files matching the sidecar naming pattern. Valid sidecars are served with versioned URLs (?v=<hash>) and dynamically imported in the browser, where the manifest schema is validated before rendering controls.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →