GioJSdocs
Deployment

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

bash
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

text
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 types

worker.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:

bash
node run.mjs

run.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:

ini
[Service]
ExecStart=node /srv/app/run.mjs
Restart=always
Environment=NODE_ENV=production

Cross-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:

bash
npm i @gio.js/server-linux-x64 --force   # install the target's binary package
gio build standalone --target linux-x64

Targets: 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

App-level .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.