Skip to content

Headless

Checked against f15b998 on 2026-11-10. The files it covers are unchanged since.

Two hosts have no window. They run a page’s event loop on virtual time, render frames when asked and tap at coordinates, and they’re how niso’s own tests drive pages.

niso-run (crates/niso-quickjs/src/bin/niso-run.rs) runs scripts or an HTML page on QuickJS:

Terminal window
cargo run --release -p niso-quickjs --bin niso-run -- --dump --tap 60,140 examples/dist/counter.js
target/release/niso-run --page index.html --root . --boxes

The options that matter most:

  • --page FILE [--root DIR] [--url URL] loads a page as a browser does; with --root, http://localhost/ serves the files under DIR.
  • --serve URL=FILE answers a fetch with a file’s bytes, so a page that reads the network gets the same answer every run.
  • --tap X,Y renders a frame and taps there; --dump prints the document’s HTML; --boxes prints every element’s border box as JSON.
  • --render FILE records every frame’s render stream; --time reports the time to first frame, the time per tap frame and peak memory.
  • --missing lists every DOM member and global the page looked up that niso doesn’t have, which is the quickest way to see why a web app breaks.
  • --storage DIR keeps localStorage and IndexedDB between runs.
  • --hold keeps the process (and its workers) alive after --time until stdin closes, so a heap tool can inspect it.

It exits 1 on any uncaught exception. The full list is in the CLI reference.

niso-node (bindings/js/napi/niso-node.js) is the same thing on Node, Deno or Bun through the Node-API binding (crates/niso-napi), so a page runs on V8 or JavaScriptCore instead of QuickJS. It takes niso-run’s options, plus --live, which runs the page in real time until it has nothing left to do.

Terminal window
cargo build --release -p niso-napi
node --experimental-vm-modules bindings/js/napi/niso-node.js --dump --tap 60,140 examples/dist/counter.js

The binding’s details, and why it’s built on napi-sys, are in Node-API.

Running niso inside Node as a library for server-side rendering is possible through bindings/js/napi/niso.js, but no guide covers it yet.