Skip to content

What is @shaisrc/tty? โ€‹

@shaisrc/tty โ€” โ€œA KISS ASCII Rendererโ€ โ€” is a minimalist, high-performance library for rendering ASCII/text-based graphics in the browser and beyond.

Philosophy โ€‹

Unlike heavy game frameworks, @shaisrc/tty provides:

  • Simple functions over complex abstractions
  • Composable helpers instead of rigid components
  • Output-agnostic design - works anywhere text can be rendered
  • Developer experience first - chainable API, TypeScript support, smart defaults

๐Ÿšง Release Status โ€‹

Current builds are beta. A stable 0.1.0 release is blocked by:

  • DOMTarget (browser DOM render target for accessibility)

Who is it for? โ€‹

@shaisrc/tty is perfect for:

  • ๐ŸŽฎ Game developers building roguelikes, RPGs, or text-based games
  • ๐ŸŽจ Creative coders exploring ASCII art and procedural generation
  • ๐Ÿ“Š Dashboard builders creating text-based UIs
  • ๐ŸŽ“ Educators teaching game development concepts
  • ๐Ÿ”ง Tool makers building CLI visualizations in the browser

Core Principles โ€‹

1. KISS (Keep It Simple, Stupid) โ€‹

No unnecessary complexity. Every method does one thing well.

typescript
renderer.clear().box(10, 5, 20, 10).drawText(12, 7, "Hello!").render();

2. Output Agnostic โ€‹

Same API works with different outputs:

  • Canvas - Browser rendering with fonts and colors
  • DOM - HTML elements for accessibility (planned)
  • Custom - Extend for any target

3. Performance First โ€‹

  • Double-buffering prevents flicker
  • Dirty rectangle optimization
  • Minimal allocations in game loops
  • Designed for 60 FPS

4. Excellent DX โ€‹

  • Chainable methods
  • TypeScript with full type inference
  • Comprehensive JSDoc
  • Smart defaults
  • Clear error messages

How It Works โ€‹

1. Render Target โ€‹

First, create where your ASCII will be displayed:

typescript
const canvas = document.getElementById("game");
const target = new CanvasTarget(canvas, {
  width: 80,
  height: 24,
  charWidth: 8,
  charHeight: 16,
});

2. Renderer โ€‹

Then create a renderer:

typescript
const renderer = new Renderer(target);

3. Draw โ€‹

Use chainable methods to draw:

typescript
renderer
  .clear()
  .box(5, 5, 30, 10, { style: "double" })
  .centerText(8, "Game Title", { fg: "yellow" })
  .render(); // Flush to screen

4. Game Loop (Optional) โ€‹

For games, use the built-in game loop:

typescript
const game = new GameLoop(
  (deltaTime) => {
    // Update game state
  },
  () => {
    // Draw everything
    renderer.clear()./* ... */.render();
  },
  { fps: 60 },
);

game.start();

Key Features โ€‹

Layers โ€‹

Separate visual concerns:

typescript
renderer
  .layer("background")
  .fill(0, 0, 80, 24, " ", null, "blue")
  .layer("entities")
  .setChar(player.x, player.y, "@")
  .layer("ui")
  .box(0, 0, 20, 5)
  .layerOrder(["background", "entities", "ui"])
  .render();

Camera โ€‹

For scrolling worlds:

typescript
renderer
  .follow(player.x, player.y) // Camera follows player
  .setChar(player.x, player.y, "@") // Draw using world coords
  .render();

Helpers โ€‹

Common UI patterns built-in:

typescript
renderer.menu(10, 5, ["New Game", "Load", "Quit"], {
  selected: 0,
  indicator: ">",
  border: true,
});

renderer.progressBar(10, 15, 30, health / maxHealth, {
  style: "blocks",
  fillFg: "green",
});

renderer.panel(5, 5, 40, 15, {
  title: "Inventory",
  content: items,
  scrollOffset: 0,
});

Comparison โ€‹

vs Game Frameworks (Phaser, PixiJS) โ€‹

  • โœ… Much lighter weight
  • โœ… Focused on ASCII/text rendering
  • โœ… Output agnostic
  • โŒ Not for sprite-based games

vs DIY Canvas โ€‹

  • โœ… Ready-to-use helpers
  • โœ… Layers and camera built-in
  • โœ… Input management
  • โœ… Game loop
  • โœ… Optimized rendering

Next Steps โ€‹

Ready to start building?

Released under the MIT License.