@w3booster/sdk · 0.2.0

Build on the live match.

One typed SDK for Warcraft III applications, dashboards, stream overlays, and in-game surfaces. W3Booster owns the difficult platform work; your app owns the experience.

Native ESMTypeScript includedFramework-neutralImmutable state
{ }Your appUI + product logic
authenticated launch
SDK@w3booster/sdkState + lifecycle + host
scoped realtime stream
W3PlatformIdentity + consentIIIMatchRecorder state

Quick start

From install to synchronized state.

Create the client, subscribe before startup, and render the complete lifecycle from one immediate store.

npm install @w3booster/sdk
import { createClient } from '@w3booster/sdk';

const lifetime = new AbortController();
const client = createClient({
  clientId: 'your_app_id',
  signal: lifetime.signal
});

client.lifecycle.subscribe(snapshot => {
  renderConnection(snapshot.status);
  if (snapshot.state) renderMatch(snapshot.state);
}, { signal: lifetime.signal });

await client.start();

// Component or page teardown:
lifetime.abort();
Your client ID is public. W3Booster generates the immutable ID when you create an app. Identity does not grant access: installation, enabled surfaces, scopes, and short-lived launch sessions are enforced by the platform.

start() resolves after the current connection has a synchronized state. Application code does not choose a WebSocket, carry credentials, apply patches, or implement reconnection.

Develop without W3Booster

Demo mode loads a representative fixture on demand and keeps demo code out of normal production startup.

const client = createClient({
  clientId: 'your_app_id',
  demo: true
});

await client.start();

Pass demo: { interval: 0, settings: { … } } for a deterministic fixture, or provide a complete demo state for focused UI tests.

Application model

One app. Up to three surfaces.

Every W3Booster app is a remotely hosted web application. Configure only the surfaces the product needs; hosting it yourself or through W3Booster does not change the SDK.

01Application

An interactive dashboard or workspace opened inside the client.

02Stream overlay

A transparent surface composed into the user’s stable OBS browser source.

03In-game overlay

A transparent surface aligned over Warcraft III by the desktop host.

  1. Enable Developer ModeUse the account menu in W3Booster, then open Apps → Developer.
  2. Create a private appAdd its name, public client ID binding, requested scopes, and at least one HTTPS surface.
  3. Build and testUse demo data for UI work and an owner-only local session for real match data.
  4. Invite testersPrivate invitation codes grant discovery; each tester still installs and enables the app.
Hash routing is reserved. W3Booster puts the short-lived launch credential in the URL fragment. The SDK consumes it and cleans the visible address. Use paths or query parameters for app routing.

Local development

Use real data without deploying.

Run Vite, Angular, or any web server on localhost. In your app’s developer page, choose Test locally and add the local URLs for the surfaces you are working on.

LOCALhttp://localhost:5173/Owner only · expires after 12 hours

The session installs and enables the app only for its owner and temporarily replaces only the chosen surfaces. Published metadata and other users do not change. Return to the published version at any time.

// Normal application code stays environment-free.
const client = createClient({ clientId: 'your_app_id' });

// Only platform developers normally force a backend.
const local = createClient({
  clientId: 'your_app_id',
  backend: 'local'
});

Cloud is the default. W3Booster may add ?backend=local or ?backend=cloud to a platform launch, and the SDK honors it automatically. Use backend: 'auto' only when intentionally trying local before cloud.

Frontend lifecycle

Render connection, freshness, and state together.

client.lifecycle is the preferred UI boundary. Its snapshot contains status, state, isSynchronized, and the current connection error. It publishes immediately and after every transition.

idleconnectingconnectedreconnecting
const client = createClient({
  clientId: 'your_app_id',
  retry: true,
  signal
});

client.lifecycle.subscribe(({ status, state, isSynchronized, error }) => {
  render({ status, state, fresh: isSynchronized, error });
}, { signal });

await client.start({ signal });
MethodResolves whenUse it for
start()A fresh synchronized state exists by defaultCanonical long-lived frontend startup
connect()The transport is connectedLow-level transport control
whenReady()Any hydrated state exists, including preserved reconnect stateWork that can use temporarily stale state
whenSynchronized()A fresh snapshot for the current connection existsRendering or actions that require a current baseline

Automatic reconnect preserves hydrated state for visual continuity but sets isSynchronized to false until a fresh snapshot arrives. State is recursively immutable and structurally shared, so unchanged branches preserve identity.

State and scopes

One hydrated, capability-aware match model.

The platform filters data before serialization. A scope expresses which branch an app may read; it is not a subscription tier. state.capabilities is the final runtime answer after the app’s granted scopes, account plan, and match context have been applied. Individual optional values can still be absent when the live source does not provide them.

All plans

Available to Basic and PRO accounts when scoped and present.

PRO / Observer

PRO during normal play; also available in observer match state.

ScopeState branchAvailabilityIncludes
match:readmatchAll plansLifecycle, time, map, mode, realm, observer/replay flags
players:readplayers[]All plansIdentity, race, team, color, position
stats:readplayers[].statsAll plansRank, league, wins, losses, main account
heroes:readplayers[].heroes[]PRO / ObserverLevel, XP, health, mana, abilities, inventory
upgrades:readplayers[].upgradesPRO / ObserverCompleted, active, and researching upgrades
resources:readplayers[].resourcesAll plansGold, lumber, supply, worker supply
controlgroups:readplayers[].controlgroupsAll plansFront units and group sizes
overlay:readoverlay.runtimeAll plansHUD scale, score, chat state, team-color preference
client.state.subscribe(state => {
  if (!state) return;

  const resources = state.capabilities.includes('resources')
    ? state.players[0]?.resources
    : undefined;

  renderResources(resources);
});
Display-ready conventions: game time is whole seconds excluding pauses; resources are normalized; win rates are percentages from 0–100; HUD scale is a CSS multiplier from 0.5–1.0; player start positions are map coordinates, not pixels.

Complete API data model

Everything W3Booster delivers.

This is the full hydrated MatchState<TSettings> exposed by @w3booster/sdk. The SDK validates it at runtime, freezes it recursively, and maintains it from snapshots and patches.

All plans

The field has no W3Booster subscription gate. Its scope and live source data may still make it optional.

PRO / Observer

The API removes the branch and its capability for a Basic account during normal player matches. Observer match state bypasses the plan gate.

Conditional

Optional because of match type, source availability, privacy, surface, or app configuration—not because it is necessarily PRO.

ROOT

MatchState<TSettings>

All plans
FieldTypeAvailabilityDescription
capabilitiesreadonly Capability[]AlwaysThe data branches actually available now: match, players, stats, heroes, upgrades, resources, controlgroups, and overlay.
matchMatchAll plansCurrent match metadata. Without match:read, the root remains present as a neutral no-match value.
playersreadonly Player[]All plansOne entry per player when at least one player-related scope is available; otherwise an empty array.
overlay?OverlayStateAll plansRecorder-derived overlay runtime when overlay:read is available.
application?ApplicationState<TSettings>App launchThe current application identity, surface, development state, and resolved user settings.
match:read

Match

All plans
FieldTypeRequiredDescription
idstringYesStable match identity; empty only while status is none.
status'starting' | 'running' | 'finished' | 'none'YesCurrent match lifecycle state.
gameTimenumberYesElapsed in-game time in whole seconds, excluding paused time.
modestringYesNormalized game mode such as 1v1, 2v2, or 4ffa.
map?stringNoHuman-readable, display-ready map name.
realm?stringNoMatch service or realm, for example W3Champions or Battle.net context.
paused?booleanNoWhether the current game clock is paused.
isReplay?booleanNoWhether W3Booster is reading a replay.
isReforged?booleanNoSelects Reforged versus Classic presentation assets.
isObserver?booleanNoWhether the active match state is an observer context. This is the API-side bypass for PRO-only match branches.
broadcasterPlayerId?stringNoPublic player ID associated with the broadcaster.
realBroadcasterPlayerId?stringNoUnderlying broadcaster player ID when presentation identity differs.
startedAt?stringNoISO-8601 match start timestamp.
players:read + related scopes

Player

All plans
FieldTypeScope / planDescription
idstringAny player branchStable identity within the match.
name?stringplayers:read · All plansDisplay name, subject to protected-match redaction.
race?Raceplayers:read · All plansrandom, human, orc, undead, or night-elf.
team?numberplayers:read · All plansZero-based Warcraft team ID.
colorId?numberplayers:read · All plansNative Warcraft player-color index.
startPosition?{ x: number; y: number }players:read · All plansWarcraft map coordinates, useful for ordering and relative placement—not screen pixels.
isAI?booleanplayers:read · All plansWhether this slot is computer-controlled.
mainAccount?MainAccountstats:read · All plansResolved main-account identity when one exists.
stats?PlayerStatsCollectionstats:read · All plansSolo, team, 4v4, and FFA ranking collections.
resources?Resourcesresources:read · All plansNormalized economy and supply values.
controlgroups?Record<string, ControlGroup>controlgroups:read · All plansControl-group number to its visible front unit and size.
heroes?readonly Hero[]heroes:read · PRO / ObserverFull hero state. Omitted and removed from capabilities when the plan gate applies.
upgrades?UpgradeStateupgrades:read · PRO / ObserverCompleted, active, and researching upgrade state.
Protected W3Champions 4-player FFA: the broadcaster remains identifiable. Other players are delivered with positional names such as Player 2, race random, and no mainAccount. This privacy filtering happens on the trusted server before the app stream is serialized.
stats:read

PlayerStats

All plans
FieldTypeDescription
winsnumberRecorded wins.
lossesnumberRecorded losses.
winRatenumberDisplay-ready percentage from 0–100.
rank?numberLeaderboard rank.
league?string | numberService-provided league or division.
level?numberService-provided ladder level.

PlayerStatsCollection may contain solo?, team?, team4?, and ffa?. Use preferredStats() from @w3booster/sdk/standard-game to select the best entry for the match mode.

stats:read

MainAccount

All plans
FieldTypeDescription
namestringResolved main-account name.
country?stringNormalized country identifier; resolve its flag with @w3booster/sdk/assets.
mainRace?RaceMain-account race when known.
resources:read

Resources

All plans
FieldTypeDescription
goldnumberCurrent gold.
lumbernumberCurrent lumber.
supplynumberUsed supply.
supplyCapnumberCurrent supply cap.
workerSupply?numberSupply committed to workers.
controlgroups:read

ControlGroup

All plans
FieldTypeDescription
frontunitstringRawcode of the group’s front unit or building.
sizenumberNumber of units/buildings assigned to the group.
heroes:read

Hero, HeroAbility, and ValuePool

PRO / Observer
ObjectFieldTypeDescription
HeroidstringStandard-game hero rawcode used for metadata and artwork lookup.
namestringHuman-readable hero name.
levelnumberCurrent derived hero level.
experience?numberTotal hero experience.
hitpoints?ValuePoolCurrent and maximum hit points.
mana?ValuePoolCurrent and maximum mana.
abilities?readonly HeroAbility[]Learned abilities and activation timing.
inventory?readonly string[]Item rawcodes in slot order.
HeroAbilityidstringStable identity within the owning hero.
namestringStandard-game ability rawcode.
levelnumberLearned ability level.
lastActivation?numberMilliseconds on the match game-time clock; use the cooldown helper instead of interpreting it directly.
ValuePoolcurrentnumberCurrent value.
maxnumberMaximum value.
upgrades:read

UpgradeState

PRO / Observer
FieldTypeDescription
upgradesreadonly CompletedUpgrade[]Completed research and upgrade levels.
activereadonly ActiveUpgrade[]Currently relevant active upgrades.
researchingreadonly ResearchingUpgrade[]Research currently in progress.
Upgrade fieldTypeDescription
namestringCanonical four-character standard-game upgrade rawcode.
levelnumberExplicit normalized upgrade level.
gametimenumberUnix timestamp in milliseconds when W3Booster observed the upgrade.
researchStart?stringISO-8601 timestamp on researching upgrades.
researchFinish?stringISO-8601 estimated completion timestamp.
overlay:read

OverlayRuntimeState

All plans
FieldTypeDescription
chatbarOpen?booleanWhether the in-game chat bar is open.
hudScale?numberCSS multiplier normalized from 0.5–1.0.
matchScore?{ wins: number; losses: number }User-controlled nested match score.
teamColors?booleanNative versus simplified team-color preference.
Authenticated app context

ApplicationState<TSettings>

App launch
FieldTypeDescription
clientIdstringThe current app’s public immutable identifier.
settingsDeepReadonly<TSettings>Resolved per-user settings for this app only.
surface?'application' | 'streamOverlay' | 'ingameOverlay'The surface W3Booster launched.
development?booleanWhether the owner’s temporary local override is active.

Schema-dependent A settings field can declare requiresPlan: 'pro'. That prevents Basic users from changing the setting; it is an app-settings control, not a data entitlement. The resolved default or previously saved value can still be delivered.

Optional does not mean PRO. Most ? fields are conditional because no match is active, the source did not provide the value, the app lacks that scope, the current surface does not use it, or server-side privacy filtering applies. Only the hero and upgrade branches have a platform data-plan gate today.

Events and selectors

Observe the view model you need.

Use state subscriptions for complete rendering, watch() for one derived value, and domain events for meaningful changes after the initial snapshot.

const stopClock = client.state.watch(
  state => state?.match.gameTime ?? null,
  seconds => drawClock(seconds)
);

client.on('match.started', ({ match }) => showMatch(match));
client.on('player.resources.changed', ({ player, resources }) => {
  updateEconomy(player.id, resources);
});
client.on('hero.inventory.changed', ({ player, inventory }) => {
  updateInventory(player.id, inventory);
});

The initial snapshot emits state.ready and state.changed. It does not synthesize match.started for a match that was already running.

Pure selectors

import {
  broadcasterPlayer,
  groupPlayersByTeam,
  matchScore,
  playerRelationship
} from '@w3booster/sdk/selectors';

const broadcaster = broadcasterPlayer(state.match, state.players);
const teams = groupPlayersByTeam(state.players);
const score = matchScore(state);

Selectors are framework-free and never mutate state. The namespace also includes stable fallbacks, identity helpers, broadcaster-first teams, relationships, inventory, resources, upgrades, and overlay runtime.

Standard-game data and assets

Import only the Warcraft knowledge you use.

Rules, icons, and cooldown metadata have separate entry points. This keeps lightweight apps small while preserving a combined objects namespace for compatibility.

import * as game from '@w3booster/sdk/standard-game';
import * as icons from '@w3booster/sdk/standard-game/icons';
import * as cooldowns from '@w3booster/sdk/standard-game/cooldowns';

const heroIcon = icons.heroIconUrl(hero, {
  graphics: state.match.isReforged ? 'reforged' : 'classic'
});
const cooldown = cooldowns.abilityCooldown(ability, state.match.gameTime);
const clock = game.formatGameTime(state.match.gameTime);
const progress = game.heroExperienceState(hero.experience);

The standard-game namespace covers race labels, modes, player colors, statistics selection, game-time formatting, day/night state, hero progression, health/mana ratios, observer ordering, and presentation colors. Hosted Classic and Reforged icons resolve from the versioned static asset catalog; artwork is not bundled with npm.

Standard game is not every custom map. Blizzard-shipped melee and campaign metadata can be changed or replaced by a custom map. Prefer live recorder values whenever the map supplies them.

Typed settings

Define settings once. Keep UI and types together.

Build the schema in W3Booster and let the client render consistent controls. The SDK can generate a checked-in TypeScript binding with the exact schema, defaults, scopes, client ID, and a managed application runtime.

npx w3booster-settings init app_your_id
npm run w3booster:sync
npm run w3booster:check

Commit src/w3booster.generated.ts. This keeps editor types and offline builds deterministic while making schema changes visible in code review.

import { w3boosterApp } from './w3booster.generated';

const runtime = w3boosterApp.createRuntime({ retry: true });

runtime.lifecycle.subscribe(snapshot => {
  renderMatch(snapshot.state, { fresh: snapshot.isSynchronized });
  renderSettings(snapshot.settings);
  renderHostActions(snapshot.host);
});

await runtime.start();
await runtime.stop();

The managed runtime resolves partial user settings over database defaults and publishes settings atomically with state and host capabilities. Lower-level tools remain available from @w3booster/sdk/settings.

Host actions

Ask the workspace. Await the result.

Embedded app surfaces can open or close windows, change Match Vision scores, persist typed settings, report their height, and issue app-specific commands. Every asynchronous action waits for a host acknowledgement.

import { canUseHostCapability } from '@w3booster/sdk';

client.host.lifecycle.subscribe(host => {
  setCompactEnabled(canUseHostCapability(host, 'window:open'));
});

await client.host.openWindow({
  path: '?view=compact',
  width: 520,
  height: 620
});

const saved = await client.host.setSetting(
  'observer.layout',
  'wide',
  { signal, timeout: 3000 }
);

Use host.can(capability) for imperative code or the reactive host lifecycle for UI. Capability discovery distinguishes pending, known, legacy, and unavailable hosts. Action cancellation raises AbortError; rejected execution raises HostActionError; missing or timed-out hosts raise ConnectionError.

Framework integration

Use the store your framework already understands.

The SDK has no frontend framework dependency. Its immediate stores map directly to Angular signals and RxJS; a small React subpath implements the complete useSyncExternalStore contract.

React@w3booster/sdk/react
const store = createReactStore(client.lifecycle, {
  getServerSnapshot: () => ({
    status: 'idle', state: null,
    isSynchronized: false, error: null
  })
});

const snapshot = useSyncExternalStore(
  store.subscribe,
  store.getSnapshot,
  store.getServerSnapshot
);
Angularsignal()
const lifecycle = signal(client.lifecycle.get());

client.lifecycle.subscribe(
  snapshot => lifecycle.set(snapshot),
  { signal: lifetime.signal }
);

Errors and diagnostics

Separate startup failure from runtime issues.

Catch permanent startup errors around start(). Subscribe to structured issue events for recoverable connection, protocol, recorder, and listener problems that should not turn healthy match data into a failed UI.

import {
  classifyW3BoosterError,
  createClient
} from '@w3booster/sdk';

const client = createClient({ clientId: 'your_app_id' });

client.on('issue', issue => {
  console.warn(issue.source, issue.recoverable, issue.error);
});

try {
  await client.start();
} catch (error) {
  const info = classifyW3BoosterError(error);
  switch (info.kind) {
    case 'permission': showOpenFromW3Booster(); break;
    case 'connection': showOffline(info.code); break;
    case 'abort': break;
    default: report(info.error);
  }
}
PermissionRequiredError

Open the installed, enabled app from W3Booster or renew its local session.

ConnectionError

Inspect the stable code such as UNAVAILABLE, CONFIGURATION, or STATE_TIMEOUT.

ProtocolError

Use the code and details. Recoverable invalid data resynchronizes; permanent incompatibility closes the stream.

HostActionError

The authenticated workspace received an action but rejected its execution.

Publish

Private first. Reviewed before discovery.

  1. Complete the store listingAdd a clear description, surfaces, screenshots, source or homepage links, and requested scopes.
  2. Test every surfaceCheck application, stream, and in-game behavior; disabled states; reconnects; and missing optional data.
  3. Request reviewW3Booster reviews the record, hosted behavior, scope use, and user experience.
  4. Make it publicAfter approval, users can discover and install it from the App Store. Metadata edits do not require another review.

Installation and enabling are separate platform states. Disabling preserves the app in the user’s library; uninstalling removes the grant. Revocation closes affected streams immediately.

Package reference

Focused entry points, one compatibility policy.

@w3booster/sdk

Client, lifecycle, hydrated data model, events, host facade, errors.

@w3booster/sdk/selectors

Pure match, player, team, resources, score, and identity derivations.

@w3booster/sdk/app

Generated application bindings and managed application runtimes.

@w3booster/sdk/settings

Schema validation, defaults, resolution, and binding generation.

@w3booster/sdk/standard-game

Lightweight Warcraft III rules and presentation helpers.

…/standard-game/icons

Classic/Reforged asset URLs and match-aware resolvers.

…/standard-game/cooldowns

Ability cooldown metadata and state derivation.

@w3booster/sdk/assets

Hosted shared-asset and country-flag URL helpers.

@w3booster/sdk/react

Dependency-free adapters for React external stores and selectors.

@w3booster/sdk/testing

Demo transports and custom transport types for tests.

Platform-only: @w3booster/sdk/compositor authenticates the stable browser source and loads enabled overlay apps. Ordinary applications do not import it and never receive browser-source credentials.