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

@rulecad/model-link

v0.2.0

Published

Share a printable model as a link (the model lives in the URL), and write STL or multi-colour Bambu Studio 3MF files, in the browser or Node.

Readme

@rulecad/model-link

Share a printable model as a link. The model is compressed into the URL's #fragment, which browsers never send to the server, so a public web page can open a private design and nothing is uploaded. It also writes STL files, and 3MF files in Bambu Studio's project layout with each part on its own filament (AMS) slot. No dependencies: it uses the browser's own CompressionStream, which Node 20+ has too.

import { fromParts, encode, decode, stl, threemf } from '@rulecad/model-link';

const model = {
  title: 'Soap tray', version: '1.0.0',
  ...fromParts([
    { name: 'tray', triangles },                                  // [[[x, y, z] ×3], …], mm, Z up
    { name: 'logo', triangles: logoTriangles, slot: 2 },          // printed in the AMS's second filament
  ]),
};
const link = `https://your-viewer.example/#m=${await encode(model)}`;

const back = await decode(link.split('#m=')[1]);
const stlBytes = stl(back);              // Uint8Array, binary STL
const zip = await threemf(back);         // Uint8Array, a .3mf (one object, two parts on slots 1 and 2)
  • Precision: corners are snapped to a grid about 1/5000 of the model's size, and shared corners are stored once.
  • Many copies of one shape (nine keycaps): fromShapes() stores each shape once and a transform per copy, and decode() expands them.
  • Things that move: a model can carry motion: its items, the joints between them (fixed, revolute, prismatic, cylindrical, ball, path), named poses, and which item each part moves with. jointValues(motion, pose) gives every joint's values, followers included, and placeItems(motion, values) gives where each item is. The page uses these for its sliders, and cad uses the same functions to place an assembly, so both agree. The format is described at the top of the motion section in model-link.mjs.
  • Safety: links are data, never code. decode() checks the format and sizes (LIMITS), refuses damaged links, and refuses links from a newer format version.
  • Short links: parseHash(location.hash) also reads #s=<id>, a GitHub Gist holding the data, and fromGist(id) fetches it without signing in.
  • The file says who made it: stl(m, keep, { generator }) and threemf(m, keep, { generator }); the default is rulecad.
  • Reproducible files: a 3MF records the day it was made; bambu3mf(objects, { date: '2026-10-14' }) fixes it, so the same model gives the same bytes.
  • bambu3mf([{ name, parts: [{ name, triangles, slot }] }]) writes a 3MF from triangles directly. It has been checked by loading the files back into Bambu Studio; other slicers read the same file as plain objects.
  • zip([[name, text], …]) writes a ZIP of text files, with the platform's own compression (no library).