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

@vbz-gg/game-base

v0.2.0

Published

Build a game the vbz arcade can run: on-screen controls, the two artifacts, and a harness that frames your game the way the arcade does

Readme

@vbz-gg/game-base

The SDK for building a game the vbz arcade can run.

A game on the arcade is a Clockwork 2 simulation: fixed-step ticks, seeded randomness, and an input log that a server replays to check the score. This package is what sits between that and the arcade - the on-screen controls, the two artifacts an upload carries, and a harness that frames your game locally the way the arcade frames it.

bunx @vbz-gg/game-base new ./my-game
cd ./my-game && bun install
bun run dev

That copy builds and plays before a line of it is changed, so anything that breaks afterwards is something you just did. Its id comes from the directory name and is immutable once published.

@clockwork2/engine is a peer dependency, so your game installs one copy of the engine rather than two.

The three commands

game-base new   <dir>   copy a game that already conforms, and rename it
game-base build <dir>   write dist/sim.js, dist/frame.js and dist/manifest.json
game-base dev   <dir>   serve the game on two origins, the way the arcade does

dev is the arcade's play view on your laptop: the game in a sandboxed frame on one origin, the page that frames it on another, and the pad your manifest asked for drawn over it. A scheme picker switches layouts without editing the manifest, and ending a run publishes its recording.

On-screen controls

A phone has no keyboard, so a game says in its manifest how it expects to be steered there. There are two ways, and the difference is who draws the buttons.

The arcade draws them. Name a scheme and put your own actions in its slots:

inputs: {
  map: {
    left: [{ code: "ArrowLeft", device: "key" }],
    right: [{ code: "ArrowRight", device: "key" }],
  },
  controls: {
    mode: "scheme",
    scheme: "dpad",
    bind: { left: "left", right: "right" },
  },
}

Four schemes: tap is one button covering the viewport, and dpad, dpad+1 and dpad+2 are a direction pad with nought, one or two action buttons beside it. Bind the slots you use and leave the rest of the layout empty - the example above draws two buttons in a d-pad's left and right positions.

The arcade owns every pixel of those buttons, which is what lets it promise they are thumb-sized, clear of the notch and the home indicator, and the same in every game that uses them.

You draw them. Declare controls: { mode: "custom" }, paint the controls in your own renderer, and read pointer input. The arcade draws nothing and promises nothing. Two rules follow from the engine's own: a game may not build an input event, so the hit test goes in tick() rather than in the renderer, and it works in simulation units because the host has already quantised the pointer against a viewport that differs from one device to the next.

Leaving controls out says your game wants a keyboard, and the arcade tells a phone player so rather than framing a canvas they cannot steer.

Using the renderer yourself

If you are building a host rather than a game:

import { mountControls } from "@vbz-gg/game-base/controls"

const pad = mountControls(playView, {
  scheme: "dpad+1",
  bind: { left: "left", right: "right", a: "jump" },
  onPress: (action, value) => frame.virtualInput(action, value),
})

It takes an element and gives back update and destroy. Plain DOM, so it works in React and outside it. It sets its own layout, hit target and safe-area clearance and takes its appearance from CSS custom properties (--gb-control-bg, --gb-control-size, --gb-control-radius and the rest), so a host restyles it without importing a stylesheet.

destroy and update both send a release for anything still held. A held control that never comes up is not a visual bug: it runs the player into a wall for the rest of the session.

License

MIT