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

terme

v0.1.0

Published

Ultra-smooth WebGL terminal renderer with MSDF font rendering

Readme

Terme - WebGL Terminal Renderer

CI npm version Bundle Size TypeScript License: MIT

Ultra-smooth, high-performance terminal renderer using WebGL 2 and MSDF font rendering. Capable of handling millions of lines via virtual scrolling with sustained 120+ FPS.

What is Terme?

Terme is a WebGL-based terminal renderer optimized for extreme performance. Unlike traditional DOM-based terminals, Terme renders text using GPU-accelerated instancing and MSDF fonts, achieving 120+ FPS even with millions of lines.

Use Cases:

  • Terminal emulators (xterm.js alternative)
  • Log viewers with millions of lines
  • Browser-based code editors
  • REPL/Shell interfaces
  • Real-time data monitoring dashboards

Not a full terminal emulator: Terme focuses on rendering. For complete terminal functionality with ANSI support, PTY handling, etc., you'll need to implement or integrate those layers.

Quick Start

See USAGE.md for detailed documentation.

Installation:

npm install terme

Vanilla TypeScript:

import { Terminal } from 'terme';

const terminal = await Terminal.create(
  canvas,
  '/fonts/cascadia-code.png',
  '/fonts/cascadia-code.json'
);

terminal.setContent(['Hello, World!']);
terminal.onInput((text) => console.log('Input:', text));

React:

import { TerminalCanvas } from 'terme/react';

<TerminalCanvas
  fontAtlasUrl="/fonts/cascadia-code.png"
  metricsUrl="/fonts/cascadia-code.json"
  config={{ fontSize: 14 }}
  onTerminalReady={(terminal) => {
    terminal.setContent(['Hello from React!']);
  }}
/>

Font Setup:

# Copy bundled fonts to your public directory
cp -r node_modules/terme/dist/fonts public/fonts

Features

  • WebGL 2 Rendering: Efficient GPU-accelerated text rendering using MSDF (Multi-channel Signed Distance Field) fonts
  • Virtual Scrolling: Handles millions of lines with O(1) access and minimal memory overhead
  • High Performance: Target 120+ FPS with zero allocations in hot paths
  • Instanced Rendering: Single draw call per frame for optimal GPU utilization
  • Text Input: Keyboard input with caret positioning
  • Responsive: Automatic DPI handling and resize support

Prerequisites

  1. Install msdfgen (required for font atlas generation):

    # macOS
    brew install msdfgen
    
    # Arch Linux
    sudo pacman -S msdfgen
    
    # From source (Linux/Windows)
    git clone https://github.com/Chlumsky/msdfgen.git
    cd msdfgen
    cmake -S . -B build
    cmake --build build
    sudo cmake --install build
  2. Node.js: v18+ recommended

Installation

As a Package

npm install terme

For React integration:

npm install terme react react-dom

For Development

# Clone repository
git clone https://github.com/victorqueiroz/Terme.git
cd Terme

# Install dependencies
npm install

# Generate font atlas (MUST run before dev server)
npm run generate:font

# Start development server
npm run dev

Usage

Running the Demo

The demo application generates 1 million lines of sample content to showcase performance:

npm run dev

Open http://localhost:5173 in your browser.

Controls:

  • Scroll: Mouse wheel or trackpad
  • Navigate: Arrow keys move the caret
  • Input: Type any key (logged to console)

Using as a Component

import { TerminalCanvas } from 'terme/react';
import type { Terminal } from 'terme';

function MyApp() {
  const handleTerminalReady = (terminal: Terminal) => {
    // Set initial content
    terminal.writeLine('Hello, World!');
    terminal.writeLine('This is a terminal renderer');
    terminal.writeLine('Powered by WebGL and MSDF');

    // Setup callbacks
    terminal.onInput((text) => console.log('Input:', text));
    terminal.onScroll(() => console.log('Scrolled'));
  };

  return (
    <TerminalCanvas
      fontAtlasUrl="/fonts/cascadia-code.png"
      metricsUrl="/fonts/cascadia-code.json"
      config={{
        fontSize: 14,
        lineHeight: 1.5,
        backgroundColor: [0, 0, 0, 1],
        overscan: 10,
      }}
      onTerminalReady={handleTerminalReady}
    />
  );
}

Vanilla TypeScript API

import { Terminal } from 'terme';

// Create terminal (automatically initializes and attaches to canvas)
const terminal = await Terminal.create(
  canvas,
  '/fonts/cascadia-code.png',
  '/fonts/cascadia-code.json',
  {
    fontSize: 14,
    lineHeight: 1.5,
  }
);

// Write content
terminal.writeLine('Hello, World!');
terminal.writeLine('This is line 2');

// Control scrolling
terminal.scrollTo(100);

// Setup callbacks
terminal.onInput((text) => console.log('Input:', text));
terminal.onScroll(() => console.log('Scrolled'));

// Cleanup when done
terminal.dispose();

Architecture

src/
├── core/
│   ├── Terminal.ts              # Main orchestrator
│   ├── font/                    # Font atlas loading, metrics
│   ├── text/                    # Text buffer, layout engine
│   ├── scroll/                  # Virtual scrolling, viewport
│   ├── input/                   # Caret, keyboard handling
│   └── renderer/                # WebGL pipeline
├── ui/react/                    # React wrapper
└── demo/                        # Demo application

Key Technical Decisions

  1. Virtual Scrolling: Paged array (1024 lines/page) for O(1) access
  2. Rendering: Instanced rendering with single quad geometry
  3. Font Pipeline: msdfgen → Node.js packing → PNG atlas + JSON metrics
  4. Performance: Reuse typed arrays, zero allocations in hot paths
  5. React Integration: Terminal owns RAF loop, React is thin wrapper

Font Generation

The font generation script calls msdfgen for each character and packs them into a texture atlas:

npm run generate:font

This creates:

  • public/fonts/cascadia-code.png - MSDF texture atlas
  • public/fonts/cascadia-code.json - Glyph metrics

Customization: Edit scripts/generate-font-atlas.mjs to:

  • Change font file path
  • Add/remove characters
  • Adjust glyph size or MSDF range
  • Modify atlas packing algorithm

Performance

Optimizations

  • ✅ Zero allocations in scroll/layout hot paths
  • ✅ Reuse typed arrays and object pools
  • ✅ Single texture bind per frame
  • ✅ Single draw call via instancing
  • ✅ Dirty flag prevents unnecessary renders
  • ✅ Overscan reduces layout thrashing

Benchmarks

  • 1M lines: Smooth 120 FPS scrolling
  • Memory: ~200MB for 1M lines @ 100 chars/line
  • Init time: <100ms for font loading + WebGL setup
  • Draw call: 1 per frame for all visible glyphs

Troubleshooting

msdfgen not found

Error: msdfgen not found in PATH

Install msdfgen (see Prerequisites above).

Font atlas missing

Error: Failed to load font metrics

Run npm run generate:font before starting the dev server.

Text looks blurry

Ensure LINEAR filtering is used (already configured). MSDF textures must NOT use sRGB colorspace.

Low FPS

  • Check GPU utilization (should be low, <10%)
  • Verify single draw call in Chrome DevTools > Rendering > Frame Rendering Stats
  • Reduce overscan if layout is bottleneck

Tech Stack

  • React 18.2+ - UI framework
  • TypeScript 5.2+ - Type safety
  • Vite 5.0+ - Build tool
  • WebGL 2 - GPU rendering
  • twgl.js 5.5+ - WebGL utilities
  • gl-matrix 3.4+ - Matrix math
  • msdfgen - Font atlas generation

License

MIT

Credits