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.
}
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.