Uniview

Examples

Runnable demos — ports of real terminal apps — and how the screenshots are made

lazygit — in both frameworks

The lazygit demo: status, files, branches, commits and stash panels down the left, a log panel on the right, a keybinding bar at the bottom
pnpm --filter @uniview/tui-lazygit-demo  dev   # React
pnpm --filter @uniview/tui-lazygit-solid dev   # Solid

The same application, written twice. 15/0 focus a panel; / move the branch or commit selection; the log panel mirrors the selected commit.

These two exist to be compared. Their rendered frames are byte-identical — the proof that the framework sits above the renderer, not inside it.

Charts — an oha-style dashboard

A load-test dashboard: progress gauge, request stats, status-code distribution, requests-per-second bar chart, response-time histogram
pnpm --dir examples/tui/charts-demo dev

A simulated load test: gauge, bar chart, histogram, and live stats.

2048 — played by a trained agent

2048 in the terminal showing the 2048 tile reached, score 20904, a score-curve sparkline, and an AI panel reading depth 2
pnpm --filter @uniview/tui-2048 build
pnpm --filter @uniview/tui-2048 start

↑↓←→ to play, a to hand it to the AI, s to step it once, +/- for search depth.

The AI is not a heuristic. It is an n-tuple network (5 patterns, 8-way dihedral symmetry, ~84 MB of trained weights) driving expectimax over afterstates. At depth 1 it reaches 2048; at depth 2 it reaches 4096. The engine is verified against the reference implementation — 816 golden move cases, and V(board) reproduced across six different grid shapes.

The weights are not in the repository. The game runs without them — it is fully playable by hand, and the AI panel simply says so.

Note what the board is made of: colored Boxes and centered Text, and the score curve is the same Sparkline the charts demo uses. A game needed no new render primitive.

Ports of real terminal apps

The next five re-implement well-known Rust/ratatui TUIs as uniview plugins, to prove the framework carries a real app. Every one is pure plugin code — zero renderer changes — and each keeps its interesting logic in a small, pure, unit-tested core.

htop — a live system monitor

A system monitor: a CPU/MEM history line chart and a memory meter across the top, a per-core CPU bar chart, and a process table sorted by CPU%
pnpm --filter @uniview/tui-htop-demo dev

/ move; C / M / T / P / N sort the table by CPU, memory, time, PID or name (press again to flip). A CPU/MEM history LineChart and a memory Gauge sit above a per-core BarChart and a sortable, virtualized Table.

The data is real — CPU% from differencing os.cpus() snapshots, memory from os.freemem()/totalmem(), processes from ps — sampled on an interval. That is exactly the Node/Bun bridge-plugin story: a sandboxed Worker can't read these, a plugin with real I/O can. The parsing and math (computeCpuPercent, parsePs, sortProcesses) are pure and unit-tested.

scope — an audio oscilloscope

An audio scope: a braille oscilloscope trace of two waveforms over time, with mode tabs and a signal readout
pnpm --filter @uniview/tui-scope-demo dev

Modelled on scope-tui. Tab (or 1/2/3) switches between oscilloscope, vectorscope and spectroscope, each drawn on a braille Canvas fed by a synthetic stereo signal. The frame loop is useAnimation() over the host frame clock — every frame regenerates the signal and repaints locally, no per-frame RPC. The DSP (a hand-rolled radix-2 FFT + Hann window) is pure and tested against a naive DFT.

csv — less for CSV

A CSV pager: a table of world cities with rank, city, country, population and founded columns, a scrollbar, and a status bar
pnpm --filter @uniview/tui-csv-demo dev                 # bundled sample
pnpm --filter @uniview/tui-csv-demo dev -- data.csv     # a real file

A csvlens-style pager. / pick the sort column (marked ), s sorts it, / finds by regex (n/N to jump), & filters rows. It reuses the framework Table nearly as-is — virtualized rows, column layout, a cursor — with the CSV parser and natural-order comparator as a pure, tested core.

openapi — an API explorer

An OpenAPI browser: an operations list on the left, operation details top-right, and a collapsible JSON-Schema tree with $ref drill-down bottom-right
pnpm --filter @uniview/tui-openapi-demo dev

A browse-only openapi-tui. Tab switches panes, / move, / expand a schema node, f filters by tag. The heart is a collapsible JSON-Schema Tree with inline $ref drill-down and a cycle guard (Category.parent ↻), built by a pure schemaToTree converter over a bundled Petstore spec.

image — a raster viewer

A terminal image viewer showing a colorful Mandelbrot set rendered as half-block cells
pnpm --filter @uniview/tui-image-demo dev                    # synthetic gallery
pnpm --filter @uniview/tui-image-demo dev -- photo.png       # a real image

An RGBA raster painted as half-block cells — fg = the upper pixel, bg = the lower pixel, two pixels per cell at full truecolor. This is the universal, protocol-free image path (the fallback yazi/chafa use), and it needs no new primitive: it emits the same styled-lines tree as the charts. Real files decode via Bun.Image + pngjs.

How these screenshots are made

Each example has a snapshot script. It runs the real application and swaps exactly one line — AnsiCellSurface becomes SvgCellSurface — then writes toSVG() into docs/public/tui/.

pnpm --filter @uniview/tui-2048 snapshot
# wrote docs/public/tui/2048-solid.svg (17481 bytes, won=true, score=20904)

So the images are real frames of the real component tree, not mock-ups that can quietly drift from the code. They are SVG, so they stay crisp at any zoom — and being cells, they are also just text underneath.

Snapshots are seeded where the app is random (2048 picks its spawns from an injected RNG), so re-running the script does not churn the diff.

On this page