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

pcb-scene3d-viewer

v1.2.2

Published

Reusable Three.js PCB 3D scene viewer for normalized ECAD and CircuitJSON scene descriptions

Readme

PCB Scene3D Viewer

Reusable browser-side 3D PCB viewer utilities for normalized ECAD scene descriptions and canonical CircuitJSON documents.

This package renders scene descriptions produced by packages such as altium-toolkit/scene3d and kicad-toolkit/scene3d. It does not parse ECAD source files and does not build format-specific scene data. Hosts that already have CircuitJSON can pass a common DocumentResult, a prepared CircuitJsonDocumentContext, or an element array directly to the controller or runtime.

The package was extracted from ECAD Forge, where it is used for browser-based PCB 3D scene rendering. Its runtime, geometry factories, model loading, component picking, view presets, archive export, GLTF/GLB assembly writing, and optional DOM shell can be reused by other browser-based ECAD tools.

CircuitJSON 1.1 convergence

Version 1.2.2 accepts the common document and prepared-context shapes returned by CircuitJSON, Gerber, Altium, and KiCad Toolkit 1.1-compatible APIs. The adapter requests the shared elements index once and reuses it across repeated scene builds. PcbScene3dCircuitJsonAdapter.prepare() exposes that proof-aware path to hosts. Existing bare arrays are normalized by the shared CircuitJSON boundary, while legacy parser-compatible hybrid arrays retain their native builder behavior. Canonical model_asset paths and matching document or session assets are resolved directly by the adapter; hosts do not need an app-side document transform or resolver wrapper. Document asset indexes are created only for referenced models and cached through a prepared context. Exact case-sensitive paths win; case-insensitive fallback is used only when unique. Polygon-plated holes use the shared CircuitJSON hole primitive model, including rotation-local pad_outline extents and pill-slot width, height, and rotation; outer-pad and drill rotations remain independent and board-space drill angles are applied exactly once. Gerber routed slots therefore retain horizontal, diagonal, and vertical canonical geometry in the viewer. Multiple disjoint pcb_board rows (or multiple pcb_panel rows) render as independent substrate, outline, mask, and export contours instead of dropping every row after the first. Legal rectangular and square CircuitJSON drill apertures retain their exact width, height, and board-space rotation through substrate, pad, and assembly export meshes.

Canonical documents retain their exact source.format as the scene sourceFormat; raw element arrays continue to use circuitjson. Routed traces and copper pours with no authored solder-mask coverage value remain covered, while covered_with_solder_mask: false keeps an explicit opening exposed. Standard vias likewise default to tented and honor is_tented: false as an explicit opening.

The live runtime loads STEP/STP, WRL/VRML, STL, OBJ, GLTF/GLB, and 3MF from canonical text/bytes or browser files. Referenced GLTF buffers, OBJ material libraries, and WRL textures are attached from matching document/session assets using safe project-relative paths. URL loading is explicit through modelLoaderOptions.fetch or allowNetworkModelFetch: true, with optional headers, timeout, cache, and bounded-resource settings. Static authHeaders stay on the main model origin; authHeadersForUrl is the explicit per-URL override. The model ZIP exporter uses the same policy and writes each raw model under its original source basename with safe GLTF, OBJ, and WRL companions.

STEP loading uses the installed @sunbox/occt-import-js package directly. Its package-owned worker is reused for browser imports, while runtimes without Web Workers dynamically import the same ESM factory. Hosts only need to serve the package dist/ directory at /node_modules/@sunbox/occt-import-js/dist/; no copied runtime, global script, or host-owned worker is required.

Install

npm install pcb-scene3d-viewer

For local ECAD Forge development, use the sibling checkout:

{
    "dependencies": {
        "pcb-scene3d-viewer": "file:../pcb-scene3d-viewer"
    }
}

Usage

import {
    PcbScene3dController,
    PcbScene3dShellRenderer
} from 'pcb-scene3d-viewer'
import { PcbScene3dBuilder } from 'altium-toolkit/scene3d'

container.innerHTML = PcbScene3dShellRenderer.render(documentModel)

const controller = new PcbScene3dController(
    container.querySelector('[data-scene-3d-viewport]'),
    documentModel,
    {
        buildScene: (nextDocumentModel, options) =>
            PcbScene3dBuilder.build(nextDocumentModel, options),
        createModelRegistry: () => null
    }
)

controller.setSelectedComponent('U1')

Canonical document input does not require a format-specific buildScene callback:

import { PcbScene3dController } from 'pcb-scene3d-viewer'
import { Parser } from 'gerber-toolkit'

const document = await Parser.parseAsync({
    fileName: file.name,
    data: await file.arrayBuffer()
})

const controller = new PcbScene3dController(viewportNode, document)

Documentation

License

This project is available under two licensing options.

1. Open-source software license

GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later).

You may use, modify, and distribute this project under the AGPL. If you distribute modified versions, run modified versions as a network service, or create larger works based on this project, they must comply with the AGPL, including source-code availability requirements.

2. Commercial/proprietary license

For use in closed-source, proprietary, or otherwise AGPL-incompatible products, a separate paid commercial license is required.

Commercial licensing contact: https://github.com/SunboX

Documentation and notices

Documentation and non-code text are licensed under Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA-4.0) unless otherwise marked.

Copyright (C) 2026 André Fiedler.

Copyright, license, attribution, and source-origin notices must be preserved as required by the AGPL, CC-BY-SA-4.0, and the notice files in this repository. See LICENSE, COMMERCIAL-LICENSE.md, and NOTICE.md.