A few months ago I started building terminaltui — a TypeScript framework for interactive terminal apps. The pitch is "Next.js for the terminal": write a pages/ directory of TS files, get a fully navigable TUI with file-based routing, components, themes, and SSH hosting.
It just hit v1.8.1 on npm with 2,142 passing tests. You can try it in zero seconds:
npx terminaltui try
That opens a 5-page guided tour of the framework — no install, no signup.
This post is the technical writeup: how the file-based router works, the layout engine, and the SSH hosting bit. If you've used Ink (React for the terminal), terminaltui is in the same neighborhood but a step further — it ships routing, layout, and themes as defaults instead of "bring your own React patterns."
The file-based router
A terminaltui project is just two things: config.ts and pages/.
// pages/about.ts
import { card, markdown } from "terminaltui";
export const metadata = {
label: "About",
icon: "◆",
order: 2,
};
export default function About() {
return [
card({ title: "About me", body: "Developer." }),
markdown("Some markdown here."),
];
}
File paths map to routes the same way Next.js does:
pages/
index.ts → /
about.ts → /about
projects/
index.ts → /projects
[slug].ts → /projects/:slug
Dynamic routes use bracket syntax. The page function gets { params: { slug: string } }.
Under the hood, the framework walks the pages/ directory at boot, compiles each TS file via esbuild (or imports directly under tsx in dev mode), and builds a route table. Spatial navigation is automatic — arrow keys move to the nearest focusable item by screen position. You never write a tabIndex.
You can read the router source on GitHub if you want to see how the scanner walks the directory and how dynamic segments get parsed.
The layout engine
terminaltui has a 12-column grid that behaves like CSS grid + flexbox:
row([
col(sidebarBlocks, { span: 3, xs: 12 }),
col(mainBlocks, { span: 9, xs: 12 }),
], { gap: 1 });
Breakpoints kick in at 60, 90, and 120 terminal columns. Each col can nest more rows. The engine measures each block's content (with stringWidth() for proper CJK/emoji widths), computes a flexbox-like layout, then renders.
Where this matters: most TUI frameworks make you do absolute positioning or rely on a parent that does. With a grid that wraps responsively, the same page renders correctly in a 200-col Kitty window AND a 60-col Apple Terminal window. (Yes, Apple Terminal gets a 256-color fallback because it can't handle truecolor escapes.)
SSH hosting in one command
The thing I'm most happy about: every terminaltui app can be hosted over SSH without touching a single SSH config file.
terminaltui serve --port 2222
That spins up an SSH server (using ssh2 underneath) that accepts any client, allocates a PTY, and renders the app inside the session. Each connection gets its own isolated runtime — concurrent sessions don't clobber each other's state. The framework auto-detects the client's TERM and color depth.
Connect from anywhere with:
ssh user@your-server -p 2222
This means your CLI doesn't have to be installed on the connecting side. You can ship a "live demo" by running serve once on a VPS — anyone with SSH can experience your app.
Source for the SSH server if you want to see how the multi-session isolation works (it uses Node's AsyncLocalStorage so each session sees its own runtime context).
Why TypeScript instead of Go or Rust?
I get this question a lot. Honest answer: most existing TUI frameworks are written in Go (Bubble Tea), Rust (Ratatui), or Python (Textual). Those are great languages but they're all new dependencies for a JS/TS team. terminaltui ships as a regular npm package — your existing CI/CD, your existing types, your existing editor. No new language, no new build chain.
Plus: I wanted to write import { card, row, col } from "terminaltui" and have it Just Work. TypeScript's structural typing + esbuild's speed makes the developer loop feel like React in 2026, not like ncurses in 1990.
What's not great yet
Being honest:
-
Docs are README-only. A real docs site is coming. For now the README + the bundled demos (
npx terminaltui demo restaurant, etc.) are the manual. - No Windows ConPTY fast path. Works on Windows via a fallback, but native ConPTY support would speed it up.
-
No hot-reload for
api/routes in dev. Pages hot-reload fine; API endpoints currently require a restart.
If any of those bother you, the issues tab is open.
Try it
# Tour the framework (no install)
npx terminaltui try
# Scaffold a real project
npx terminaltui init my-site
# Or run any of the 11 bundled demos
npx terminaltui demo mac-monitor # live macOS activity monitor
npx terminaltui demo dashboard # a portfolio dashboard
npx terminaltui demo conference # a tech conference site
Source is MIT-licensed on GitHub. v1.8.1 is on npm. The landing page lives at terminaltui.dev.
If you build something with it, I'd love to see it.
Top comments (0)