Steam

0 in apps16 in games

Games shipping on Steam get a built-in Steamworks bridge: the steam namespace lets your game's JavaScript unlock achievements, read the player's identity, save to Steam Cloud, and set rich presence, with no native code, no Steam headers, and no node integration in your page. Steamworks runs in the app's main process; your game only ever sees typed promise calls.

Turn it on in the dashboard's Steam section (games only): enable the integration and enter your Steam App ID from the Steamworks partner site. Use App ID 480 (Spacewar, Valve's test app) to develop before your app is approved.

Every method degrades the same way: when Steam isn't available; the integration is off, this is a non-Steam build, or the Steam client isn't running, calls resolve { success: false, reason } instead of throwing. One build of your game code works on Steam and everywhere else.

Debugging: start with getStatus

const status = await window.deskifier.steam.getStatus();
// { success, available, appId, reason? }
// reason is one of: 'disabled' | 'stripped' | 'not-running' | 'init-failed'

disabled: Steamworks is off in the dashboard. stripped: this build was made without the integration. not-running: the Steam client isn't running, or the logged-in account doesn't own the app.

The player

const { name, steamId64, level } = await window.deskifier.steam.getPlayer();

steamId64 is a string (the id doesn't fit in a JS number).

Achievements

Achievements are defined in the Steamworks partner site; you call them by API name:

await window.deskifier.steam.activateAchievement({ name: 'ACH_FIRST_WIN' });   // shows the toast
await window.deskifier.steam.clearAchievement({ name: 'ACH_FIRST_WIN' });      // re-lock (testing)
const { activated } = await window.deskifier.steam.isAchievementActivated({ name: 'ACH_FIRST_WIN' });

Stats

await window.deskifier.steam.setStat({ name: 'races_won', value: 12 });
await window.deskifier.steam.storeStats();   // persist a batch to Steam's servers
const { value } = await window.deskifier.steam.getStat({ name: 'races_won' });

Cloud saves

Steam Cloud keeps a save file synced across the player's machines:

await window.deskifier.steam.cloudWrite({ name: 'save.json', content: JSON.stringify(save) });
const { content } = await window.deskifier.steam.cloudRead({ name: 'save.json' });
await window.deskifier.steam.cloudDelete({ name: 'save.json' });
const { enabledForAccount, enabledForApp } = await window.deskifier.steam.cloudIsEnabled();

Rich presence

What friends see you doing in their friends list:

await window.deskifier.steam.setRichPresence({ key: 'steam_display', value: '#StatusFull' });
await window.deskifier.steam.setRichPresence({ key: 'text', value: 'Sector 7, wave 12' });
await window.deskifier.steam.clearRichPresence();

Rich presence display formats are configured in the partner site's localization files.

Steam overlay

The Shift+Tab overlay works when enabled in the dashboard's Steam section and the game is launched through Steam. You can also open its dialogs directly:

await window.deskifier.steam.activateOverlay({ dialog: 'achievements' });
await window.deskifier.steam.activateOverlayToWebPage({ url: 'https://example.com/patch-notes' });

Steam builds are unpacked depot content, never Mac App Store builds. The two are mutually exclusive channels, and Deskifier keeps Steam code out of MAS builds automatically.

Publishing to Steam

Building your depots and pushing them with SteamPipe has its own guide, covering the builder account, depot IDs, branches, and what to do when a session lapses: Publishing to Steam.