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

@womp/kakapo-web

v0.1.1

Published

Kakapo scenes in the browser: the viewer loads a scene, models each object on the GPU and renders it on a canvas. OpenSCAD knobs can be changed live.

Readme

@womp/kakapo-web

Kakapo scenes in the browser: the viewer loads a scene, models each object on the GPU and renders it on a canvas. OpenSCAD knobs can be changed live.

Needs WebGPU (core features, default limits). ES modules, with TypeScript types.

Viewer

import { createViewer } from "@womp/kakapo-web"

const viewer = await createViewer(canvas, { sceneUrl: "https://example.com/scene.json" })

createViewer(canvas, options) resolves once the scene is loaded and its knobs are known. Modelling then continues in the background.

| Option | Type | Default | | |---|---|---|---| | sceneUrl | string | required | the scene JSON | | quality | number, 0..1 | 0.3 on phones, 0.5 elsewhere | modelling resolution | | shadows | boolean | true | | | msaa | boolean | true | 4× multisampling | | insets | () => Insets | none | the CSS pixels of the canvas your UI covers, kept clear when framing | | onProgress | ({ built, total }) => void | | modelling progress; built === total when idle | | onError | (e: ViewerError) => void | | errors after startup |

| Method | | |---|---| | getScripts(): Script[] | the visible OpenSCAD scripts and their knobs | | setParams(values: Params, nodeId?: number) | sets knobs on one script, or on every script that declares them; re-models only the objects that change | | resetParams(nodeId?: number) | back to the scene file's values | | setScene(url: string): Promise<boolean> | swaps in another revision of the same scene, re-modelling only what changed; false if a later call or destroy superseded it | | frame(nodeId?: number) | points the camera at the object holding nodeId, or at the whole scene, which then stays framed on resize | | destroy() | releases the GPU device and the listeners |

type ParamValue = number | boolean | string | ParamValue[]
type Params = Record<string, ParamValue>

interface Script {
  nodeId: number
  name: string
  params: ParamSpec[]
  warnings: string[]
  error: string
}

interface ParamSpec {
  name: string
  value: ParamValue
  defaultValue: ParamValue
  min?: number
  max?: number
  step?: number
  options?: { value: number | string; label: string }[]
  section?: string
}

interface Insets {
  left: number
  right: number
  top: number
  bottom: number
}

Errors

Failures are ViewerErrors, with a code:

| code | From | | |---|---|---| | no-scene | createViewer | sceneUrl is empty | | no-webgpu | createViewer | no WebGPU, adapter or device | | scene-load | createViewer, setScene | the scene cannot be fetched or parsed | | scene-mismatch | setScene | the revision's objects differ; create a new viewer for it | | device-lost | onError | the GPU device was lost and the viewer stops | | build | onError | one object could not be modelled; the others carry on |

Behaviour

  • The viewer fetches only scenes: sceneUrl and the URLs given to setScene. Its fonts and environment map are built in, at about 2 MB of the JavaScript (1.26 MB gzipped).
  • It draws only on canvas.
  • Text is set in Roboto Medium, with Noto Emoji for the characters Roboto lacks. The scene's font family, weight and italic are ignored.
  • Every scene is lit by the built-in environment map, whatever hdr_name it names.

Knob UI

import { createUi } from "@womp/kakapo-web/ui"

const ui = createUi(container, { shownParams: ["wall"], onChange, onPrint })
const viewer = await createViewer(canvas, { sceneUrl, insets: () => ui.insets(canvas) })

ui.setViewer(viewer)

A panel over the canvas with every visible script's knobs, Focus and Reset per script, a status line, and a Print button when onPrint is given. container must be positioned and hold the canvas; the panel lives in a shadow root inside it.

| UiOptions | | |---|---| | shownParams?: string[] | shows only these knobs | | onChange?: () => void | the user turned a knob or reset a script | | onPrint?: () => void | adds the Print button |

| Ui | | |---|---| | setViewer(viewer: Viewer) | the viewer whose knobs the panel shows | | refresh() | redraws the knobs after they change elsewhere | | setStatus(text: string \| null) | the status line; null hides it | | insets(canvas: HTMLElement): Insets | the part of the canvas the panel covers | | destroy() | removes the panel |

Not part of the contract

@womp/kakapo-web/dev exposes internals for benchmarks and debugging, and changes with the implementation.

Licences

The built-in fonts are Roboto (Apache License 2.0) and Noto Emoji (SIL Open Font License 1.1); their licence texts are in src/viewer/assets/. The environment map is Womp's own.