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

otherplane

v0.1.1

Published

A static site generator for walkable Gaussian-splat museums. Generate a 3D room per section, link rooms with doorways, publish a static walkable site.

Readme

Otherplane

A static site generator for walkable Gaussian-splat museums. Point it at the sections of a personal site and it generates a 3D room for each one, lets you mark spawn points / doorways / artifacts, links the rooms together, and publishes a plain static walkable site — host it on GitHub Pages, Cloudflare R2/Pages, S3, or any folder behind any web server.

A museum is just rooms linked by exits — like web pages linked by hrefs. There is no manifest and no central "museum" object; the graph is emergent.

This repo is the engine

Otherplane ships the tool, not a museum. You build your own site on top: your rooms, splats, colliders, music, and per-site config are your content and are gitignored by default — clone the engine, then create a museum inside it (or in any folder) and track that content in your own repo. engine/ is the content-free renderer; the rest is the CLI, schema, and authoring pipeline.

otherplane/
├── engine/              the renderer — a content-free Next.js viewer (Spark + R3F + Rapier)
├── bin/otherplane.mjs    the CLI (the npm scripts alias it)
├── schema/              room.json JSON Schema (editor autocomplete + `otherplane check`)
├── scripts/             gen_world.py — generate a room from a prompt (World Labs Marble)
├── skill.md             the authoring guide — how rooms get made, marked, linked, shipped
└── otherplane.config.example.json

# created by `otherplane init` / your content — GITIGNORED, build your own site here:
├── otherplane.config.json   deploy config (landing room, base path, title, walk speed)
├── rooms/<slug>/room.json  the rooms — one folder, one URL (/<slug>/)
├── worlds/                 splats + colliders (.spz / .glb) — host big blobs on R2/S3
└── music/                  per-room loopable tracks

The CLI mirrors your content into engine/public/ (a gitignored build artifact) so Next can serve and enumerate it; you never edit there. The renderer is a deep module: its only input is a room.json (by URL) — it knows nothing about museums, hosting, or how assets were made. See CLAUDE.md for renderer internals and skill.md for the authoring pipeline.

Quick start

Use it as an installed CLI in any folder (the engine's deps install themselves on first run):

npx otherplane init       # scaffold otherplane.config.json + rooms/ worlds/ music/
npx otherplane edit       # open http://localhost:3000 — walk, mark, and wire rooms
npx otherplane build      # → ./out (deploy anywhere) · -- --base /museum to sub-path

…or clone the repo and use the npm run aliases (npm run init / edit / build). Either way, build emits a plain static out/ in your project — host it on GitHub Pages, Cloudflare, S3, or any static host.

Add rooms one of two ways: generate them with otherplane new (World Labs Marble — needs a key + uv, see below), or bring your own .spz splat + .glb collider, drop them in worlds/, and point a rooms/<slug>/room.json at them. Then otherplane edit to place spawns/doors/artifacts (it writes room.json for you). No key or Python is needed for the bring-your-own path.

Publishing (maintainers): npm publish ships the CLI + the engine source (files allowlist; build artifacts and node_modules are excluded). The engine is heavy (Next + Three.js + Rapier); its deps install on the user's first dev/edit/build, not at install time. Bump the version and npm publish.

CLI

Like other static site generators (Hugo, Astro, Eleventy), Otherplane exposes a small set of verbs through one CLI (bin/otherplane.mjs). Run them as otherplane <verb> or via the npm run aliases below:

| Command | What it does | | :----------------- | :-------------------------------------------------------------------------- | | npm run setup | Install the engine's dependencies (one-time). | | npm run init | Scaffold a fresh project (config, rooms/, .env.example) in this folder. | | npm run new | Generate a room from a prompt (World Labs Marble). See below. | | npm run dev | Dev server with the viewer (http://localhost:3000). | | npm run edit | Dev server with edit mode on — mark/wire rooms in the viewer; writes room.json for you. | | npm run check | Validate every rooms/*/room.json against the schema. | | npm run build | Static export to engine/out — deploy this folder anywhere. -- --base /museum to mount under a sub-path. | | npm run serve | Serve the built engine/out at http://localhost:8000. | | npm run preview | build then serve. | | npm run clean | Remove build output + the synced mirror. |

Generating a room

cp .env.example .env          # then paste your WORLD_LABS_KEY
npm run setup
npm run new -- "a cozy wood-paneled library, warm lamplight" --slug library --name "Library"

This calls World Labs Marble, downloads the splat (.spz) + collider (.glb) into worlds/, saves the raw world object under generated/<slug>/, and writes a room.json skeleton to rooms/<slug>/. Use --model marble-1.0-draft (the default) while iterating — it's cheap (~$1.26).

Then mark coordinates and wire the room up in the viewer — see below.

Marking & wiring (edit mode)

npm run edit opens the viewer with an authoring panel and writes room.json for you (no clipboard, no hand-editing). Walk into a room, then:

  • C — drop (or move the selected) entryway at your floor-snapped spot.
  • B — aim and drop (or move the selected) artifact at what you're looking at.
  • F select the marker under your crosshair · Del remove it · Z fly.

Every marker shows as a labeled orb (green entryway, cyan exit, amber artifact). In the panel you name entryways, wire exits by menu (any room → entryway) or paste an arbitrary URL (link into someone else's museum), promote an entryway into a doorway, and click two-way to auto-create the return door in the target room. Changes save to rooms/<slug>/room.json as you go.

Hosting & repo size

Keep text in git (room.json + the shared bundle) and blobs in object storage. A .spz is ~5 MB and a collider ~5 MB; for anything you want to keep, mirror those to R2 (cheap, zero egress, CDN-backed) and point each room.json URL there. Adding a room then costs the repo a few KB, not 10 MB. (Marble's own CDN URLs have no documented retention SLA — self-host keepers.)

Mounting on an existing site (e.g. /museum)

To hang the museum off a personal site — an "Enter my museum" button that goes to example.com/museum/ — build it under that sub-path and drop the output into your site's tree:

npm run build -- --base /museum   # or set "basePath": "/museum" in otherplane.config.json
# then copy engine/out/* into your site's /museum/ directory (or point the host at it)

The link on your homepage is just <a href="/museum/">. The museum is plain static files, so it coexists with any host; the two builds stay separate (the viewer carries a WebGL toolchain your main site shouldn't inherit) and integrate at the deploy layer.

License

MIT — see LICENSE. Built on WorldSplats (the viewer), Spark.js (splat rendering), and World Labs Marble (generation).