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

@treactui/tty

v0.0.8

Published

A real terminal in the browser, with an accessibility layer, for any React app.

Readme

@treactui/tty

A real terminal in the browser, with an accessibility layer, for any React app.

import { TTY } from '@treactui/tty'

<TTY url="ws://localhost:8080/term" />

TTY renders xterm.js (screen-reader mode on), connects to a backend over WebSocket, and draws a visually hidden, semantic twin of the screen from a11y-snapshot messages so assistive technology gets real ARIA instead of a scraped buffer. Your bundler must be able to import CSS (@xterm/xterm/css/xterm.css).

Keyboard: the terminal captures Tab and most keys, so Ctrl+Shift+M hands focus back to the page: into the described screen's region when the backend sends snapshots, otherwise onto the terminal's container, never the bare document (where a screen reader would stay in focus mode).

Screen readers: when the selected option of a described screen changes, its name is announced. When a launched command ends, its outcome and the first lines of its output are the "Back to commands" button's description, and the full output is a labelled region of plain text. See docs/accessibility.md, which records what was verified with NVDA and what was not.

Without a server: over Wails events

A Wails app does not need a WebSocket server. Give TTY a socket that talks through Wails' events instead, and serve the program on the Go side with ttygo.Bind or ttygo.BindShared (see tty-go):

import { TTY, createWailsSocket } from '@treactui/tty'

// Created once, outside the component: a new function on every render would reconnect the terminal each time.
const wailsSocket = createWailsSocket()

<TTY createSocket={wailsSocket} />

url is not needed then. createWailsSocket({ prefix, runtime }) renames the two events (<prefix>:up and <prefix>:down, default treactui; the Go side must use the same) or supplies the runtime instead of window.runtime, which only a page served by Wails has. The page has to be served by Wails (not loaded from another address), because that is what injects window.runtime.

Command launcher

When the backend offers commands (a commands message, for example from serveCommander in @treactui/tty-node), TTY first shows an accessible form: pick a command, fill in its arguments and options, press Run. Every field has a label, a field that is wrong gets an error tied to it and focus, and each change of screen moves focus: to the form's heading on arrival, to the terminal when a command starts, to "Back to commands" when it ends. Stop ends a running command; use Ctrl+Shift+M to leave the terminal and reach it by keyboard.

Arguments reach the program as an argument list; a value that starts with a dash is passed after --, so typed text is never read as an option. A variadic argument is split on spaces.

Long output

The terminal keeps the last 1 000 lines above its visible rows and discards older ones, which is what keeps the page's memory flat however long a program prints (500 000 lines: 15 MB to 17 MB, measured). When a launched command printed more than the terminal still holds, the summary read out when it ends says how many lines are gone and reads the last ones, and the output region's label says that it holds only the end.

Announcements, from the backend or from the selection moving, are paced: the first is spoken at once and anything within the next 400 ms is held and replaced by the latest, so a program that announces in a loop, or an arrow key held down on a list, does not queue hundreds of utterances in a screen reader. A program that prints continuously is still read out continuously in the terminal's own region; see docs/stress-test.md for what was measured and what was not.

The protocol

The wire messages live in @treactui/protocol, shared with the backend adapters.

How this package is organised

Vertical feature slices: one folder per outcome, each with an index.ts that is its whole public API, flat role-suffixed files, tests beside what they test.

src/
  index.ts                  the package's public API: TTY
  transport/                the WebSocket client (queues sends until the socket opens) and the Wails events socket
  command-launcher/         the accessible form: argument builder, validator and fields
  terminal-view/            xterm.js, and the keyboard-trap escape policy
  accessibility-layer/      the hidden ARIA tree and live regions, from a snapshot
  tty/                      composes the above: the TTY component and its session hook

Dependencies point one way: tty → terminal-view, accessibility-layer, command-launcher, transport → @treactui/protocol. Enforced by npm run lint (verticalSlices in the root eslint.config.mjs).

Building and testing

nx build tty
nx test tty