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

vexart

v0.9.0-beta.20

Published

GPU-accelerated terminal UI engine. Write JSX, get browser-quality UI in your terminal. Anti-aliased corners, shadows, gradients, glow, backdrop blur — real pixels, not ASCII.

Readme

Vexart

Pixel-native terminal rendering engine. Write JSX, get browser-quality UI in your terminal.

Anti-aliased corners. Drop shadows. Linear & radial gradients. Glow effects. Backdrop blur (glassmorphism). Element opacity. Per-corner radius. All rendered as real GPU pixels — not ASCII boxes.

import { createApp, Box, Text, colors } from "vexart"

await createApp(() => (
  <Box
    width="100%"
    height="100%"
    backgroundColor={colors.background}
    alignX="center"
    alignY="center"
  >
    <Text color={colors.foreground} fontSize={16}>Hello from Vexart!</Text>
  </Box>
))

Features

  • GPU-accelerated rendering — WGPU (Metal/Vulkan/DX12) via a single Rust cdylib
  • Pixel-perfect shapes — SDF anti-aliased rounded rects, circles, lines, Bezier curves
  • JSX components — SolidJS createRenderer; fine-grained reactive updates, no VDOM
  • Incremental layout — Flexily flexbox (pure JS), reactive tree synced from reconciler; only dirty subtrees recompute
  • Design tokens — shadcn-compatible dark theme with semantic color, spacing, radius, shadows
  • 26 headless components — Button, Input, Select, Dialog, Combobox, Slider, VirtualList, and more
  • Focus management — Tab/Shift-Tab cycling, per-node keyboard handlers, focus scoping
  • Drop shadows & glow — declarative shadow and glow props, rendered via GPU
  • Gradients — linear and radial, multi-stop
  • Backdrop filters — blur, brightness, contrast, saturate, grayscale, invert, sepia, hue-rotate
  • Element opacity — per-element alpha with isolated compositing
  • Scroll containers — virtualized lists, programmatic scroll, smooth inertia
  • AnimationscreateTransition + createSpring with 12 easing presets, 30-60 fps adaptive
  • Pointer capture — drag interactions via setPointerCapture / releasePointerCapture
  • Form validationcreateForm() with sync/async validators, touched/dirty/submitting state
  • Data fetchinguseQuery (retry, refetch, interval) and useMutation (optimistic + rollback)
  • Syntax highlighting — Tree-sitter grammars, One Dark and Kanagawa themes
  • Markdown rendering — inline styling via <Markdown> component

Requirements

| Dependency | Version | Notes | |------------|---------|-------| | Bun | ≥ 1.1.0 | Runtime | | Rust toolchain | stable | For cargo build (native library) | | Kitty-compatible terminal | — | Kitty, Ghostty, or WezTerm |

Vexart requires a terminal that supports the Kitty graphics protocol. It exits with a clear error on unsupported terminals.

Quick Start

# 1. Install
bun add vexart

# 2. Configure JSX transform (babel.config.js or similar)
import { vexartSolidPlugin } from "vexart/solid-plugin"
# moduleName: "vexart/engine"

# 3. Write your app
import { createApp, Box, Text, Button, colors, radius, space } from "vexart"

function App() {
  return (
    <Box
      width="100%"
      height="100%"
      backgroundColor={colors.background}
      direction="column"
      alignX="center"
      alignY="center"
      gap={space[4]}
    >
      <Box
        backgroundColor={colors.card}
        cornerRadius={radius.lg}
        padding={space[6]}
        direction="column"
        gap={space[2]}
      >
        <Text color={colors.foreground} fontSize={16}>Hello from Vexart</Text>
        <Text color={colors.mutedForeground} fontSize={12}>Browser-quality UI in your terminal</Text>
      </Box>
      <Button
        onPress={() => process.exit(0)}
        renderButton={(ctx) => (
          <Box {...ctx.buttonProps} backgroundColor={colors.primary} cornerRadius={radius.md} padding={space[3]}>
            <Text color={colors.background}>Quit</Text>
          </Box>
        )}
      />
    </Box>
  )
}

await createApp(() => <App />)

createApp() is the managed entry point. For advanced integrations, mountApp() exposes the async app lifecycle and mount() remains the low-level engine alternative when you need to provide your own terminal and input plumbing.


Architecture

JSX (SolidJS createRenderer)
  → Reconciler syncs reactive Flexily tree (incremental layout)
    → TypeScript walk-tree (render metadata collection)
      → Rust libvexart (WGPU paint + composite + readback + Kitty emit)
        → Terminal

The Flexily layout tree is persistent and reactive — props and tree structure sync from the SolidJS reconciler. calculateLayout() only recomputes dirty subtrees. Rust owns the entire output path: GPU paint → readback → compress → Kitty encoding → terminal write. Zero bytes cross the FFI boundary for presentation.

Vexart is not a cell-based TUI framework. It renders actual pixels using the Kitty graphics protocol — the result looks like a browser running inside your terminal.

Package layers

| Package | Purpose | Layer | |---------|---------|-------| | @vexart/app | Managed app framework: router, className mapper, config, CLI helpers | App | | @vexart/styled | Design tokens + styled components (shadcn-compatible): colors, radius, space, font, shadows | Styled | | @vexart/headless | Behaviour-only components: Button, Input, Dialog, Select, Tabs, List, Table, VirtualList, etc. | Headless | | @vexart/primitives | Low-level JSX nodes: Box, Text, RichText, Span, WrapRow | Primitives | | @vexart/engine | Core engine: render loop, GPU backend, SolidJS reconciler, input, focus, animation, data fetching | Foundation |

Dependencies flow downward: app → styled → headless → primitives → engine. You can use any layer independently.

Native binary — libvexart

A single Rust cdylib (target/release/libvexart.dylib) handles all GPU and presentation work:

  • Paint — WGPU shaders: SDF rounded rects, shadows, gradients, blur, compositor
  • MSDF text — Multi-channel signed-distance-field font rendering + measurement; sharp at any size
  • Presentation — GPU readback → zlib compress → Kitty encoding → direct/file/SHM transport write. The entire output path lives in Rust — no pixel data crosses back to JS.

Built with:

cargo build --release

Components

| Component | Category | Description | |-----------|----------|-------------| | Box | Primitives | Layout container with all visual props | | Text | Primitives | Text display with font, color, size | | RichText | Primitives | Multi-span inline text | | Span | Primitives | Inline text span within RichText | | WrapRow | Primitives | Flex-wrap row helper | | ScrollView | Containers | Scrollable container with visual scrollbar | | Portal | Containers | Render subtree at root level | | Button | Inputs | Clickable element (headless render context) | | Input | Inputs | Single-line text input | | Textarea | Inputs | Multi-line editor (2D cursor, syntax, keybindings) | | Checkbox | Inputs | Toggle checkbox | | Switch | Inputs | Toggle switch | | RadioGroup | Inputs | Radio option group | | Slider | Inputs | Numeric range (click-to-position + drag) | | Select | Overlays | Dropdown with keyboard navigation | | Combobox | Overlays | Autocomplete with filtering | | Dialog | Overlays | Modal with focus trap + Escape | | Tooltip | Overlays | Delayed tooltip on hover | | Popover | Overlays | Controlled popover panel | | Tabs | Navigation | Tab switcher | | Router | Navigation | Flat + stack navigation | | List | Collections | Scrollable selectable list | | Table | Collections | Data table with row selection | | VirtualList | Collections | Virtualized list (O(1) scroll, fixed-height rows) | | ProgressBar | Display | Progress indicator | | Code | Display | Syntax-highlighted code block | | Markdown | Display | Markdown renderer with inline styling | | Diff | Display | Unified diff viewer |

Also: createForm factory, Toast (imperative), createToaster.


Effects reference

All effects are JSX props — no imperative API needed:

// Drop shadow
<Box shadow={{ x: 0, y: 4, blur: 12, color: 0x00000060 }}>

// Multi-shadow
<Box shadow={[{ x: 0, y: 2, blur: 4, color: 0x0000004f }, { x: 0, y: 8, blur: 24, color: 0x00000030 }]}>

// Outer glow
<Box glow={{ radius: 20, color: 0x56d4c8ff, intensity: 60 }}>

// Linear gradient
<Box gradient={{ type: "linear", from: 0x1a1a2eff, to: 0x0a0a0fff, angle: 90 }}>

// Radial gradient
<Box gradient={{ type: "radial", from: 0x56d4c8ff, to: 0x00000000 }}>

// Backdrop blur (glassmorphism)
<Box backdropBlur={12} backgroundColor={0xffffff1a}>

// Per-corner radius
<Box cornerRadii={{ tl: 20, tr: 20, br: 0, bl: 0 }}>

// Interactive states
<Box
  focusable
  backgroundColor={0x1e1e2eff}
  hoverStyle={{ backgroundColor: 0x2a2a3eff }}
  activeStyle={{ backgroundColor: 0x3a3a4eff }}
  focusStyle={{ borderColor: 0x4488ccff, borderWidth: 2 }}
  onPress={() => doAction()}
>

Terminal Support

| Terminal | Protocol | Quality | |----------|----------|---------| | Kitty 0.41+ | Kitty direct + SHM | ✅ Best — native pixel rendering | | Ghostty | Kitty direct | ✅ Best — native pixel rendering | | WezTerm 2025.04+ | Kitty direct | ✅ Best | | tmux, Alacritty, iTerm2, Windows Terminal | — | ❌ Unsupported — exits with clear error |


Development

bun install                  # Install JS dependencies
cargo build --release        # Build libvexart (Rust GPU backend)

bun test                     # Run unit tests
bun typecheck                # TypeScript type check
cargo test                   # Run Rust unit tests

bun run example              # Run hello world example
bun run showcase             # Run comprehensive feature showcase (7 tabs)
bun run test:visual          # Run 40-scene golden image visual suite
bun run test:visual:update   # Regenerate visual test references
bun run build:dist           # Build distributable Vexart npm package

# Performance
bun run perf:baseline        # Save avg frame time baseline
bun run perf:check           # Compare current vs saved baseline (exits 1 on regression)
bun run perf:snapshot        # Full frame breakdown (7 scenarios, per-stage timing)
bun run perf:compare         # Diff current vs pre-optimization baseline
bun run test:golden          # Save visual golden snapshot
bun run test:golden:check    # Compare render output vs golden (pixel-perfect)

Examples

See examples/README.md for a full list of examples with descriptions and run commands.

Quick-start examples:

bun run example        # Hello World — first JSX render
bun run demo4          # Interactive — focus, signals, keyboard
bun run demo7          # Scroll containers
bun run demo8          # Component showcase
bun run demo9          # Shadow & glow effects
bun run showcase       # Comprehensive 7-tab feature showcase

Links


License

Source-available. Free for personal use, open-source projects, and commercial products with annual revenue under $1M USD. A commercial license is required for products at or above $1M ARR.

See LICENSE for full terms.