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

ttfx-node

v0.1.9

Published

Headless ttfx frames for JS CLI builders (sync napi binding)

Readme

ttfx-node

Terminal text effects for JS CLI builders — chalk-style. Same engine as the ttfx-js CLI (prebuilt Rust binary, all 37 effects), exposed as functions: no child processes, no Rust needed.

npm i ttfx-node
import { play, getFrames, listEffects } from 'ttfx-node';

await play('Deploy complete', 'decrypt');                 // animates in your terminal
const frames = getFrames('hi', 'beams', { seed: 1 });    // pure ANSI strings
console.log(listEffects().length);                        // 37

play(input, effect, opts?)

Animates in the current terminal, resolves when done. Hides the cursor while playing and restores it after — including on Ctrl-C, where the promise rejects with code INTERRUPTED instead of leaving a hidden cursor. Under NO_COLOR, non-TTY output, or noColor: true, prints the final frame as plain text (chalk-style), so --ci output stays clean.

getFrames(input, effect, opts?)

Renders headlessly to string[] — one full screenful per frame, ANSI-coded, top row first. Sync and deterministic per seed (virtual clock; wall time is never consulted). The canvas derives from the input unless fixed; terminal size is never read, so output is machine-independent.

const frames = getFrames('hi', 'decrypt', {
  seed: 1,                        // deterministic output
  frameRate: 60,                  // pacing hint for players
  canvasWidth: 40,                // fixed canvas (default: input-sized)
  canvasHeight: 10,
  tabWidth: 4,
  wrapText: false,
  noColor: false,
  xtermColors: false,             // 8-bit palette instead of 24-bit
  maxFrames: 10000,               // hard cap 100000
  randomEffect: false,            // pick from registry (seeded)
  includeEffects: ['wipe'],       // filter for randomEffect
  excludeEffects: ['matrix'],
  effectArgs: ['--typing-speed', '5'],  // ANY effect option, CLI-validated
});

effectArgs passes straight into the CLI parser, so every one of the 37 effects' options — current and future — works with identical validation and defaults, and invalid flags throw a descriptive Error. Empty/blank input throws NO INPUT.; oversized input, canvas (max 1000×500) or maxFrames throw before the engine runs.

Recommendations

Building a CLI with this? The patterns that work best:

  • Fire-and-forget → play(). One call animates and cleans up. Call it on a fresh line; it reserves its own rows below the prompt and never paints over your shell history.
  • Custom player, tests, or pre-baked output → getFrames(). Compute once, reuse the array (replay it, write it to a file, snapshot it). Same seed in, byte-identical frames out — snapshots never flake.
  • Always pass seed in tests. Omit it in production for variety.
  • Discover options from the CLI: npx ttfx-js <effect> --help lists every flag; paste them into effectArgs verbatim. Invalid flags throw immediately with the CLI's own error text.
  • Respect non-terminals. play prints plain final text under NO_COLOR, pipes, or CI automatically — test yours with NO_COLOR=1. Never gate your whole CLI on animation; treat it as decoration around plain output.
  • Handle Ctrl-C. play restores the cursor and rejects with code INTERRUPTED — catch it and choose your exit code:
    try { await play('Working…', 'beams'); }
    catch (e) { if (e.code !== 'INTERRUPTED') throw e; process.exit(130); }
  • Fix the canvas for layouts. Default canvases hug the input; if several animations share a screen, pass the same canvasWidth/canvasHeight so they align instead of jumping.
  • Mind the frame budget. maxFrames defaults to 10000; a fullscreen long-runner can hold tens of MB as strings. For ambient/background loops, prefer short inputs and bounded effects (wipe, beams) over open-ended ones.
  • Colors: 24-bit by default; xtermColors: true for limited terminals, noColor: true for logs.

Sync with the CLI

ttfx-node and the ttfx-js CLI build from the same engine tag, and CI asserts CLI --parity-dump and getFrames byte-identical per OS — a release fails if the API ever renders differently. See versions.json in ttfx-js for the mapping.

Credit

Every effect, the animation engine and the CLI are the work of TerminalTextEffects by ChrisBuilds, via the ttfx Rust port. This package only binds it for Node — if you like the effects, star the original.

License

MIT — the binding is MIT; the engine stays under its TTE/ttfx MIT terms (see THIRD-PARTY-NOTICES in the repo).