$ rezi

Rezi

Rezi is a code-first terminal UI framework for Node.js and Bun. Build interactive terminal applications with a declarative widget API, automatic focus management, and native-backed rendering throug...

Rezi is a code-first terminal UI framework for Node.js and Bun. Build interactive terminal applications with a declarative widget API, automatic focus management, and native-backed rendering through the Zireael C engine.

import { ui, rgb } from "@rezi-ui/core";
import { createNodeApp } from "@rezi-ui/node";

const app = createNodeApp<{ count: number }>({
  initialState: { count: 0 },
});

app.view((state) =>
  ui.column({ p: 1, gap: 1 }, [
    ui.text("Counter", { style: { fg: rgb(120, 200, 255), bold: true } }),
    ui.row({ gap: 2 }, [
      ui.text(`Count: ${state.count}`),
      ui.button("inc", "+1", {
        onPress: () => app.update((s) => ({ count: s.count + 1 })),
      }),
    ]),
  ])
);

app.keys({ q: () => app.stop() });
await app.start();

Why Rezi?

Declarative and Type-Safe : Define your UI as a function of state. Full TypeScript support with strict typing for props, state, and events.

Rich Widget Library : 50+ built-in widgets covering forms, tables, trees, modals, code editors, command palettes, charts, and more.

Native Performance : Powered by the Zireael C engine with a binary protocol boundary. No virtual DOM diffing overhead.

Focus Management : Automatic keyboard navigation with focus zones, focus traps, and modal stacking.

Mouse Support : Click to focus and activate widgets, scroll wheel for lists and editors, drag to resize split panes, click backdrops to close modals. Detected automatically — no configuration needed.

Theming : Six built-in themes (dark, light, dimmed, high-contrast, nord, dracula) with semantic color tokens.

Keybindings : First-class support for modal keybindings with chord sequences (Vim-style g g, Emacs-style C-x C-s).

JSX Support : Write widget trees using JSX syntax with @rezi-ui/jsx — no React required. Getting started →

Performance : See benchmarks → for methodology, limitations, and the latest committed results.

Architecture

LayerPurpose
@rezi-ui/coreWidgets, layout, themes, forms, keybindings. No Node.js APIs.
@rezi-ui/nodeNode.js/Bun backend with worker and inline execution modes.
@rezi-ui/nativeN-API addon (napi-rs) binding to the Zireael C rendering engine.
@rezi-ui/jsxOptional JSX runtime for widget trees.

Getting Started

  • Install


    Install Rezi via npm and set up your first project.

    Installation

  • Quickstart


    Build a minimal Rezi application.

    Quickstart

  • Widgets


    Browse the complete widget catalog.

    Widget Catalog

  • Styling


    Themes, colors, and visual customization.

    Styling Guide

Core Concepts

State-Driven Rendering

Rezi applications are state-driven. You define a view function that returns a widget tree based on your application state:

type State = { items: string[]; selected: number };

app.view((state) =>
  ui.column({ gap: 1 },
    state.items.map((item, i) =>
      ui.text(i === state.selected ? `> ${item}` : `  ${item}`, {
        key: String(i),
      })
    )
  )
);

State Updates

Update state with app.update(). Updates are batched and coalesced for efficiency:

app.update((prev) => ({ ...prev, selected: prev.selected + 1 }));

Widget Composition

Widgets compose naturally. Container widgets like column, row, and box accept children:

ui.box({ title: "User Form", p: 1 }, [
  ui.field({ label: "Name", required: true, children:
    ui.input({ id: "name", value: state.name })
  }),
  ui.row({ gap: 2 }, [
    ui.button({ id: "submit", label: "Submit" }),
    ui.button({ id: "cancel", label: "Cancel" }),
  ]),
])

Focus and Navigation

Interactive widgets (buttons, inputs) automatically participate in focus navigation. Use Tab/Shift+Tab to move between focusable elements, or click any focusable widget with the mouse:

ui.column({}, [
  ui.button({ id: "first", label: "First" }),   // Tab stop 1
  ui.button({ id: "second", label: "Second" }), // Tab stop 2
  ui.input({ id: "name", value: "" }),          // Tab stop 3
])

Widget Categories

Primitives

Layout building blocks: text, box, row, column, spacer, divider

Form Inputs

Interactive controls: button, input, checkbox, radioGroup, select, field

Routing and wayfinding: tabs, accordion, breadcrumb, link, pagination

Data Display

Data presentation: table, virtualList, tree, richText, badge, tag, status

Overlays

Modal UIs: modal, dropdown, layer, layers, toast, focusZone, focusTrap

Layout Components

Complex layouts: splitPane, panelGroup, resizablePanel

Advanced Widgets

Rich functionality: commandPalette, codeEditor, diffViewer, logsConsole, filePicker

Charts

Data visualization: gauge, progress, sparkline, barChart, miniChart

Graphics Components

Graphics rendering: canvas, image, lineChart, scatter, heatmap

Feedback

User feedback: spinner, skeleton, callout, errorDisplay, empty

Learn More

On this page