VOOZH about

URL: https://dev.to/omarmusayev/i-built-nextjs-for-the-terminal-in-typescript-heres-the-architecture-53k4

⇱ I built "Next.js for the terminal" in TypeScript — here's the architecture - DEV Community


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.