Runtime
WebJs runs on Node 24+ or Bun. The same app source runs on either; the framework picks a runtime-neutral path internally and only the listener shell, the type stripper, and a few built-ins differ. Deno is a planned target (the listener seam is already runtime-neutral), not yet supported. This page is the single reference for the per-runtime commands and differences; other pages link here rather than repeat them.
Related reading:
- Getting Started for scaffolding an app.
- No-Build Model for how source is served.
- Deployment for shipping a container.
Node vs Bun at a glance
| Area | Node 24+ | Bun | Deno |
|---|---|---|---|
| Install | npm install | bun install (required, like Node) | planned |
| Run | npm run dev / npm run start | bun run dev / bun run start | planned |
| Listener | node:http shell | native Bun.serve (about 1.9x req/s on the listening path) | planned |
| TypeScript stripping | built-in module.stripTypeScriptTypes | amaro | planned |
| SQLite driver | built-in node:sqlite | built-in bun:sqlite | planned |
| Hot reload | node --watch | bun --hot | planned |
| WebSocket | the ws library | native Bun.serve (bridged to the same API) | planned |
| 103 Early Hints | yes | no (Bun.serve has no informational-response API) | planned |
Either way the .ts stripping is position-preserving with no sourcemap, and the bytes the browser fetches are identical. The 103 Early Hints gap only costs a small first-load latency edge where your edge forwards 103, never correctness (the modulepreload hints still ship in the document head).
Node (the default)
Scaffold with webjs create my-app (Node is the default runtime). Then:
npm install npm run dev # or: npm run start
Node 24+ is required: the built-in TypeScript stripper (module.stripTypeScriptTypes, stable from Node 24) and recursive fs.watch need it. The CLI's assertNodeVersion() preflight enforces the floor.
Bun
Scaffold with webjs create my-app --runtime bun, or bun create webjs my-app (the runtime is auto-detected from the invoking package manager). Then:
bun install bun run dev # or: bun run start
A Bun app installs with bun install (like Node), then runs on Bun: its dev / start / db scripts force bun --bun, which overrides the webjs bin's Node shebang so the server runs on Bun, where it selects the native Bun.serve listener and strips types via amaro. The dependencies resolve from node_modules, the same as Node.
The install also gives editor type intelligence (the editor reads the .d.ts files in node_modules).
Install model and reproducibility
A Bun app commits a bun.lock (the Bun analog of package-lock.json) for reproducible, offline installs. The scaffold's Bun Dockerfile runs bun install and serves on Bun via CMD ["bun", "--bun", "run", "start"].
Future runtimes
The server's listener selection is a runtime-neutral seam: startServer chooses the Bun.serve shell on Bun and the node:http shell on Node through the same seam, which is designed to also host a Deno.serve or an embedded adapter later. When Deno support lands it will appear here. Edge runtimes with no filesystem are a separate, later target.