npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vessel-dsp/stompbox

v0.6.14

Published

Headless stompbox drill-layout and preview manifests for VesselDSP .vdsp documents.

Downloads

1,497

Readme

@vessel-dsp/stompbox

Headless stompbox drill-layout and preview manifest helpers for .vdsp documents parsed by @vessel-dsp/core.

This package does not render UI. It emits headless artifacts that downstream tools can display or save:

  • drill-layout manifests;
  • drill-template SVG strings in preview and A4 print modes;
  • mesh-backed stompbox preview GLB bytes assembled from caller-provided CAD part GLBs and STEP companions via hardwareProfile plus basePath;
  • orthographic preview SVG views for top, bottom, left, right, and back;
  • optional text, SVG, or image decals for brand/model/custom sticker artwork;
  • headless pedal state, interaction, and preview-patch helpers for live stompbox previews.

Applications own production part profiles, enclosure profiles, and asset roots. Keep named style presets in your application or docs layer and pass them through styleProfile when you want preset-specific default parts or placement rules. When a .vdsp document already contains mechanical.enclosure, partProfiles, and panel physical.partProfileId data, use createStompboxHardwareProfileFromVdsp() to derive a generated-stub hardware profile for drill layout and SVG preview workflows. Production CAD-quality GLB assembly still needs an application-provided hardware profile or asset overrides because portable .vdsp part profiles do not carry full GLB target metadata.

Drill-template holes are fabrication holes: their circle diameters come from each part profile's panel drill clearance, such as the PJ-629HAN 9.5 mm drill and the DC099 8 mm barrel opening. Preview views and collision checks may use larger visible exterior geometry, such as jack rings, bushings, nuts, and bezels.

When .vdsp physical placement is present, stompbox preserves it as vdsp-declared. When placement or common enclosure hardware is absent, stompbox generates deterministic auto-generated placements for knobs, status LED, bypass footswitch, input/output jacks, and the 9V connector. Set includePowerJack: false to omit the synthesized 9V connector.

Pass decals to preview or drill-template helpers to place custom text, SVG, or image artwork on the enclosure. Preview SVG views render the decal content on the box, preview GLB output includes decal plane nodes with sticker metadata, drill template preview mode shows decal outlines, and A4 print mode places the decals in a separate sticker sheet area.

Decals can target the top, left, right, back, or bottom plane. Use placement: { kind: "grid" } when the sticker should snap to the center of a face grid cell. The grid uses the requested columns and rows, capped so each cell remains at least 12 mm wide or tall. For example, a 40 mm wide face can address at most 3 columns.

const decals = [
  {
    id: "brand-label",
    kind: "text",
    text: "FUZZ LAB",
    face: "top",
    color: "#2563eb",
    fontFamily: '"Roboto", sans-serif',
    placement: { kind: "grid", columns: 4, rows: 4, column: 4, row: 2 },
    sizeMm: { widthMm: 28, heightMm: 7 },
  },
  {
    id: "side-vector",
    kind: "svg",
    face: "left",
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"><path d="M1 5 H9" stroke="currentColor"/></svg>',
    color: "#ef4444",
    placement: { kind: "grid", columns: 2, rows: 4, column: 2, row: 3 },
    sizeMm: { widthMm: 10, heightMm: 8 },
  },
  {
    id: "back-image",
    kind: "image",
    face: "back",
    href: "/artwork/sticker.png",
    placement: { kind: "grid", columns: 4, rows: 1, column: 4, row: 1 },
    sizeMm: { widthMm: 16, heightMm: 8 },
  },
] as const;

Helper map

Use FromVdsp helpers when the caller has serialized .vdsp text. Use the document helpers when the caller has already parsed or edited a CircuitDocument.

| Need | .vdsp helper | CircuitDocument helper | | --- | --- | --- | | Drill hole coordinates and diagnostics | createStompboxDrillLayoutFromVdsp | createStompboxDrillLayout | | Drill-template manifest | createStompboxDrillTemplateFromVdsp | createStompboxDrillTemplate | | Drill-template SVG string | createStompboxDrillTemplateSvgFromVdsp | createStompboxDrillTemplateSvg | | Preview manifest | createStompboxPreviewFromVdsp | createStompboxPreview | | Orthographic 2D SVG views | createStompboxPreviewSvgViewsFromVdsp | createStompboxPreviewSvgViews | | Mesh-backed 3D GLB bytes | createStompboxPreviewGlbFromVdsp | createStompboxPreviewGlb | | Generated-stub hardware profile from .vdsp metadata | createStompboxHardwareProfileFromVdsp | createStompboxHardwareProfileFromDocument | | Frontend recolor patch | createStompboxAppearancePatch | createStompboxAppearancePatch | | Resolved appearance alias | resolveStompboxAppearance | resolveStompboxAppearance | | Source/compiled control surface | parseCircuitDocumentFile then createStompboxControlSurface | createStompboxControlSurface | | Default live pedal state | createDefaultStompboxPedalStateFromVdsp | createDefaultStompboxPedalState | | Headless live state store | createStompboxPedalStateStore | createStompboxPedalStateStore | | Preview state patch | createStompboxPreviewStatePatch | createStompboxPreviewStatePatch |

Generated docs examples are published at:

  • 2D preview SVG: /core/examples/stompbox-mxr-style-preview-top.svg
  • 3D preview GLB: /core/examples/stompbox-mxr-style-preview.glb
  • Drill-template preview SVG: /core/examples/stompbox-mxr-style-drill-template-preview.svg
  • Drill-layout JSON: /core/examples/stompbox-mxr-style-drill-layout.json

Deriving a hardware profile from .vdsp

If the .vdsp source already declares mechanical metadata, stompbox can derive a minimal hardware profile from it:

import {
  createStompboxDrillLayoutFromVdsp,
  createStompboxHardwareProfileFromVdsp,
} from "@vessel-dsp/stompbox";

const hardwareProfile = createStompboxHardwareProfileFromVdsp(vdspSource, {
  id: "pedal-derived-hardware",
  label: "Pedal derived hardware",
});

const layout = createStompboxDrillLayoutFromVdsp(vdspSource, {
  hardwareProfile,
});

The derived profile maps .vdsp potentiometer/selector, LED, footswitch, audio jack, DC jack, and enclosure part profiles into generated-stub stompbox profiles. Pass defaultPartIds, enclosureAssets, or partAssets when the document needs specific fallback parts or served asset paths.

Providing CAD assets for 3D preview

createStompboxPreviewGlbFromVdsp() and createStompboxPreviewGlb() read GLB files from disk. Put each part and enclosure GLB under an application-owned asset root, reference those files from hardwareProfile, and pass that root as basePath.

import {
  createStompboxPreviewGlbFromVdsp,
  type StompboxHardwareProfile,
} from "@vessel-dsp/stompbox";

const hardwareProfile: StompboxHardwareProfile = {
  id: "my-app-hardware",
  label: "My app hardware",
  defaultEnclosureId: "box-1590b",
  defaultPartIds: {
    knob: "my-knob",
    largeKnob: "my-knob",
    smallKnob: "my-knob",
    led: "my-led",
    footswitch: "my-footswitch",
    audioJack: "my-audio-jack",
    dcJack: "my-dc-jack",
  },
  enclosureProfiles: {
    "box-1590b": {
      variantId: "box-1590b",
      label: "1590B enclosure",
      dimensionsMm: { widthMm: 60.5, lengthMm: 111.5, depthMm: 31 },
      topFace: { usableRectMm: { x: -29.25, y: -54.75, width: 58.5, height: 109.5 } },
      assets: {
        glbRelativePath: "enclosures/1590b.glb",
        stepRelativePath: "enclosures/1590b.step",
      },
    },
  },
  partProfiles: {
    "my-knob": {
      id: "my-knob",
      label: "My knob",
      family: "knob",
      level: "exterior",
      status: "generated-stub",
      panelHoleDrillMm: 7.14375,
      drillHoleProfileId: "sixteen-mm-pot-9-32",
      geometry: { kind: "knob", diameterMm: 20, depthMm: 11, shaftDiameterMm: 6.35 },
      assets: {
        glbRelativePath: "parts/my-knob.glb",
        stepRelativePath: "parts/my-knob.step",
      },
    },
    // Add my-led, my-footswitch, my-audio-jack, and my-dc-jack.
  },
};

const glb = createStompboxPreviewGlbFromVdsp(vdspSource, {
  hardwareProfile,
  basePath: "/absolute/path/to/cad-assets",
});

The example above reads /absolute/path/to/cad-assets/parts/my-knob.glb and /absolute/path/to/cad-assets/enclosures/1590b.glb. Use baseUrl for served preview references; use basePath when assembling a GLB because the files are read from the filesystem.

Live pedal state

Stompbox can manage preview state for a pedal instance without owning the UI or audio runtime. Use the state helpers to rotate knobs, light LEDs, depress footswitches, and drive synthesized bypass hardware in the generated preview.

import {
  createDefaultStompboxPedalStateFromVdsp,
  createStompboxControlSurface,
  createStompboxPedalStateStore,
  createStompboxPreviewFromVdsp,
} from "@vessel-dsp/stompbox";
import { parseCircuitDocumentFile } from "@vessel-dsp/core";

const document = parseCircuitDocumentFile(vdspSource, { filename: "pedal.vdsp" });
const surface = createStompboxControlSurface(document, {
  pedalId: "stage-1",
  compiledControls: runtimeControlsFromYourCompiler,
});
const preview = createStompboxPreviewFromVdsp(vdspSource, { hardwareProfile });
const state = createDefaultStompboxPedalStateFromVdsp(vdspSource, {
  pedalId: "stage-1",
});
const store = createStompboxPedalStateStore(state, { preview });

store.subscribePreviewPatch((patch) => {
  // Apply patch.parts["part-knob-GAIN"], patch.parts["part-led-status"], etc.
  // to your SVG elements or loaded GLB node/material objects.
});

store.turnKnob("GAIN", 0.82);
store.pressFootswitch("switch-bypass", true);

compiledControls is optional. When present, pass a downstream compiler output shaped like { id, sourceComponentId, name, kind, value, min, max, step } plus optional unit, sweep, options, and targets. Stompbox uses it only to merge audio-bound control metadata with .vdsp source-panel order and to return headless runtime command descriptions. It does not compile .vdsp or send worklet messages.

Live GLB previews require semantic state targets on user-provided LED and footswitch part assets. Declare those targets in the part profile so renderers can affect the LED lens and the moving footswitch actuator instead of guessing against the whole part assembly:

const ledPartProfile = {
  // ...
  stateTargets: {
    led: {
      lens: {
        selector: {
          nodeName: "o1.2",
          meshNameIncludes: "5mm_led_lens",
        },
      },
    },
  },
};

const footswitchPartProfile = {
  // ...
  stateTargets: {
    footswitch: {
      actuator: {
        selector: {
          nodeName: "o1.3",
          meshNameIncludes: "plunger",
        },
      },
      travelAxis: "z",
      travelMm: 1.2,
    },
  },
};

Validate caller-provided GLBs before using them for live state:

import {
  validateStompboxGlbAssetFile,
  validateStompboxHardwareProfileAssets,
} from "@vessel-dsp/stompbox";

const ledValidation = validateStompboxGlbAssetFile(
  "/cad/parts/led-bezel-lh5/led.step.glb",
  ledPartProfile,
);

const profileValidation = validateStompboxHardwareProfileAssets(hardwareProfile, {
  basePath: "/cad/parts",
});

Missing or ambiguous live targets produce diagnostics such as missing-state-target-contract, missing-state-target, and ambiguous-state-target. Static drill layouts and static SVG previews can still be generated; live GLB preview code should treat those diagnostics as a signal to avoid whole-part recolor or movement guesses.

For pointer interaction, convert viewer events into state commands, then apply the resulting patch in your renderer:

import {
  applyStompboxPreviewInteraction,
  createStompboxFootswitchPressCommand,
  createStompboxKnobTurnCommand,
  createStompboxPreviewStatePatch,
} from "@vessel-dsp/stompbox";

const knobCommand = createStompboxKnobTurnCommand(surface, {
  controlId: "GAIN",
  position: 0.65,
});
const nextState = applyStompboxPreviewInteraction(store.getSnapshot(), knobCommand);
const patch = createStompboxPreviewStatePatch(preview, nextState, store.getSnapshot());

store.dispatch(knobCommand);
applyPatchToYourViewer(patch);

const bypassCommand = createStompboxFootswitchPressCommand(surface, {
  partId: "switch-bypass",
  pressed: true,
});
store.dispatch(bypassCommand);

Synthesized switch-bypass and led-status follow the pedal-level enabled state. Source-declared knobs, switches, and LEDs follow their ControlState entries. A 9V connector is still generated by default for pedal previews and can be omitted with includePowerJack: false.

React context, hooks, pointer handlers, SVG mutation, Three.js node updates, and audio/worklet routing remain downstream responsibilities. A React app can wrap createStompboxPedalStateStore() with its own context and useSyncExternalStore, but @vessel-dsp/stompbox stays framework-neutral.

2D and 3D preview viewers

For static 2D previews, use createStompboxPreviewSvgViewsFromVdsp() or createStompboxPreviewSvgViews() and display the returned top, bottom, left, right, or back SVG string directly in the consuming app.

For model-backed 2D or interactive 3D previews, keep Three.js in the consuming app. @vessel-dsp/stompbox should only create the preview GLB bytes and metadata; the app can load that GLB, choose a camera, and add viewer-only effects such as CAD-style linework.

import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { createStompboxPreviewGlbFromVdsp } from "@vessel-dsp/stompbox";

const assembly = createStompboxPreviewGlbFromVdsp(vdspSource, {
  hardwareProfile,
  basePath: "/absolute/path/to/cad-assets",
});

const previewUrl = URL.createObjectURL(
  new Blob([assembly.bytes], { type: assembly.mimeType }),
);
const gltf = await new GLTFLoader().loadAsync(previewUrl);
scene.add(gltf.scene);

Use a perspective camera and orbit controls for a 3D preview. For a 2D model-backed preview, use an orthographic camera aimed at the desired face. The assembled GLB uses millimeters and stable node names such as enclosure-box-1590b, part-knob-GAIN, and hole-backing-jack-IN, so the viewer can frame or select individual parts without parsing source documents.

function setTopPreviewCamera(
  camera: THREE.OrthographicCamera,
  dimensionsMm: { widthMm: number; lengthMm: number },
) {
  const marginMm = 12;

  camera.left = -dimensionsMm.widthMm / 2 - marginMm;
  camera.right = dimensionsMm.widthMm / 2 + marginMm;
  camera.top = dimensionsMm.lengthMm / 2 + marginMm;
  camera.bottom = -dimensionsMm.lengthMm / 2 - marginMm;
  camera.near = 0.1;
  camera.far = 500;
  camera.position.set(0, 0, 220);
  camera.up.set(0, 1, 0);
  camera.lookAt(0, 0, 0);
  camera.updateProjectionMatrix();
}

setTopPreviewCamera(camera, assembly.preview.enclosure.dimensionsMm);

To render CAD-style border linework, expose a viewer option such as linework and lineworkColor, then add an EdgesGeometry overlay after loading the GLB. This is a display-only effect and should not be written back into the stompbox artifact.

function addCadLinework(root: THREE.Object3D, lineworkColor = "#111827") {
  const meshes: THREE.Mesh[] = [];
  const material = new THREE.LineBasicMaterial({
    color: new THREE.Color(lineworkColor),
    transparent: true,
    opacity: 0.85,
    depthTest: true,
  });

  root.traverse((object) => {
    if (object instanceof THREE.Mesh) {
      meshes.push(object);
    }
  });

  for (const object of meshes) {
    if (!(object.geometry instanceof THREE.BufferGeometry)) continue;
    const edges = new THREE.EdgesGeometry(object.geometry, 35);
    const lines = new THREE.LineSegments(edges, material);

    lines.name = `${object.name || "mesh"}-cad-linework`;
    lines.renderOrder = 10;
    object.add(lines);
  }
}

const linework = true;
const lineworkColor = "#eb7223";

if (linework) {
  addCadLinework(gltf.scene, lineworkColor);
}

LineBasicMaterial is usually limited to one device pixel in WebGL. If the viewer needs heavier strokes, use Three.js LineSegments2 and LineMaterial from three/addons/lines in the application layer.

Appearance customization

Pass appearance to preview, GLB, SVG-view, or drill-template helpers to style the generated artifacts without changing .vdsp placement data. state remains for live values such as knob position, LED on/off, and footswitch pressed state; appearance is for enclosure, LED, label, template, and non-knob material hints. Knob bodies keep the material colors from their imported CAD/GLB assets.

Portable .vdsp v3 documents can also self-contain stompbox visual design at top-level appearance:

appearance:
  kind: stompbox
  enclosure:
    color: "#f8fafc"
    strokeColor: "#111827"
  defaults:
    label:
      color: "#2563eb"
      fontFamily: Vessel Block

appearance.kind is mutually exclusive: use stompbox for pedal enclosure, template, part, and label styling, or amp for amp-specific appearance. Helper options still override embedded .vdsp appearance when both are provided.

import {
  createStompboxAppearancePatch,
  createStompboxPreviewFromVdsp,
  createStompboxPreviewSvgViewsFromVdsp,
} from "@vessel-dsp/stompbox";

const appearance = {
  enclosure: { color: "#f97316", strokeColor: "#7c2d12", roughnessFactor: 0.45 },
  template: {
    guideColor: "#0ea5e9",
    foldColor: "#334155",
    holeStrokeColor: "#7c3aed",
    holeFillColor: "#faf5ff",
    centerDotColor: "#581c87",
  },
  defaults: {
    led: { color: "#ef4444", offColor: "#fee2e2" },
    label: { color: "#111827" },
  },
  controls: {
    GAIN: {
      label: { text: "DRIVE", color: "#ffffff" },
    },
    LED1: {
      led: { color: "#22c55e", offColor: "#064e3b" },
      label: { text: "READY", color: "#16a34a" },
    },
  },
} as const;

const preview = createStompboxPreviewFromVdsp(vdspSource, {
  hardwareProfile,
  appearance,
});
const views = createStompboxPreviewSvgViewsFromVdsp(vdspSource, {
  hardwareProfile,
  appearance,
});
const patch = createStompboxAppearancePatch(preview);

Preview SVG output includes stable hooks such as data-control-id, data-part-family, .knob-body, .knob-indicator, .led-lens, .label-text, .top-panel, .hole, .drill-hole-center-dot, .fold-line, and .guide-line. Preview GLB output bakes available material colors into copied GLB materials and writes the same frontend-friendly patch into asset.extras.appearance. Knob GLB materials are left as imported.