WARCRAFT FOREVER / DEVELOPERS
Headless builds and modules
Decode, validate, export, and compare builds without mounting a calculator.
Use the same rules as the interactive calculator from a browser or Node process. The headless module has no React or DOM dependency:
import { createClient } from 'https://warcraftforever.com/talents/headless.mjs';
const talents = createClient();
const layout = await talents.definition({ class: 'paladin' });
const result = await talents.validate({
class: 'paladin',
revision: layout.revision,
maxLevel: 30,
allocation: { 'paladin-holy-divine-strength': 5 }
});
console.log(result.valid, result.complete, result.pointsRemaining);
const encoded = await talents.encode({
class: 'paladin',
revision: layout.revision,
maxLevel: 30,
allocation: result.allocation,
format: 'blizzard'
});
const decoded = await talents.decode({ class: 'paladin', maxLevel: 30, code: encoded.code });
const difference = await talents.diff({
class: 'paladin',
maxLevel: 30,
before: {},
after: decoded.allocation
});
console.log(difference.pointDelta, difference.changes);validate takes exactly one of code or allocation. Invalid builds return valid: false and structured issues. encode and diff reject invalid allocations with SdkError.code === 'invalid-build'. Legality and completeness are distinct: a partial allocation may be valid. definition and result objects are detached from the client’s cache.
encode supports blizzard (the default for talents), deprecated compact, and structured. String exports have a code; structured exports have a build. See build exports for the native-format verification boundary and compatibility rules. diff accepts allocations or strings for both sides, interprets both against one class and revision, and returns changed ranks and a point delta.
Dataset pins
Use discovery to obtain the talents dataset ID, then call createClient({ dataset }). The descriptor fixes the definition and revision registry. Store the dataset, class and revision beside saved strings when you need reproducible interpretation. SDK release IDs, dataset IDs, and layout revisions are separate contracts.
Module and TypeScript entry points
Every capability has /latest.js for script tags and /latest.mjs for ES modules: talents, legacy, tooltips, catalog, and data. ES modules do not create WarcraftForever or $WF globals. Talents and Legacy also have /headless.mjs for environments without a DOM.
Browser imports use the serving module’s origin for assets and API reads. Native Node does not load HTTPS modules by default: download a pinned headless module and import the local .mjs file, or bundle the module as part of your application. A downloaded module defaults to https://warcraftforever.com; createClient({ origin }) selects another deployment. No npm package is published by this interface.
Adjacent .d.mts files provide TypeScript declarations. For a local download, preserve the declaration’s relative dependency tree under releases/<version>/types/; copying only the root declaration is insufficient. /types.d.ts is the script-type entry; include each loaded capability’s entry to compose its WarcraftForever and $WF declarations, or use the matching /releases/<version>.d.ts for a pinned script. Module and headless declarations do not declare these globals. The portal’s type reference is generated from the same source.
Errors
Check error.code rather than parsing messages. Headless errors distinguish invalid options, unknown classes, unsupported revisions/formats, invalid builds, and unavailable or inconsistent data. Build errors can carry details with validation issues. Data API failures use the same SdkError shape; HTTP errors return { error: { code, message } } and are never cached as successful data.