Terminal Context
The Terminal context renders elements to a character-based terminal using Unicode braille patterns (U+2800–U+28FF). Each terminal cell encodes a 2×4 grid of sub-pixel dots, giving 8× the resolution of plain text. It supports ANSI truecolor for full-color output.
Demo
The demo below renders a bar chart live in an xterm.js terminal widget — the same @ripl/terminal code that runs in Node.js:
Installation
The terminal context is provided by the @ripl/terminal package. For Node.js usage, also install @ripl/node:
npm install @ripl/terminal @ripl/nodeUsage
Node.js
Import from @ripl/node to automatically configure the runtime factory:
import '@ripl/node';
import {
createCircle,
createNodeOutput,
createRect,
createTerminalContext,
} from '@ripl/node';
const output = createNodeOutput();
const context = createTerminalContext(output);
createCircle({
fill: '#3a86ff',
cx: context.width / 2,
cy: context.height / 2,
radius: 40,
}).render(context);Browser (xterm.js)
Since @ripl/terminal is runtime-agnostic, you can wire it to any output that implements the TerminalOutput interface — including an xterm.js instance in the browser:
import {
Terminal,
} from '@xterm/xterm';
import {
BrailleRasterizer,
TerminalContext,
} from '@ripl/terminal';
const xterm = new Terminal({ disableStdin: true });
xterm.open(document.getElementById('terminal'));
const output = {
write: (data) => xterm.write(data),
columns: xterm.cols,
rows: xterm.rows,
};
const context = new TerminalContext(output, {
rasterizer: new BrailleRasterizer(xterm.cols, xterm.rows),
});How It Works
The terminal context:
- Records drawing commands (lines, arcs, curves, rects) from elements
- Rasterizes them onto a sub-pixel grid using algorithms like Bresenham's line, midpoint circle, and adaptive Bézier subdivision
- Applies scanline fill for filled shapes
- Maps CSS colors to ANSI truecolor escape sequences
- Encodes each 2×4 cell into a Unicode braille character
- Flushes the serialized output to the
TerminalOutputadapter
Logical Sizing
By default the context's coordinate space is the braille pixel grid — columns × 2 wide by rows × 4 tall (an 80×24 terminal is a 160×96 space). A scene authored in typical screen pixels (fixed radii, offsets in the hundreds) will overflow that space entirely.
Pass logicalWidth/logicalHeight to author in a larger logical space instead. The context then reports the logical size via context.width/context.height and uniformly scales + centres (letterboxes) it into the character grid — the same way the canvas context maps CSS pixels onto its device-pixel backing store:
// A scene written for a 800×600 canvas renders proportionally in any terminal.
const context = createContext(output, {
logicalWidth: 800,
logicalHeight: 600,
});The scale factor is uniform on both axes, so circles stay circular. Text glyphs remain cell-sized (inherent to terminals); only their position follows the logical space, and measureText reports metrics in logical units. On terminal resize the logical size is preserved and the mapping is recomputed. The docs playground's Terminal mode uses this to render examples with the same proportions as the Canvas and SVG modes.
Extensible Rasterizer
The default BrailleRasterizer can be swapped for alternative character sets by implementing the Rasterizer interface:
interface Rasterizer {
readonly pixelWidth: number;
readonly pixelHeight: number;
resize(cols: number, rows: number): void;
setPixel(x: number, y: number, color: string): void;
setChar(col: number, row: number, char: string, color: string): void;
clear(): void;
serialize(): string;
}Pass a custom rasterizer via the rasterizer option when creating a context.
Limitations
- No interaction — Terminal contexts do not support pointer events or hit testing
- No gradients — CSS gradient strings are not supported; use solid colors
- No image drawing —
drawImageis a no-op - Monospace text — Text is placed at character-grid positions; font metrics are approximate
- No transforms —
rotate,scale,translateare currently no-ops - Resolution — Limited by braille dot density (2×4 per cell)
When to Use Terminal
Terminal is the best choice when:
- Server-side rendering — Visualize data in CI/CD pipelines, monitoring dashboards, or CLI tools
- No browser available — Render charts and graphics in headless environments
- Quick prototyping — See rendering output without setting up a browser environment