Build websites that live in your terminal.
terminaltui is a TypeScript framework for interactive terminal apps. File-based routing, a 12-column grid, themes, and SSH hosting. Run with npx.
A directory is the site map.
File paths become routes. Layouts wrap their siblings. Brackets become parameters. Nothing to configure.
Pages are functions
Each page exports a default function returning content blocks. export const metadata sets the menu label, icon, and order.
Layouts compose
A pages/layout.ts wraps siblings and descendants. Nested layouts compose from outside in.
Dynamic routes
Drop [slug].ts in any folder. The page receives params.slug at runtime.
API on the same filesystem
Files in api/ export GET(), POST(), etc. A local HTTP server starts alongside the TUI.
Nine reference apps.
Each demo runs from npm with a single command. Hover any tile to preview the rendered terminal.
Everything a real app needs.
A focused, fully typed surface for UI, layout, state, data, routing, and testing.
30+ components
Card, Table, Timeline, Hero, Gallery, Tabs, Accordion, Quote, Badge, ProgressBar, Sparkline, Section, Divider.
Forms with validation
TextInput, TextArea, Select, Checkbox, Toggle, RadioGroup, NumberInput, SearchInput, Button. Validation and submission built in.
12-column grid
Bootstrap-style layout for terminals. Breakpoints at 60, 90, and 120 columns. Rows wrap, spans nest.
Spatial navigation
Arrow keys move to the nearest item by screen position. Distance and alignment scoring, no configuration.
File-based routing
Pages are files. Layouts wrap siblings. Dynamic routes use brackets. Async pages are first-class.
API routes
Files in api/ become endpoints. Export GET, POST, PUT, DELETE. The framework runs the server.
Ten built-in themes
Cyberpunk, Dracula, Nord, Monokai, Solarized, Gruvbox, Catppuccin, Tokyo Night, Rosé Pine, and Hacker. Custom themes too.
Reactive state
createState, computed values, persistent state, fetcher with auto-refresh, and live data over WebSocket and SSE.
Headless emulator
Spawn the app in a PTY. Read the screen, send keystrokes, assert content. Like Puppeteer for terminals.
Write a config. Drop in pages.
No JSX, no template language. Pages are TypeScript functions returning content blocks.
import { defineConfig } from "terminaltui"; export default defineConfig({ name: "My Site", theme: "cyberpunk", banner: { text: "MY SITE", font: "ANSI Shadow" }, // optional: serve over ssh serve: { port: 2222, maxConnections: 100, }, });
import { card, timeline, link } from "terminaltui"; export const metadata = { label: "About", icon: "◆", order: 2, }; export default function About() { return [ card({ title: "About Me", body: "Full-stack developer based in Portland.", }), timeline([ { date: "2026", title: "Started terminaltui" }, { date: "2024", title: "Joined Acme Corp" }, ]), link("GitHub", "https://github.com/me"), ]; }
import { card, section, badge } from "terminaltui"; type Params = { params: { slug: string } }; export default async function Project({ params }: Params) { const data = await fetch( `/api/projects/${params.slug}` ).then(r => r.json()); return [ section({ title: data.name, level: 1 }), badge(data.status, { tone: "success" }), card({ title: "Description", body: data.description }), ]; }
// api/stats.ts becomes GET /api/stats export async function GET() { return { users: 45_231, uptime: 99.97, requests: 1_284_512, }; } export async function POST(req: Request) { const body = await req.json(); return { ok: true }; }
import { row, col, card, container } from "terminaltui"; export default function Dashboard() { return [ container([ row([ col(statsCard, { span: 3, xs: 12 }), col(chartCard, { span: 9, xs: 12 }), ], { gap: 1 }), row([ col([card({ title: "Revenue", body: "$1.2M" })], { span: 4 }), col([card({ title: "Users", body: "45,231" })], { span: 4 }), col([card({ title: "Uptime", body: "99.97%" })], { span: 4 }), ]), ], { maxWidth: 120, center: true }) ]; }
Host any TUI over SSH.
One server, many sessions. Each connection is independent. Auto-detects the client TERM for color depth.
Get started.
Four commands.
npx your-site.| terminaltui init [template] | Scaffold a new project from a template. |
| terminaltui dev [path] | Compile and run. |
| terminaltui serve [path] | Host the TUI over SSH. |
| terminaltui build | Bundle for npm publish. |
| terminaltui demo [name] | Run a built-in demo. |
| terminaltui test | Run headless emulator tests. |