SDK Channels: Alpha, Beta, Stable

The BodyLink SDK ships on three release channels. A channel is just which build of the SDK your game pins. Picking the right one is a two-line decision:

  • Develop on Alpha. Newest features, may break between releases.
  • Ship on Stable. Frozen, vetted, and what every published game and every production session runs.

The one rule that matters: a game submitted to production must pin Stable. New scaffolds already default to Stable, so if you never touch the channel you are always shippable.


The three channels

Channel What it is Use it for
Alpha The latest SDK — new APIs land here first. May break between releases without notice. Experimenting, trying a brand-new capability, giving feedback early.
Beta A release candidate stabilizing toward Stable. More settled than Alpha, not yet frozen. Validating your game against what's about to become Stable.
Stable Frozen and vetted. Changes are deliberate and versioned. This is what production runs. Everything you intend to publish. The default for new scaffolds.

Think of it as a maturity ladder: an API is born on Alpha, hardens on Beta, and freezes into Stable. The further right you pin, the fewer surprises.


Which channel to pin

Just starting / shipping soon   ->  Stable   (the default — do nothing)
        Trying a new/unreleased feature ->  Alpha    (opt in, expect churn)
        Pre-flighting the next Stable   ->  Beta
        Submitting to production        ->  Stable   (required)
        

A healthy workflow is: prototype a risky idea on Alpha, and before you submit, move back to Stable and re-run your build + validate so you ship against the frozen SDK the reviewer and players will actually run.


How a channel is actually pinned

There is one knob: the bodylink-platform dependency in your game's package.json. That is the only place a channel is pinned — there is no channel field in bodylink.game.json, and no separate lock file you edit. A channel is just which published bodylink-platform build that dependency resolves to (each channel publishes the same immutable SDK bytes under its own bodylink-platform-<version>.tgz tarball).

New scaffolds pin Stable — you configure nothing to be shippable. The scaffolder writes the Stable-aligned bodylink-platform dependency for you, so a fresh package.json looks like:

"dependencies": {
          "bodylink-platform": "file:./vendor/bodylink-platform-1.0.0.tgz"
        }
        

To develop against Alpha (or Beta) instead, point that one dependency at the channel's build — either at scaffold time or by editing package.json:

# at scaffold time: pass the channel's build to --platform
        npx create-bodylink-game myslug --platform ./vendor/bodylink-platform-<alpha-version>.tgz

        # or on an existing project: change the bodylink-platform dependency, then
        npm install
        

--platform takes a bodylink-platform-<version>.tgz (vendored under vendor/) or any npm dependency spec, and it is used verbatim as the bodylink-platform dependency. What you should see: npm install re-resolves bodylink-platform and updates your lockfile to that build. Your game now builds against that channel.

The pin is the dependency, nothing else. If you are ever unsure which build a channel publishes, follow the exact tarball/spec create-bodylink-game (or your SDK's release notes) prints for that channel — the default-Stable, production-requires-Stable rule holds regardless of version.


Why production requires Stable

Published games run in front of real players on real hardware, and every game in the catalog shares one host. Pinning Stable guarantees:

  • Reproducibility. The bytes you tested are the bytes that ship. Stable is immutable: it advances only through the gated Beta → Stable promotion, and that promotion is refused unless every check is green and the Director's approval is applied. Stable never moves under you between those events.
  • Vetting. Stable builds are the ones that have been through the soak and every gate; Alpha is the churning edge where fresh bytes land first and explicitly has not been vetted.
  • Integrity / back-compat. The runtime SDK is loaded cross-origin and SRI-pinned at export (SDK Delivery & SRI). The frozen legacy sdk-v1.js is defined as the Stable pointer — a pre-migration game that still loads /sdk/sdk-v1.js gets exactly what Stable serves, and that alias only advances when the gated Stable promotion advances. At submit, your pinned integrity is asserted against the Stable channel manifest (/sdk/stable/sdk-manifest.json), not against whatever was published most recently (the top-level pointer tracks Alpha).

If you submit a bundle pinned to a non-Stable channel, expect it to be rejected. Move to Stable, re-export, and resubmit.


Keeping your SDK up to date

The Stable channel manifest is the source of truth for the latest SDK version:

<origin>/sdk/stable/sdk-manifest.json
        

(The <origin> is the SDK delivery origin your game already loads the SDK from — see SDK Delivery & SRI.) The manifest is a small JSON document with a version field and a tarball field naming the exact bodylink-platform-<version>.tgz build for that channel.

Current channel state. Alpha and Beta both serve 0.7.5. Stable has deliberately not had its first gated promotion yet — so today the stable manifest path returns 404, and every updater (npm run sdk:update, the dev:hosted update check, the raw install below) falls back down the chain stable → beta → the legacy top-level /sdk/sdk-manifest.json pointer. Only a clean 404 moves down the chain; a network error fails loud instead of guessing. Nothing changes for you when the first Stable promotion lands — the same lookup simply starts returning Stable.

See what you're on:

npm ls bodylink-platform
        

Update in one command — scaffolds on SDK 0.7.5+ ship a verified upgrade that resolves the manifest, installs, and then checks the install actually took:

npm run sdk:update
        

On an older scaffold, take the tarball name from the manifest and install it straight from the channel path:

npm install <origin>/sdk/<tarball-from-manifest>
        # e.g. npm install <origin>/sdk/bodylink-platform-0.7.5.tgz
        

The tarball filename is not guessable from memory — always read it from the manifest, which is why the manifest is the source of truth. And after any raw install, verify with npm ls bodylink-platform — npm can satisfy a URL dependency from a stale lockfile and report success anyway. The full update model (clone vs GitHub, the truth-check, the recovery block) is in Getting Updates.

As of the dev-host update-notice release, npm run dev:hosted checks the manifest automatically when online and prints the exact upgrade command when you're behind. It never blocks your session — offline it just skips the check (set BODYLINK_SDK_UPDATE_CHECK=0 to turn it off entirely).

Stay on Stable unless BodyLink asks you to test something on Beta or Alpha.


Related pages