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

boltgame.js

v1.1.0

Published

Standalone Node.js headless host library for BOLT and HaxBall rooms.

Readme

boltgame.js

Standalone Node.js 24+ headless host library for BOLT and HaxBall rooms.

Built directly on top of the reconstructed @bolt/core game engine and native node-datachannel WebRTC data channels. It runs entirely in Node.js: no Chromium process or open BOLT Headless browser page is required.


Features

  • Zero-Token Hosting: Host public or unlisted rooms on the BOLT network instantly without solving captchas or fetching tokens.
  • 🔄 HaxBall-Compatible Runtime: Replace the haxball.js package/import while retaining standard room configuration, callbacks, and methods. Pass a HaxBall token to publish the same host on HaxBall and BOLT, or omit it for BOLT-only hosting.
  • 🚀 Native BOLT Features (BOLTInit): Built-in support for match statistics tracking, vote-kick moderation, autonomous balancing bots, captain picking, voluntary AFK, and custom ratings (room.bolt).
  • 🛡️ Guarded Native WebRTC: Safe, high-performance WebRTC data channels backed by libdatachannel with process crash protections.
  • 🏢 Multi-Room Concurrency: Host multiple independent rooms within a single Node.js process without global state conflicts.
  • 📦 Dual ESM & CommonJS: Works out of the box with import and require() across modern Node.js runtimes.

Installation

Requires Node.js 24 or newer.

npm install boltgame.js

Quickstart

1. Drop-In Replacement for haxball.js (HBInit)

import BoltGameJS from 'boltgame.js';

// Exact haxball.js syntax:
const HBInit = await BoltGameJS();

const room = HBInit({
  roomName: 'My BOLT Headless Room',
  maxPlayers: 12,
  public: true,
  noPlayer: true,
});

room.onRoomLink = (link) => {
  console.log('Room link:', link);
};

room.onPlayerJoin = (player) => {
  console.log(`${player.name} joined the room!`);
  room.sendAnnouncement(`Welcome to the room, ${player.name}!`, player.id, 0x00ff00);
};

Or using direct named import:

import { HBInit } from 'boltgame.js';

const room = HBInit({
  roomName: 'My BOLT Room',
  maxPlayers: 12,
  public: true,
  noPlayer: true,
});

2. Enhanced BOLT Room with Custom Ratings & Features (BOLTInit)

import BoltGameJS from 'boltgame.js';

const { BOLTInit } = await BoltGameJS();

const room = BOLTInit({
  roomName: 'BOLT Pro 3v3',
  maxPlayers: 12,
  public: true,
  noPlayer: true,
  bolt: {
    statistics: true,  // Live match statistics tracking
    voteKick: true,    // Peer-channel vote-kick moderation
    afk: true,         // Voluntary !afk queue
    captain: true,     // Automatic captain picks
    bots: true,        // Autonomous balancing bots
    ratingLabel: 'ROOM ELO',
  },
});

room.onPlayerJoin = (player) => {
  // Set custom in-game rating for player displayed in BOLT client UI
  room.bolt?.setRating(player.id, 1500);
};

3. Legacy HaxBall Room (Direct HaxBall Network Hosting)

import BoltGameJS from 'boltgame.js';

const HBInit = await BoltGameJS();

const room = HBInit({
  roomName: 'Haxball Room',
  maxPlayers: 16,
  public: false,
  noPlayer: true,
  token: 'THR1-AAAA...', // HaxBall headless token from haxball.com/headlesstoken
});

4. Existing Room Policies with Dual BOLT + HaxBall Listing

Use BOLTInit and explicitly disable every built-in policy that your room already owns. The room.bolt presentation API remains available.

import { BOLTInit } from 'boltgame.js';

const room = BOLTInit({
  roomName: 'My Production Room',
  maxPlayers: 16,
  public: true,
  noPlayer: true,
  token: process.env.HAXBALL_TOKEN,
  bolt: {
    afk: false,
    bots: false,
    captain: false,
    voteKick: false,
    statistics: false,
  },
});

// Keep the room's existing AFK, captain, moderation, stats, ELO, and level code.
room.onPlayerJoin = (player) => {
  // Optional display-only state for BOLT clients:
  room.bolt?.setRating(player.id, getExistingRating(player.auth));
};

The token registers one room with HaxBall; BOLT lists and joins that same room. This is not two synchronized room instances. Keep the Node.js process running for as long as the room should remain online.

Configuration

BoltGameJS(config) accepts an optional configuration object. The BOLT site and the BOLT platform API live on different origins, so they are configured separately:

| Option | Env fallback | Default | Used for | |---|---|---|---| | apiEndpoint | BOLT_PLATFORM_API_ORIGIN | https://spain.api.boltgame.io | Registering the room (/rs/api/host) | | endpoint | BOLT_PLATFORM_WEB_ORIGIN | https://boltgame.io | /room/<token> links and the signaling Origin header | | proxy | — | — | HTTP/HTTPS proxy for master and WebSocket connections | | sourceIp | BOLT_ROOM_SOURCE_IP | — | Source IP for outgoing sockets | | debug | — | false | Verbose logs |

Neither is required — the defaults host on the public BOLT network. If you run your own single-origin deployment, set endpoint (or BOLT_PLATFORM_ORIGIN) alone and it is used for both.

const HBInit = await BoltGameJS({
  endpoint: 'http://localhost:8090',     // web app
  apiEndpoint: 'http://localhost:8091',  // platform server
});

Network Path

Gameplay data channels connect directly between each player and the Node.js room process on your VPS. BOLT and HaxBall are used for directory and WebRTC signaling, not as gameplay relays. BOLT's optional bolt presentation channel also runs directly over the peer connection. Dual listing therefore adds no BOLT server hop to gameplay, although exact latency still depends on the client's normal ICE and network route.


License

Proprietary / Closed Source. Copyright (c) 2026 BOLT (boltgame.io). All rights reserved. See LICENSE for terms.