Node/Bun backend¶
The Node/Bun backend owns:
- native engine execution mode (
auto|worker|inline) - frame scheduling and buffer pooling
- transfer of drawlists to the engine and event batches back to core
Most apps should construct the app via:
import { createNodeApp } from "@rezi-ui/node";
const app = createNodeApp({
initialState: { count: 0 },
config: {
executionMode: "auto",
fpsCap: 60,
maxEventBytes: 1 << 20,
},
});
createNodeApp is the recommended path because it keeps core/backend config
knobs aligned:
maxEventBytesis applied to both app parsing and backend transport buffers.fpsCapis the single scheduling knob.executionMode: "auto"resolves to inline whenfpsCap <= 30, otherwise it prefers worker mode and falls back to inline for headless runs without a TTY ornativeShimModule.
Development hot reload:
createNodeApp({ hotReload: ... })watches source files and hot-swaps either:- widget views via
app.replaceView(...), or - route tables via
app.replaceRoutes(...)for route-managed apps. - lifecycle is automatic: watcher starts/stops with
app.start()/stop()/run(). app.hotReloadexposes manualreloadNow()when needed.- low-level
createHotStateReload(...)remains available for advanced manual wiring. - Raw draw mode remains excluded.
Execution mode details:
auto(default): select inline for low-fps workloads (fpsCap <= 30); otherwise prefer worker mode and fall back to inline when no TTY ornativeShimModuleis available.worker: force worker-thread engine execution. With the real native addon this requires an interactive TTY; test harnesses can providenativeShimModuleinstead.inline: run the engine inline on the main JS thread.
For headless snapshots and unit tests, prefer createTestRenderer() /
@rezi-ui/testkit over the real native backend.
NO_COLOR support:
- If
NO_COLORis present in the process environment,createNodeApp(...)forces a monochrome theme (no semantic color accents). createNodeApp(...)returns an app object withapp.isNoColorso app code can detect this mode.
import { createNodeApp } from "@rezi-ui/node";
const app = createNodeApp({ initialState: {} });
if (app.isNoColor) {
// Optional app-level behavior for colorless terminals/CI.
}
Screen mode (alt vs inline):
screen.modeselects the terminal presentation:"alt"(default, full-screen on the alternate buffer) or"inline"(a bounded region ofscreen.inlineRowsrows on the primary screen with scrollback preserved above and the final frame left in scrollback on exit).screen.inlineRows(1..1024) is required with"inline"and rejected otherwise; the effective viewport is clamped to the live terminal height.- Unrelated to
executionMode: "inline"(engine-on-main-thread); the two options compose freely. - See the Screen Modes guide and
examples/inline-statusfor a runnable app.
const app = createNodeApp({
initialState: {},
config: {
screen: { mode: "inline", inlineRows: 9 },
},
});
Inline screen-mode runtime APIs (engine ABI 1.4.0+):
app.printAbove(view, opts?)renders a standalone widget tree and commits it into terminal scrollback above the region (backendcommitScrollback(drawlist, rows)).app.setInlineRows(rows)changes the inline viewport height at runtime (backendsetInlineRows(rows)), re-sending the created runtime config with the new height.- Both reject unless the backend was created with
screen.mode: "inline".
Emoji width policy:
emojiWidthPolicykeeps core text measurement and native rendering aligned.- Allowed values:
"auto"(default): resolve from native overrides/env, optional probe, then fallback to"wide"."wide": emoji clusters occupy at least 2 cells."narrow": emoji clusters occupy at least 1 cell.- Native overrides (
nativeConfig.widthPolicy/width_policy) must match explicit policy values. - Optional terminal probe is disabled by default and only runs when
ZRUI_EMOJI_WIDTH_PROBE=1(opt-in to avoid startup input races).
Manual composition (advanced):
- Prefer
createNodeApp()for typical apps so related runtime knobs cannot drift. - If you compose manually with
createNodeBackend()+createApp()(@rezi-ui/core), Rezi throws deterministicZRUI_INVALID_PROPSerrors when cursor/event/fps settings conflict.
Next: Worker model.