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

steam-bridge

v0.2.14

Published

Native-backed Steamworks bridge for Electron and Node.

Readme

Steam Bridge

npm CI license

Native Steamworks for Electron and Node, with a TypeScript API and a Rust napi-rs core.

Steam Bridge handles Steam API initialization, callbacks, native library loading, and managed Electron overlays. The npm package includes prebuilt native addons and Valve runtime redistributables for every supported platform, so consumers do not need to download the Steamworks SDK.

Install

npm install steam-bridge

Requirements:

  • Node.js 18 or newer
  • Electron 24 or newer when used with Electron
  • A running Steam client and a Steam app ID

The repository smoke application tracks Electron 43.1.1. Windows shared-texture hosting is tested against that runtime; applications using the lower-level host should feature-detect Electron's offscreen texture event.

What is included

  • Typed Steamworks APIs for auth, achievements, stats, cloud, input, inventory, workshop, networking, matchmaking, game servers, and more.
  • A compatibility-style grouped client for familiar JavaScript call patterns.
  • Managed Electron overlays for store, web, checkout, Friends/chat, profiles, community, achievements, stats, and other Steam surfaces.
  • A Steam Web API client for public and publisher endpoints.
  • Prebuilt native addons and Valve Steam runtime libraries.

See the Steam API coverage for the complete implemented surface and known gaps.

Platform Targets

| Platform | Target | | --- | --- | | Windows x64 | x86_64-pc-windows-msvc | | Linux x64 and Steam Deck | x86_64-unknown-linux-gnu | | macOS Apple Silicon | aarch64-apple-darwin |

macOS Apple Silicon Only

Intel macOS, Rosetta, and universal macOS builds are not supported. Build and run macOS test apps only on native darwin/arm64 Apple Silicon hosts. Do not package, launch, or verify macOS smoke apps through Rosetta.

Quick start

import steamworks from "steam-bridge";

const client = steamworks.init(480);

const steamId = client.localplayer.getSteamId().steamId64;
const ticket = await client.auth.getAuthTicketForWebApi("my-game");

client.callback.register("MicroTxnAuthorizationResponse", (event) => {
  console.log(event);
});

client.overlay.activateToWebPage(
  "https://store.steampowered.com/app/480/"
);

console.log({ steamId, ticketBytes: ticket.getBytes().length });

Valve's SpaceWar App ID 480 is useful for generic local smoke testing. Replace it with your own app ID for app-specific features and production. Purchase flows require your real Steam-launched app and configured products; SpaceWar cannot prove them.

When launching outside Steam during development, place a steam_appid.txt containing your app ID next to the executable or in its working directory.

Electron overlay

Configure Electron before app.ready, then create one managed overlay for the main game window and reuse it:

import { app, BrowserWindow } from "electron";
import steamworks from "steam-bridge";

steamworks.electronConfigureSteamOverlay();

app.whenReady().then(async () => {
  const mainWindow = new BrowserWindow({ width: 1280, height: 720 });
  const client = steamworks.init(480);
  const overlay = client.overlay.createElectronSteamOverlay(mainWindow);

  const result = await overlay.openStoreAndWaitIfAvailable({ appId: 480 });
  if (!result) {
    console.warn("The Steam overlay is not available yet");
  }
});

Wait helpers resolve after the Steam overlay closes and control returns to the application. Steam Bridge supports one managed native presenter per process, controlled from Electron's main thread. Raw activation helpers remain available for diagnostics, but Electron product UI should use the managed overlay path.

Close Chromium DevTools before validating Steam overlay behavior. DevTools can change Chromium surface activity and timing; it is not a supported way to make the Steam surface repaint.

The repository's Windows release matrix is fail-closed around synthetic close input. An exact pre-dispatch screenshot must prove the foreground native host, contained modal geometry, a DPI-scaled Steam close glyph, the dimmed backdrop, and loaded content. Coordinates are never reused across frames. Friends/chat's dark navigation layout is accepted only when the close glyph itself passes the direct pixel score.

On Windows, a managed presenter is non-activating and click-through while it is parked. When Steam opens an interactive surface, the presenter becomes focusable inside the Electron content bounds; after Steam closes, it returns to the parked state and restores application focus. This keeps the ordinary title bar, menus, minimize, maximize, window drag, and rounded-corner behavior owned by the Electron window. The interactive surface is an Electron-owned popup (owned-popup in diagnostics); the release proof rejects the obsolete standalone popup-layered identity.

The same managed overlay also prepares passive Steam notifications, including achievement progress and unlock toasts. The presenter stays transparent, click-through, and idle until Steam requests a frame, then parks again without an overlay-activation callback. Applications do not need a separate polling or repaint loop. When a development tool clears and immediately re-awards an achievement, wait for client.stats.onUserStatsStored(...) before the next mutation; store() is accepted synchronously, but Steam confirms the state change asynchronously. client.achievement.onStored(...) reports the later progress or unlock notification update.

overlay.snapshot().lastError reports an unrecovered presenter fault. A transient Electron frame-capture failure is retried and cleared after a later capture succeeds; a terminal presenter failure remains available with closeReason: "error" for diagnostics.

Windows game-host mode

Steam renders into a top-level native swap chain on Windows. A Chromium offscreen surface or Win32 child window is not a complete Steam presentation target. Games that need native title-bar behavior and continuous rendering while Steam is open can use startNativeOverlaySession() as a standalone D3D11 host and render the game in a hidden Electron window created with:

const gameWindow = new BrowserWindow({
  show: false,
  webPreferences: {
    offscreen: {
      useSharedTexture: true,
      sharedTexturePixelFormat: "argb"
    }
  }
});

For every frame paint event, pass the frame texture's textureInfo.handle.ntHandle, coded width and height, and textureInfo.contentRect (or the paint event's dirty rectangle) to session.updateSharedTexture(). Electron only guarantees that update region was populated, so Steam Bridge copies it into a retained bridge-owned texture without erasing unchanged pixels. The call uses a bounded GPU query wait and fails instead of hanging if the copy does not complete; release Electron's texture in a finally block after it returns. Steam Bridge then uses the matching high-performance DXGI adapter, aspect-fits the source, and presents through a two-buffer flip-sequential swap chain. updateFrame() remains available as a BGRA CPU fallback.

Set frameRate to the active display's refresh rate and update it with session.setFrameRate(...) when the native host moves to another monitor. The Windows standalone host uses a DXGI frame-latency waitable swap chain as its presentation boundary and submits tear-free frames with Present(1). Waiting on DXGI before each frame avoids relying on JavaScript timer precision while still following the active display's refresh cadence. New CPU frames and shared textures are marked dirty and pump at least once immediately, including when continuousPresent is false; the session timer remains the retained-frame and Steam-overlay fallback. Set continuousPresent: true for game-streaming or desktop-capture hosts that must keep exposing a retained frame while the Electron source is static. It is false by default. DXGI gates continuous Windows presentation to the display instead of relying on millisecond timer precision.

const session = steamworks.overlay.startNativeOverlaySession({
  clientWidth: 1280,
  clientHeight: 720,
  minClientWidth: 640,
  minClientHeight: 480,
  minimumMenuScale: 1.25,
  frameRate: 60,
  continuousPresent: true,
  menu: [
    {
      label: "&File",
      items: [{ label: "E&xit", commandId: 1 }]
    }
  ],
  onInputEvent(event) {
    if (event.kind === "menuCommand" && event.commandId === 1) {
      app.quit();
      return;
    }
    // Forward other mapped input to gameWindow.webContents.
  }
});

function applyDisplayRate(displayFrequency: number | undefined) {
  const frameRate = Math.max(1, Math.round(displayFrequency || 60));
  gameWindow.webContents.setFrameRate(frameRate);
  session.setFrameRate(frameRate);
}

clientWidth and clientHeight are logical pixels. On Windows, Steam Bridge scales them to the primary display's DPI at creation and clamps the restored window to that display's usable work area. Moving the host between monitors preserves its logical size through the normal per-monitor-DPI transition. When both minClientWidth and minClientHeight are provided, the standalone Windows host enforces that minimum logical client size during edge and corner resize operations and clamps a smaller initial client request to that minimum. The two minimum dimensions must be provided together.

The optional menu tree creates a real Windows menu bar on a standalone host. Leaf commandId values are returned as menuCommand input events. The menu is removed in fullscreen, restored when returning to windowed mode, and changing it preserves the existing client size. By default Windows draws the menu at the monitor's configured scale. A consumer may opt into minimumMenuScale (from 1 through 4) when its product design needs a larger menu at low Windows scale settings. The floor affects only that menu: it does not override Chromium, the native title bar, the game client area, or the user's system settings, and a monitor with a higher effective scale still wins. The scaled path keeps the native HMENU, command routing, keyboard mnemonics, system colors, and Microsoft Active Accessibility metadata.

Steam Bridge owns the generic per-monitor-DPI mechanics and exact logical-to- physical client sizing. The application owns policy: its logical game size, minimum client size, and whether to request a menu scale floor. Do not use a process-wide Chromium force-device-scale-factor switch to compensate for one piece of native chrome; it also changes browser UI and content and creates two competing coordinate systems.

The native host owns ordinary Windows movement, resize, maximize, minimize, fullscreen, focus visibility, rounded-corner clipping, cursor state, and the Steam presentation surface. The consumer must map onInputEvent coordinates through the same aspect-fit transform and forward them to the offscreen webContents; release pressed input on capture or focus loss. This is an advanced path. Prefer createElectronSteamOverlay() unless the application needs a standalone game host.

Steam checkout cancellation can create a separate top-level Steam Dialog instead of drawing the confirmation inside the hooked swap chain. While a standalone host's Steam overlay is active, Steam Bridge narrowly recognizes a new visible, unowned Steam Dialog/SDL_app window from steamwebhelper.exe, makes it an owned popup of the game host, and keeps it centered with the host. Pre-existing Steam dialogs and managed attached presenters are excluded, and the original owner and rectangle are restored when the overlay or host ends. session.snapshot().nativeHostDiagnostics.steamDialog reports the baseline and adoption state for troubleshooting.

Steam Web API

Set STEAM_WEB_API_KEY for endpoints that require a publisher key, or provide an explicit key when creating or calling the client:

import steamworks from "steam-bridge";

const players = await steamworks.webApi.userStats
  .getNumberOfCurrentPlayers(480);

const news = await steamworks.webApi.news.getNewsForApp({
  appId: 480,
  count: 5
});

console.log({ players, news });

Keep publisher keys and private app, product, account, and transaction data out of source control and logs.

Packaging

The published package includes:

| Platform | Native addon | Valve runtime libraries | | --- | --- | --- | | Windows x64 | steam_bridge_native.win32-x64-msvc.node | steam_api64.dll, sdkencryptedappticket64.dll | | Linux x64 | steam_bridge_native.linux-x64-gnu.node | libsteam_api.so, libsdkencryptedappticket.so | | macOS Apple Silicon | steam_bridge_native.darwin-arm64.node | libsteam_api.dylib, libsdkencryptedappticket.dylib |

STEAMWORKS_SDK_PATH is needed only when building the native addon from source.

Electron packagers must keep the native addon and its matching Steam runtime libraries outside ASAR. The repository's packaged Electron example demonstrates the supported layout.

Windows application signing belongs to the final application distributor. It is not required to install or publish this package. Valve's runtime DLLs should retain their upstream signatures.

Steam Deck uses the Linux x64 package in both Game Mode and Desktop Mode.

macOS electron-builder helper

Steam overlays on macOS require the package's native launcher and Steam-compatible entitlements. Add the provided helper to electron-builder's afterPack hook:

const {
  prepareMacosSteamAppAfterPack
} = require("steam-bridge/electron-builder");

exports.afterPack = async (context) => {
  prepareMacosSteamAppAfterPack(context);
};

Use your normal Apple signing and notarization pipeline after preparation. The helper rejects Intel, Rosetta, and universal targets.

For the complete packaging matrix and platform procedures, see the Electron example guide.

Command-line helpers

The package exposes focused tools used by advanced checkout and packaging workflows:

  • steam-bridge-init-client-txn
  • steam-bridge-prepare-macos-app
  • steam-bridge-verify-macos-signing
  • steam-bridge-validate-checkout-target

Run a command with --help for its supported options. The full examples and operational guidance live in the Electron example guide.

Building from source

Repository development requires Node.js 22.13 or newer, Rust stable, and the Steamworks SDK through the normal steamworks-sys setup or STEAMWORKS_SDK_PATH.

npm install
npm run native:build
npm test

native:build links the newest matching Cargo artifact from either the target release directory or its deps directory, which keeps source-linked consumer testing from accidentally loading an older addon.

See Contributing for the full development and release checks.

Documentation

License

MIT