Alto

Alto turns broken images into accessible ASCII fallbacks.
Buzz Aldrin standing on the lunar surface during Apollo 11
0x0

How To Use Alto

Install the npm package, import the CSS, then let Alto replace failed images or render loaded pixels as sized, colored ASCII.

Install

npm install alto-ascii

LLM Skill

Give this file to an agent so it has the package-specific integration rules, resolution guidance, and browser constraints up front.

Download SKILL.md
---
name: alto-ascii
description: Alto ASCII image fallback guidance for accessible alt-text-to-ASCII rendering. Use when integrating, debugging, documenting, or building with the alto-ascii package, including broken-image replacement, local image conversion, React or Next usage, CSS imports, resolution controls, and accessible fallback behavior.
metadata:
  priority: 4
  docs:
    - "https://mootbing.github.io/Alto/"
    - "https://github.com/Mootbing/Alto"
  pathPatterns:
    - "package.json"
    - "src/**"
    - "examples/**"
  bashPatterns:
    - "\\bnpm\\s+(?:install|add)\\s+alto-ascii\\b"
    - "\\bpnpm\\s+add\\s+alto-ascii\\b"
    - "\\byarn\\s+add\\s+alto-ascii\\b"
---

# Alto ASCII

Use Alto to turn broken images, planned image fallbacks, or local image previews into accessible ASCII renderings driven by meaningful alt text.

## Install

```bash
npm install alto-ascii
```

Import the stylesheet once in the application entrypoint.

```js
import "alto-ascii/style.css";
```

## Automatic broken-image fallbacks

Use `installAlto()` when ordinary image elements should be observed and replaced only after they fail to load.

```js
import "alto-ascii/style.css";
import { installAlto } from "alto-ascii";

const stopAlto = installAlto({
  resolution: "1x"
});
```

- Keep the original `alt` text specific and human-readable.
- Prefer explicit `data-alto-columns` and `data-alto-rows` when a fallback must match a fixed slot.
- Call the returned cleanup function before tearing down a routed page or temporary preview.

## Planned local conversion

Use `imageToAscii()` when an image loads successfully and the UI intentionally wants an ASCII version.

```js
import { createAltoFallback, fitAltoFallback, imageToAscii } from "alto-ascii";

const image = document.querySelector("img");
const frame = await imageToAscii(image, {
  colorMode: "color",
  columns: 120,
  rows: 64,
  maxColumns: 520,
  maxRows: 340,
  output: "frame"
});

const fallback = createAltoFallback(image.alt, {
  ascii: frame.ascii,
  aspectRatio: image.naturalWidth / Math.max(1, image.naturalHeight)
});

image.replaceWith(fallback);
fitAltoFallback(fallback);
```

## Resolution guidance

- Use `resolution` for source-relative scales such as `"4x"`, `"2x"`, `"1x"`, `"0.5x"`, and `"0.25x"`.
- Use explicit `columns` and `rows` for container-aware demos or responsive slots.
- Clamp high-resolution conversions with `maxColumns` and `maxRows`.
- Recompute ASCII after layout changes when the fallback must adapt to the rendered element size.

## Color guidance

- `imageToAscii()` returns plain text with no per-cell color metadata by default.
- Use `output: "frame"` plus `colorMode: "color"` to receive per-cell sampled RGB colors.
- Use `output: "frame"` plus `colorMode: "black-and-white"` when metadata is useful but binary black/white colors are preferred.
- Render `frame.ascii` for text-only output, or render `frame.cells` as character spans with `--alto-cell-color` for colored demos.

## Accessibility and browser constraints

- Preserve useful alt text; Alto uses it as the accessible label for the fallback.
- Treat decorative images as decorative and avoid inventing meaningful labels for them.
- Import the CSS so `.alto-fallback` receives the package styling.
- Convert local assets or CORS-safe remote images; browser canvas pixel reads fail for tainted cross-origin images.

Automatic Broken Image Fallbacks

<link rel="stylesheet" href="/node_modules/alto-ascii/src/alto.css" />

<img
  src="/missing-photo.jpg"
  alt="A yellow kayak crossing a blue alpine lake at sunrise"
  data-alto-resolution="high"
/>

<script type="module">
  import { installAlto } from "alto-ascii";

  installAlto();
</script>

Keep alt text readable and meaningful. Alto uses that same text as the accessible label for the generated fallback.

Use Exact Dimensions

<img
  src="/missing-photo.jpg"
  alt="Glass building at night"
  data-alto-columns="80"
  data-alto-rows="48"
/>

Exact columns and rows override density presets.

Use Source Scale

const ascii = await imageToAscii(imageElement, {
  resolution: "0.5x"
});

For image conversion, use 4x, 3x, 2x, 1x, 0.75x, 0.5x, or 0.25x.

Color Frame Output

const frame = await imageToAscii(imageElement, {
  colorMode: "color",
  output: "frame",
  resolution: "0.5x"
});

frame.ascii;
frame.cells;

Use frame.ascii for plain text, or render frame.cells as spans with --alto-cell-color for sampled per-character colors.

Convert An Image To ASCII

import { createAltoFallback, fitAltoFallback, imageToAscii } from "alto-ascii";
import "alto-ascii/style.css";

const image = document.querySelector("img");
const frame = await imageToAscii(image, {
  colorMode: "color",
  maxColumns: 4800,
  maxRows: 3600,
  output: "frame",
  resolution: "1x"
});

const fallback = createAltoFallback(image.alt, {
  ascii: frame.ascii,
  aspectRatio: image.naturalWidth / image.naturalHeight
});

document.body.append(fallback);
fitAltoFallback(fallback);

Usage

import { AltoImage } from "alto-ascii/react";
import "alto-ascii/style.css";

export function Example() {
  return (
    <AltoImage
      src="/missing-photo.jpg"
      alt="Portrait of Jules in a green jacket"
      fallbackResolution="high"
    />
  );
}

Accessibility Notes

  • Do not put ASCII art inside the alt attribute. Keep the alt text human-readable.
  • Use empty alt="" only for decorative images.
  • The ASCII output is visual decoration. The accessible label remains the original alt description.