Today I learned
How do I call Steamworks from a Vue + Electron game and get the overlay?
A Vue game in Electron can't talk to Steam on its own: steamworks.js is a native Node module, and the Steam overlay doesn't appear over Chromium's window by default.
Keep Steam in the main process and give Vue a small API through the preload script:
// main.js
const steamworks = require('steamworks.js')
const client = steamworks.init(2757440) // your App ID
ipcMain.handle('steam:unlock', (_e, id) => client.achievement.activate(id))
ipcMain.handle('steam:name', () => client.localplayer.getName())
steamworks.electronEnableSteamOverlay() // last line of main.js
// preload.js
contextBridge.exposeInMainWorld('steam', {
unlock: id => ipcRenderer.invoke('steam:unlock', id),
name: () => ipcRenderer.invoke('steam:name'),
})
In a Vue component it is then just await window.steam.unlock('FIRST_CARD'). The renderer keeps contextIsolation on, so you don't need the nodeIntegration: true shortcut from the README. When you package, unpack the .node binary from the asar (asarUnpack: ['**/*.node'] in electron-builder), or require fails in the shipped build only.
What I saw: everything worked in dev, the overlay never showed up, and it turned out electronEnableSteamOverlay() was missing. It adds the Chromium flags the overlay needs to hook the window.
Source: steamworks.js, Electron section