npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ugtui

v1.0.1

Published

A beautiful terminal UI framework for Node.js - Create interactive CLI applications with ease

Readme

ugtui

A beautiful terminal UI framework for Node.js that makes building rich, interactive command-line applications easy and enjoyable.

Features

  • 🎨 Beautiful UI Components - Pre-built components for common UI patterns
  • 📐 Flexible Layout System - Flexbox-like layout engine
  • 🎯 Event Handling - Keyboard event support
  • 💅 Styling & Theming - Rich styling options with built-in themes
  • High Performance - Efficient rendering with minimal overhead
  • 🔧 TypeScript Support - Full type definitions included
  • 📦 Easy to Use - Simple API with intuitive design
  • 🔌 Zero Dependencies - Uses only Node.js built-ins

Installation

Install from npm (Recommended)

npm install ugtui

Install from local folder

cd /path/to/your-project
npm install /path/to/ugtui

Development setup

# Clone or navigate to ugtui directory
cd /path/to/ugtui

# Install dependencies
npm install

# Build
npm run build

# Run examples
npm run example

Quick Start

Your First App

Create a file app.js:

const { App, Box, Text, Button } = require('ugtui');

const app = new App();

const title = new Text({
  content: 'Hello, ugtui!',
  style: { fg: 'green', styles: ['bold'] },
  padding: 1
});

const button = new Button({
  label: 'Click Me!',
  padding: 1,
  onPress: () => console.log('Button clicked!')
});

const box = new Box({
  border: true,
  borderStyle: 'rounded',
  title: ' My App ',
  style: { fg: 'blue' }
});

box.addChild(title);
box.addChild(button);

app.mount(box);
app.start();

Run it in an interactive terminal:

node app.js

Getting Started Guide

1. Understanding Components

ugtui is built around components - reusable building blocks that you compose to create your UI.

const { Box, Text, Button, FlexLayout } = require('ugtui');

// Create components
const title = new Text({ content: 'Title' });
const button = new Button({ label: 'Click' });
const box = new Box({ border: true });

// Add children
box.addChild(title);
box.addChild(button);

2. Layout with FlexLayout

Organize components using the flexible layout system:

const layout = new FlexLayout({
  direction: 'column',  // 'row' or 'column'
  justify: 'center',     // 'flex-start', 'flex-end', 'center', 'space-between'
  align: 'center',       // 'flex-start', 'flex-end', 'center', 'stretch'
  gap: 1,               // Spacing between children
  padding: 1             // Internal padding
});

layout.addChild(component1);
layout.addChild(component2);

3. Styling Components

Apply colors and styles to make your UI beautiful:

const styledText = new Text({
  content: 'Styled Text',
  style: {
    fg: 'blue',              // foreground color
    bg: 'white',             // background color (optional)
    styles: ['bold', 'underline']  // text effects
  }
});

4. Interactive Components

Handle user input with interactive components:

// Button with click handler
const button = new Button({
  label: 'Submit',
  onPress: () => {
    console.log('Button pressed!');
  }
});

// Input with change handler
const input = new Input({
  placeholder: 'Type something...',
  onChange: (value) => console.log('Typing:', value),
  onSubmit: (value) => console.log('Submitted:', value)
});

// List with selection handler
const list = new List({
  items: ['Option 1', 'Option 2', 'Option 3'],
  onSelect: (index, item) => {
    console.log('Selected:', item);
  }
});

5. Putting It All Together

const { App, Box, Text, Button, FlexLayout } = require('ugtui');

const app = new App();

// Create UI
const title = new Text({
  content: 'Welcome!',
  style: { fg: 'green', styles: ['bold'] },
  padding: 1
});

const button = new Button({
  label: 'Get Started',
  onPress: () => {
    title.updateProps({ content: 'Hello, User!' });
  }
});

// Layout
const content = new FlexLayout({
  direction: 'column',
  gap: 1,
  padding: 1
});

content.addChild(title);
content.addChild(button);

// Container
const box = new Box({
  border: true,
  borderStyle: 'rounded',
  title: ' My App '
});

box.addChild(content);

// Start app
app.mount(box);
app.start();

Components

Box

Container with optional borders and titles.

const box = new Box({
  border: true,
  borderStyle: 'rounded', // 'single', 'double', 'rounded'
  title: 'Container',
  padding: 2,
  style: { fg: 'blue' }
});

Text

Displays text with alignment and wrapping.

const text = new Text({
  content: 'Hello, World!',
  align: 'center', // 'left', 'center', 'right'
  wrap: true,
  style: { fg: 'green', styles: ['bold'] }
});

Button

Interactive button with press handling.

const button = new Button({
  label: 'Click Me',
  padding: 1,
  disabled: false,
  activeColor: 'blue',
  hoverColor: 'white',
  onPress: () => console.log('Clicked!'),
  style: { fg: 'blue', styles: ['bold'] }
});

Input

Text input field with validation and password support.

const input = new Input({
  placeholder: 'Enter text...',
  password: false,
  maxLength: 50,
  disabled: false,
  onChange: (value) => console.log('Value:', value),
  onSubmit: (value) => console.log('Submitted:', value)
});

// Get current value
const currentValue = input.getValue();

// Set value programmatically
input.setValue('New value');

List

Scrollable list of selectable items.

const list = new List({
  items: ['Item 1', 'Item 2', 'Item 3'],
  maxHeight: 10,
  showScrollbar: true,
  onSelect: (index, item) => console.log('Selected:', item)
});

// Get selected index
const index = list.getSelectedIndex();

// Set selected index
list.setSelectedIndex(1);

// Get selected item
const item = list.getSelectedItem();

FlexLayout

Flexible container layout similar to CSS Flexbox.

const layout = new FlexLayout({
  direction: 'row', // 'row' or 'column'
  justify: 'center', // 'flex-start', 'flex-end', 'center', 'space-between', 'space-around'
  align: 'center', // 'flex-start', 'flex-end', 'center', 'stretch'
  gap: 2,
  padding: 1
});

layout.addChild(component1);
layout.addChild(component2);

Styling

Colors

Available colors:

Basic:

  • black, red, green, yellow, blue, magenta, cyan, white

Bright:

  • brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite

Text Styles

Available styles:

  • bold - Bold text
  • dim - Dimmed text
  • italic - Italic text
  • underline - Underlined text
  • blink - Blinking text
  • reverse - Reversed foreground/background
  • hidden - Hidden text

Style Example

{
  fg: 'blue',              // foreground color
  bg: 'white',             // background color (optional)
  styles: ['bold', 'underline']  // array of styles
}

Theme Colors

Default theme colors:

{
  primary: 'blue',
  secondary: 'magenta',
  success: 'green',
  danger: 'red',
  warning: 'yellow',
  muted: 'white',
  background: 'black',
  surface: 'brightBlack',
  text: 'white',
  textSecondary: 'brightWhite'
}

Keyboard Navigation

  • Tab - Navigate between components
  • Arrow Keys - Navigate within lists and forms
  • Enter - Select item or submit form
  • Home/End - Jump to start/end of list
  • Backspace - Delete character
  • Delete - Delete forward character
  • q - Exit application
  • Ctrl+C - Exit application

API Reference

App

Main application class.

const app = new App({
  fps: 60,    // Frame rate
  debug: false  // Enable debug mode
});

// Mount root component
app.mount(component);

// Start application
app.start();

// Stop application
app.stop();

// Global key press listener
app.onKeyPress((event) => {
  console.log('Key:', event.key);
  console.log('Ctrl:', event.ctrl);
  console.log('Alt:', event.alt);
  console.log('Shift:', event.shift);
});

// Get terminal instance
const terminal = app.getTerminal();

Component Methods

All components inherit from the base Component class:

// Add child component
component.addChild(child);

// Remove child component
component.removeChild(child);

// Get all children
const children = component.getChildren();

// Set position
component.setPosition({ x: 0, y: 0 });

// Get position
const pos = component.getPosition();

// Set size
component.setSize({ width: 20, height: 10 });

// Get size
const size = component.getSize();

// Give focus
component.focus();

// Remove focus
component.blur();

// Check if focused
const isFocused = component.isFocused();

// Update properties
component.updateProps({
  style: { fg: 'green' },
  padding: 2
});

// Get properties
const props = component.getProps();

Examples

Simple Counter

const { App, Box, Text, Button, FlexLayout } = require('ugtui');

const app = new App();
let count = 0;

const counterText = new Text({
  content: `Count: ${count}`,
  style: { fg: 'green', styles: ['bold'] },
  padding: 1
});

const incrementButton = new Button({
  label: 'Increment',
  onPress: () => {
    count++;
    counterText.updateProps({ content: `Count: ${count}` });
  }
});

const decrementButton = new Button({
  label: 'Decrement',
  onPress: () => {
    count--;
    counterText.updateProps({ content: `Count: ${count}` });
  }
});

const buttons = new FlexLayout({
  direction: 'row',
  gap: 2,
  justify: 'center'
});

buttons.addChild(incrementButton);
buttons.addChild(decrementButton);

const content = new FlexLayout({
  direction: 'column',
  gap: 1,
  align: 'center'
});

content.addChild(counterText);
content.addChild(buttons);

const box = new Box({
  border: true,
  borderStyle: 'rounded',
  title: ' Counter '
});

box.addChild(content);

app.mount(box);
app.start();

Todo List

const { App, Box, Text, Input, List, FlexLayout } = require('ugtui');

const app = new App();
const todos: string[] = [];

const input = new Input({
  placeholder: 'Add a todo...',
  onSubmit: (value) => {
    if (value.trim()) {
      todos.push(value);
      list.updateProps({ items: [...todos] });
      input.setValue('');
    }
  }
});

const list = new List({
  items: todos,
  maxHeight: 10,
  onSelect: (index, item) => {
    todos.splice(index, 1);
    list.updateProps({ items: [...todos] });
    console.log('Removed:', item);
  }
});

const content = new FlexLayout({
  direction: 'column',
  gap: 1,
  padding: 1
});

content.addChild(input);
content.addChild(list);

const box = new Box({
  border: true,
  borderStyle: 'rounded',
  title: ' Todo List '
});

box.addChild(content);

app.mount(box);
app.start();

Form with Validation

const { App, Box, Text, Input, Button, FlexLayout } = require('ugtui');

const app = new App();

const nameInput = new Input({
  placeholder: 'Name',
  padding: 1
});

const emailInput = new Input({
  placeholder: 'Email',
  padding: 1
});

const submitButton = new Button({
  label: 'Submit',
  onPress: () => {
    const name = nameInput.getValue();
    const email = emailInput.getValue();
    console.log(`Submitted: ${name} (${email})`);
  }
});

const form = new FlexLayout({
  direction: 'column',
  gap: 1,
  padding: 2
});

form.addChild(nameInput);
form.addChild(emailInput);
form.addChild(submitButton);

const box = new Box({
  border: true,
  borderStyle: 'double',
  title: ' Registration Form '
});

box.addChild(form);

app.mount(box);
app.start();

Important Notes

Terminal Requirements

ugtui requires an interactive terminal (TTY). It works in:

✅ Terminal.app ✅ iTerm2 ✅ VS Code integrated terminal ✅ SSH sessions ✅ tmux, screen

It doesn't work in:

❌ Non-interactive environments ❌ Some CI/CD pipelines ❌ Piped output scenarios

TypeScript Usage

For TypeScript projects:

import { App, Box, Text } from 'ugtui';

const app = new App();
const box = new Box({ border: true });
// Full type safety!

Troubleshooting

"ugtui requires an interactive terminal"

This error means you're not running in a TTY environment. Make sure to:

  1. Run in an interactive terminal (not through pipes)
  2. Don't redirect output
  3. Use Terminal.app, iTerm2, or similar

Nothing displays

Make sure you've called app.mount() before app.start():

const app = new App();
app.mount(component); // ← Must be before start
app.start();

Components overlap

Use FlexLayout with proper gap and padding:

const layout = new FlexLayout({
  direction: 'column',
  gap: 1,    // Spacing between children
  padding: 1   // Internal padding
});

Building

# Build TypeScript
npm run build

# Watch mode
npm run dev

# Run examples
npm run example

Version History

1.0.0 (2024-03-04)

Initial release:

  • Terminal handling with raw mode
  • 6 UI components (Box, Text, Button, Input, List, FlexLayout)
  • Styling system with 16 colors and 7 styles
  • Flexbox-like layout engine
  • Keyboard navigation
  • Full TypeScript support
  • Zero external dependencies

Contributing

Contributions are welcome! Please feel free to:

  • Report bugs
  • Suggest features
  • Submit pull requests
  • Improve documentation

License

MIT License - see LICENSE file for details.

Credits

Created by Unmesh.

Links

  • Installation: npm install ugtui
  • Repository: https://github.com/unmesh100/ugtui
  • Issues: https://github.com/unmesh100/ugtui/issues

Happy building with ugtui! 🚀