Desktop and Mobile
The package is plain TypeScript with no DOM assumptions, so it runs unchanged in an Electron renderer, an Electron main process, and a Capacitor WebView. Nothing here is web-only.
The One Boundary
thetowersdk/node is the only entry point that needs Node, because it is the one that reads
files. That is the boundary you want anyway: the decoder belongs on the side that is allowed to touch
the filesystem, and everything else — catalogs, formulas, builders, charts, formatting — runs happily
in a renderer or a WebView.
// Renderer or WebView: catalogs and formulas, no filesystem.
import { LAB_CATALOG } from 'thetowersdk/data'
import { computeWaveBaseHealth } from 'thetowersdk/mechanics'
// Main process only: this one reads a file.
import { decodePlayerInfoSaveBytes } from 'thetowersdk/node'Pin The Toolchain
Electron and Capacitor builds are sensitive to the toolchain that produced them, so pin it with the hash corepack verifies against:
{
"packageManager": "pnpm@10.8.1+sha512.c50088ba…",
"engines": { "node": ">=22 <23" }
}Reading A Save On Each Platform
On desktop, the save is a file and thetowersdk/node reads it directly from the main
process. On mobile, a connected device can hand it over without the player exporting anything —
see Save Files for the whole route, including the
bridge.
Further Detail
The main/renderer split, the IPC boundary, running the bridge in-process, and what is available on
mobile are covered in docs/DESKTOP_AND_MOBILE.md in the repository.