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

@pablo-mayrgundter/portal-netgl

v0.1.0

Published

Command-stream WebGL portals: route a three.js renderer's GL calls over a postMessage transport so an iframe's draws compose into the host canvas without a bitmap round-trip.

Readme

@pablo-mayrgundter/portal-netgl

Command-stream WebGL portals: route a three.js renderer's GL calls over a postMessage transport so an iframe's draws compose into the host canvas without a bitmap round-trip.

Two adoption modes:

  • Embedded app authors own their own renderer (e.g. integrating celestiary, bldrs, an existing three.js app into a portal): use makeNetGLPortalGuest. The factory builds a recorder-wrapped THREE.WebGLRenderer that you use instead of new WebGLRenderer(...); your render loop runs unchanged.
  • Portal-aware target with a scene + anchor: use makeNetGLPortalTarget. The factory drives rendering in response to inbound setPose messages from the host.

Install

npm install three @pablo-mayrgundter/portal-netgl

three is a peer dependency — your version of three.js is used. Supported range: three@>=0.171.0 <1.0.0.

makeNetGLPortalGuest — embedded-app integration

import * as THREE from 'three'
import { makeNetGLPortalGuest } from '@pablo-mayrgundter/portal-netgl'

// Detect portal mode (in an iframe + ?portal=1 in the URL).
const portalMode =
  window.parent !== window.self &&
  new URLSearchParams(location.search).get('portal') === '1'

if (portalMode) {
  const { renderer } = makeNetGLPortalGuest({
    WebGLRenderer: THREE.WebGLRenderer,
    anchor: {
      position: [0, 0, 0],
      normal: [0, 0, -1],
      up: [0, 1, 0],
      halfWidth: 1,
      halfHeight: 1
    },
    background: { r: 0, g: 0, b: 0 },
    rendererParams: { antialias: true, stencil: true, depth: true }
    // optional onSetPose(msg) hook if you want to honour the host's pose
  })
  // Use `renderer` exactly as you would a normal THREE.WebGLRenderer.
  // setSize, render, setAnimationLoop — all work the same. GL calls
  // cross the wire to the host canvas instead of painting locally.
}

The host page iframes the embedded app with ?portal=1 and runs a NetGL replay engine (makeNetGLReplay from this package) against its own WebGL2 canvas, with remapScreenViewport configured to place the embedded app's screen-target draws inside the portal door's pixel rect.

makeNetGLPortalTarget — portal-aware scene

Use when the embedded app exists primarily to be embedded. Build a THREE.Scene, hand it to the factory with a portal anchor; the factory owns the renderer, the message protocol, and the per-frame render trigger:

import { makeNetGLPortalTarget } from '@pablo-mayrgundter/portal-netgl'

const target = makeNetGLPortalTarget({
  scene: myScene,
  anchor: {
    position: [0, 1.6, 0],
    normal: [0, 0, -1],
    up: [0, 1, 0],
    halfWidth: 1.3,
    halfHeight: 1.6
  },
  tick: (time) => animate(myScene, time)
})
target.start()

Protocol

NetGL is two streams over a single transport:

  • Calls (sender → receiver): NetGLCall { name, args, returnId? } for every GL call, plus NetGLFrameEnd { type: 'netgl:frame-end' } markers after each frame.
  • Control (host ↔ guest): netgl:ready handshake announcing the guest's anchor + background; netgl:setPose from the host with the coupled camera state.

See DESIGN.md for the architecture, the adoption findings that surfaced building celestiary integration, and the open problems on the roadmap.

Status

Pre-1.0. The wire protocol shape is documented and exercised against a real GL-heavy app (celestiary) but isn't ABI-stable across patch releases. Lock to an exact version in production.

Publishing (maintainers)

Releases are CI-driven via npm Trusted Publishing (OIDC). No long-lived NPM_TOKEN secret. Cutting a release:

  1. Bump version in packages/portal-netgl/package.json.
  2. Land on main.
  3. The npm-publish workflow detects the version diff vs @latest and publishes, attaching a provenance attestation pointing at the commit + workflow run.

Bootstrap (one-time, for the very first version): npm requires a package to exist before you can configure trusted publishing for it, so the v0.1.0 publish must come from a maintainer's laptop. Run the following from the repo root — the -w flag targets the workspace package by name regardless of cwd, so there's no risk of accidentally publishing the root portal-monorepo (which is private + name-clashes with an existing portal on npm anyway):

npm install                         # populate workspace symlinks
npm run build -w @pablo-mayrgundter/portal-netgl
npm run publish:portal-netgl        # interactive 2FA

Then configure the trusted publisher on npmjs.com: https://www.npmjs.com/package/@pablo-mayrgundter/portal-netgl/access → Trusted Publishers → Add → GitHub Actions, with:

  • Organization or user: pablo-mayrgundter
  • Repository: portal
  • Workflow filename: npm-publish.yml
  • Environment name: (leave blank, or set to release if you want an approval gate)

From v0.1.1 onward, every release goes through CI.

License

MIT