Standalone Deploys
One folder, one command. Build a self-contained deploy directory, copy it to any server that has Node installed, and run node run.mjs. No node_modules, no npm install, no toolchain on the host.
A normal GioJS deploy runs your app from source: the server compiles and scans routes at startup, which means Node, your dependencies, and npm install all live on the production host. A standalone build moves all of that to build time. It packages the Rust server binary and your entire Node side - React included - into a single directory that runs on a bare server. tsx and esbuild do their work during the build and are never loaded at runtime.
Build
gio build standalone [--out <dir>] [--target <platform>]
--out <dir> output directory (default: ./standalone)
--target <platform> cross-build for another platform (see below)(Plain gio build just prints an explanation - normal deploys have no build step; the server renders on demand. standalone is the packaging mode.)
What you get
standalone/
server(.exe) the Rust HTTP server binary for the target platform
worker.js the entire Node side bundled to one file (React included)
run.mjs launcher: spawns the server wired to worker.js and static/
static/ prebuilt hydration chunks
public/ your public assets (if any)
gio.toml your server config (if any)
.gio/ manifest (deployment ID input) and generated route typesworker.js is generated from your discovered app modules - every page, layout, route.ts handler, gio.config, and middleware file is statically imported and bundled, so boot performs no filesystem discovery and no TypeScript transform. The hydration chunks in static/ are built ahead of time too.
Deploy
Copy the folder to any server with Node 20+ installed, then:
node run.mjsrun.mjs spawns the server binary with the environment wired up (NODE_ENV=production by default, worker and static paths pointed into the folder), forwards SIGINT/SIGTERM for clean shutdown, and passes any extra arguments through to the server.
As a systemd service, the whole unit is one line of ExecStart:
[Service]
ExecStart=node /srv/app/run.mjs
Restart=always
Environment=NODE_ENV=productionCross-building for another platform
By default the build packages the server binary for the machine you build on. To build on one platform and deploy to another (say, build on Windows or macOS, deploy to a Linux VPS), pass --target:
npm i @gio.js/server-linux-x64 --force # install the target's binary package
gio build standalone --target linux-x64Targets: linux-x64, linux-x64-musl, linux-arm64, win32-x64, darwin-x64, darwin-arm64. The platform package must be installed - if it isn't, the build fails with the exact npm i command to run.
Limitations
.css imports (import './styles.css' from a page or layout) are not carried into the standalone bundle in this version. Serve stylesheets from public/ and link them from a layout instead.When to prefer a normal deploy
A standalone folder is frozen at build time: framework fixes only reach it when you rebuild and re-copy. A normal deploy (npm install on the host, run gio) keeps you on the update path - npm update picks up new GioJS releases - and needs no build step at all. Prefer standalone when the target host should stay minimal (only Node, no npm registry access, no node_modules); prefer a normal deploy when you want the easiest upgrades. See Deploying for the normal path.