Skip to content

@backendkit-labs/console-animations

npmLicenseNode

Enterprise-grade terminal animations for Node.js CLI applications and backend processes.

17 built-in animations — spinners, progress bars, loaders and visual effects — with terminal states (succeed / fail / warn), dynamic text updates, CI detection, and zero runtime dependencies.

bash
# Try it instantly
npx @backendkit-labs/console-animations

Installation

bash
npm install @backendkit-labs/console-animations

Quick Start

typescript
import { AnimationManager, AnimationType } from '@backendkit-labs/console-animations';

const manager = new AnimationManager();

const spinner = manager.start({
  type:   AnimationType.SPINNER,
  color:  'cyan',
  prefix: '  Installing packages ',
});

setTimeout(() => {
  manager.succeed(spinner.id, 'Packages installed');
}, 3000);

Available Animations

Spinners & Loaders

AnimationTypeUse case
SpinnerSPINNERTasks, installs, fetching
DotsDOTSWaiting, processing
PulsePULSEHeartbeat, status check
WormWORMIndeterminate progress
SnakeSNAKEScanning, searching
Bouncing BallBOUNCING_BALLLoading, buffering

Progress & Fill

AnimationTypeUse case
Progress BarPROGRESS_BARFile download, build steps
CyberpunkCYBERPUNKDeploy, upload, sync

Text & Visual Effects

AnimationTypeUse case
TypingTYPINGCommand output, logs
WavesWAVESAudio, processing
MatrixMATRIXData stream, encryption
HackerHACKERHex scan, network
RainRAINAmbient, idle state
FireFIREAlerts, hot paths
StarsSTARSSuccess, decorative
ParticlesPARTICLESAmbient
FuturistaFUTURISTASci-fi, startup

Terminal States

Stop animations with a visible result — the most important feature for professional CLIs:

typescript
manager.succeed(id, 'Build complete')   // ✔ Build complete   (green)
manager.fail(id, 'Build failed')        // ✖ Build failed     (red)
manager.warn(id, 'Skipped 3 files')     // ⚠ Skipped 3 files  (yellow)
manager.info(id, 'Cache hit')           // ℹ Cache hit        (cyan)

Presets

Ready-to-use configurations for the most common backend and CLI scenarios:

typescript
import { AnimationManager, Presets } from '@backendkit-labs/console-animations';

const manager = new AnimationManager();

const s = manager.start(Presets.install('Installing dependencies'));
const b = manager.start(Presets.build('Compiling TypeScript'));
const d = manager.start(Presets.deploy('Deploying to production'));
const c = manager.start(Presets.connect('Connecting to database'));
PresetAnimationColorUse case
Presets.install(text?)SPINNERcyannpm/package installs
Presets.build(text?)DOTSyellowCompilation, bundling
Presets.deploy(text?)WORMmagentaDeployments
Presets.connect(text?)PULSEblueDB / network connections
Presets.migrate(text?)SNAKEyellowDB migrations
Presets.download(text?, total?)PROGRESS_BARcyanDownloads with ETA
Presets.upload(text?, total?)CYBERPUNKgreenUploads
Presets.encrypt(text?)HACKERgreenBrightEncryption / hashing
Presets.scan(text?)MATRIXgreenSecurity scans
Presets.stream(text?)WAVEScyanData streaming

Progress Bar with ETA

typescript
const bar = manager.start(Presets.download('Downloading package', 100));

bar.setProgress(30);  // [████████░░░░░░░░░░░░░░░░░░░░░░]  30% | ETA: 7s
bar.setProgress(60);  // [████████████████░░░░░░░░░░░░░░]  60% | ETA: 3s
bar.setProgress(100); // [██████████████████████████████] 100% | 1.2s

manager.succeed(bar.id, 'Download complete');

Async Workflow with Auto-stop

typescript
// run() automatically calls succeed() on resolve, fail() on reject
const result = await manager.run(
  Presets.deploy('Deploying to production'),
  () => deployToProduction(),
  {
    successText: 'Deployed successfully',
    failText:    'Deployment failed',
  },
);

Dynamic Updates

typescript
const s = manager.start(Presets.install('Resolving packages'));

manager.update(s.id, { prefix: '  Downloading packages ' });
manager.update(s.id, { prefix: '  Linking dependencies ' });

manager.succeed(s.id, 'Installation complete');

CI / Non-TTY Detection

Automatic CI detection

Animations are automatically disabled in non-interactive environments (CI, piped output). Only terminal states are printed.

# In a terminal (interactive)
⠙ Building TypeScript...   ← animated

# In GitHub Actions / CI
✔ Building TypeScript       ← only final state

Detection is automatic via process.stdout.isTTY and process.env.CI — no configuration needed.

API Reference

AnimationManager

MethodSignatureDescription
start(config) → IAnimationCreates and starts an animation
stop(id) → voidStops silently
succeed(id, text?) → voidStops with ✔ (green)
fail(id, text?) → voidStops with ✖ (red)
warn(id, text?) → voidStops with ⚠ (yellow)
info(id, text?) → voidStops with ℹ (cyan)
update(id, partial) → voidUpdates config while running
pause(id) → voidFreezes current frame
resume(id) → voidResumes a paused animation
destroy(id) → voidStops and releases resources
destroyAll() → voidDestroys all active animations
get(id) → IAnimation | undefinedGets animation by ID
run<T>(config, task, opts?) → Promise<T>Wraps async task with auto-stop

AnimationBuilder

Fluent API for composing configs:

typescript
const config = new AnimationBuilder()
  .setType(AnimationType.WORM)
  .setColor('magenta')
  .setSpeed(60)
  .setPrefix('  Migrating database ')
  .build();

const anim = manager.start(config);

AnimationConfig

PropertyTypeDefaultDescription
typeAnimationTyperequiredAnimation type
idstringautoUnique animation ID
colorColorANSI color
speednumber80ms between frames
prefixstring''Text before the animation
suffixstring''Text after the animation
framesstring[]Custom frame array
widthnumber20Progress bar width
totalnumber100Progress bar total steps
showEtabooleanfalseShow ETA on progress bar

Colors

black red green yellow blue magenta cyan white gray
redBright greenBright yellowBright blueBright magentaBright cyanBright whiteBright

Events

typescript
manager.on(AnimationEvent.START,        (data) => { /* animation started */ });
manager.on(AnimationEvent.STOP,         (data) => { /* animation stopped */ });
manager.on(AnimationEvent.STATE_CHANGE, (data) => { /* state transition  */ });
manager.on(AnimationEvent.FRAME,        (data) => { /* new frame rendered */ });
manager.on(AnimationEvent.ERROR,        (data) => { /* error occurred     */ });

Custom Animations

typescript
import { AbstractAnimation, AnimationConfig } from '@backendkit-labs/console-animations';

class MyAnimation extends AbstractAnimation {
  constructor(config: AnimationConfig) { super(config); }

  protected buildFrames(): string[] {
    return ['◐', '◓', '◑', '◒'];
  }
}

Architecture

AnimationManager (Facade)
  ├── AnimationFactory    — creates animations by type
  ├── AnimationRegistry   — ID → IAnimation map
  ├── FrameScheduler      — adaptive loop, min 16 ms
  ├── RenderEngine        — stdout writer + ANSI + CI detection
  └── EventEmitter        — observer pattern

AbstractAnimation (Template Method)
  └── 17 concrete animations

AnimationBuilder   — fluent config builder
Presets            — ready-to-use configs for common tasks

Released under the Apache 2.0 License.