This page lists everything you can import from the ascii.rest npm package, grouped by import path. Each entry gives its signature, one line on what it does, and the page that shows it in use.
A few words come up everywhere:
- A piece is one animation, like
donut: a module withmetaand adefaultfunction. - A frame is the picture at one moment, as a string of text.
- A text piece is plain text in your page’s colour, drawn in a
<pre>. - A coloured piece (the scenes, logos, companies and distros) has colours of its own and is drawn on a
<canvas>.
The shortest working example plays a piece in a <pre id="art">:
import { mount } from "ascii.rest";
import { donut } from "ascii.rest/pieces";
const stop = mount(document.querySelector<HTMLElement>("#art")!, donut);
stop() stops it. If you use an AI coding agent, this page is also in llms-full.txt, with every other docs page.
Pick an import path
Each import path is one part of the package. Import only the ones you use.
| import | what it gives you | runs in | guide |
|---|---|---|---|
ascii.rest |
mount(), plus load, names, isPiece and canvas to find a piece by name |
a browser, for mount(); the rest anywhere |
typescript |
ascii.rest/pieces |
every piece, as named exports | anywhere | your own pieces |
ascii.rest/pieces/<name> |
one piece, and the type of its options | anywhere | typescript |
ascii.rest/banner |
banner(): any text in block letters, as a piece |
anywhere | banners |
ascii.rest/react |
the <Ascii> and <Banner> components |
React 18 or later | react |
ascii.rest/astro |
the Ascii Astro component |
Astro | astro |
ascii.rest/astro/banner |
the Banner Astro component |
Astro | astro |
ascii.rest/element |
the <ascii-art> and <ascii-banner> tags |
a browser | html |
ascii.rest/svg |
any piece or banner as an animated SVG | anywhere | svg |
ascii.rest/terminal |
a piece or a banner in a terminal | Node | terminal |
The package has no dependencies. React is an optional peer dependency, needed only for ascii.rest/react. Everything is typed.
ascii.rest
The main import: play a piece in an element, and find any piece by its name. Guide: typescript.
import { canvas, isPiece, load, mount, names } from "ascii.rest";
console.log(names.length); // 217
const name = new URLSearchParams(location.search).get("piece") ?? "donut";
if (isPiece(name)) {
const el = document.createElement(canvas.has(name) ? "canvas" : "pre");
document.body.append(el);
mount(el, await load[name]());
}
mount()
mount(el: HTMLElement, piece: Piece | Piece["default"], options?: MountOptions): () => void
Plays a piece in el and returns a function that stops it. In a <pre>, any piece is text in the <pre>’s colour. On a <canvas>, a coloured piece is drawn in its own colours.
It plays only while el is on screen and the tab is visible. For a reader who prefers reduced motion it holds one still frame, unless you pass motion: true. piece can also be a bare function that returns a frame function. Guide: typescript.
load
const load: Record<PieceName, () => Promise<Piece>>
One function for each piece, by name. await load["night-coast"]() imports that piece’s module. A bundler puts each piece in its own file, so a page downloads only the pieces it plays.
names
const names: PieceName[]
The names of every piece, like "night-coast", in alphabetical order.
isPiece()
isPiece(name: string): name is PieceName
Returns true when a string is a piece’s name. In TypeScript it also narrows the string to PieceName. A piece’s name has dashes: isPiece("night-coast") is true and isPiece("nightCoast") is false.
canvas
const canvas: ReadonlySet<PieceName>
The names of the coloured pieces: the scenes, logos, companies and distros. Draw these on a <canvas> to see their colours.
Types from ascii.rest
| type | what it is |
|---|---|
Piece<O> |
A piece module: { meta: Meta<O>; default(options?: Partial<O>): Frame }. |
Meta<O> |
What a piece says about itself: name, category, note, cols, rows, fps, and optionally options, palette, ground, cell, clock, loop and still. Each field is explained on your own pieces. |
Frame |
A frame function: (t: number, env?: Env) => string. It returns the frame at t seconds. |
Env |
The frame function’s second argument: { paper?: boolean; color?: Uint8Array }. Set paper for dark text on a light page. Pass color to get each cell’s index into meta.palette. |
Options |
Any piece’s options: Record<string, unknown>. |
Category |
One of the 15 categories: "scenes", "shapes", "space", "physics", "nature", "creatures", "objects", "generative", "effects", "ui", "data", "type", "logos", "companies" or "distros". |
PieceName |
Every piece’s name, as a union of strings: "a0", "agentmail" and so on. |
MountOptions |
The third argument of mount(): the piece’s own options, plus fps?: number and motion?: boolean. |
ascii.rest/pieces
Every piece, as a named export. Its export is its name in camelCase: night-coast is nightCoast, and rule-30 is rule30. Every piece is in the list on the home page. Guide: your own pieces, which explains what a piece module holds.
import { bigText, donut } from "ascii.rest/pieces";
console.log(donut.meta.cols, donut.meta.rows); // 40 22
console.log(bigText.default({ text: "hi" })(0)); // the frame at 0 seconds
Each piece is a module with two exports:
| export | what it is |
|---|---|
meta |
The piece’s Meta: its size, frame rate, options and colours. |
default(options?) |
Takes the piece’s options and returns its Frame function. |
One piece on its own
ascii.rest/pieces/<name> is one piece’s module, by the piece’s name, with dashes: ascii.rest/pieces/night-coast. The 113 pieces that take options also export a type for them: the piece’s name in PascalCase, plus Options. So big-text exports BigTextOptions, and spinners exports SpinnersOptions.
import * as spinners from "ascii.rest/pieces/spinners";
import type { BigTextOptions } from "ascii.rest/pieces/big-text";
const options: Partial<BigTextOptions> = { text: "hello" };
console.log(spinners.meta.options, options);
ascii.rest/banner
Turn any text into a piece in block letters with a drop shadow. The result plays anywhere a piece does: mount(), <Ascii>, svg() and play(). Guide: banners.
import { banner, drawable } from "ascii.rest/banner";
const hi = banner("hi", { shadow: "rounded" });
console.log(hi.default()(0));
console.log(drawable("héllo!")); // "hllo!": the font has no "é"
The first console.log prints:
▓▓╮ ▓▓╮ ▓▓╮
▓▓│ ▓▓│ ▓▓│
▓▓▓▓▓▓▓▓│ ▓▓│
▓▓╭───▓▓│ ▓▓│
▓▓│ ▓▓│ ▓▓│
╰─╯ ╰─╯ ╰─╯
banner()
banner(text: string, options?: BannerOptions): BannerPiece
Returns a piece that draws text in block letters. Every option is on banners.
It throws an error, with a message that says what to change, when:
- the font can draw none of
text, apart from spaces; fontoreffectis a name it doesn’t know, orshadowis neither a name it knows nor 16 characters;- a colour isn’t
#rrggbb, orcoloris an empty list; fillisn’t exactly one character, orglint.charsisn’t one or two;gap,pad,pixel,size.colsorsize.rowsisn’t a whole number (gapandpad0 or more, the others 1 or more);speed,max,glint.sweep,glint.every,glint.widthortype.stepisn’t above 0;glint.firstorglint.slantisn’t a number.
drawable()
drawable(text: string, font?: FontName | Font): string
Returns the characters of text that the font can draw, in the case you gave them. banner() leaves the rest out. The font is "block" by default.
fonts
const fonts: { block: Font; slim: Font; tall: Font; bold: Font; round: Font; wide: Font; mixed: Font; italic: Font }
The eight built-in fonts. block, slim, wide and italic are five rows tall, round six, tall and bold seven, and mixed nine. mixed is cased, so it draws lower case too. Each one is shown on banners.
shadows
const shadows: Record<ShadowName, string>
The built-in shadow styles, double, single, heavy, rounded and ascii. Each is a string of 16 line-drawing characters: shadows.rounded is " │││─╯╮┤─╰╭├─┴┬┼".
Types from ascii.rest/banner
| type | what it is |
|---|---|
BannerOptions |
Every option of banner(): font, pixel, gap, shadow, fill, effect, speed, glint, type, color, shadowColor, pad, size, max and name. Each is explained on banners. |
BannerPiece |
A Piece with two more fields: text, the characters it drew, and motion, { seconds, from, once, pass? }. See BannerPiece motion. |
Font |
A pixel font of your own: { height: number; glyphs: Record<string, string>; cased?: boolean }. Each glyph is its rows joined by a pipe character, with # for a pixel. Without cased, text is drawn in capitals. |
FontName |
"block", "slim", "tall", "bold", "round", "wide", "mixed" or "italic". |
ShadowName |
"double", "single", "heavy", "rounded" or "ascii". |
Effect |
How a banner moves: "glint", "type" or "still". |
Colors |
One colour as #rrggbb, or an array of two or more for a fade: string or readonly string[]. |
Themed<T> |
T, or { light?: T; dark?: T } for one value for each theme. color and shadowColor take it. |
BannerPiece motion
A banner’s motion field says how it moves. svg() reads it to play exactly one loop. The terminal banner() reads it to play the first glint, or the typing, once.
effect |
what motion holds |
|---|---|
"glint" |
seconds is the time from one glint to the next. The first glint crosses between the two times in pass. from is a moment when the glint is out of sight: an SVG’s loop starts there, and a banner held still shows it. once is false. |
"type" |
seconds is how long the letters take to type in, plus a short pause. from is 0 and once is true. |
"still" |
seconds and from are 0, and once is false. |
import { banner } from "ascii.rest/banner";
banner("hi").motion; // { seconds: 3.2, from: 0, once: false, pass: [0.5, 2.9] }
banner("hi", { glint: { first: 0 } }).motion.from; // 2.8: at 0 the glint is in sight
banner("hi", { effect: "type" }).motion; // { seconds: 0.533..., from: 0, once: true }
ascii.rest/react
Two React components. Both are client components ("use client"), so they also work in the Next.js app router. Guides: react and next.js.
import { Ascii, Banner } from "ascii.rest/react";
export default function Page() {
return (
<>
<Banner text="hello" color={["#f97316", "#f778ba"]} shadow="rounded" />
<Ascii piece="donut" />
</>
);
}
Ascii
function Ascii(props: AsciiProps): JSX.Element
Plays a piece. It renders a <pre>, or a <canvas> for a coloured piece, with role="img". Guide: react.
| prop | type | what it does |
|---|---|---|
piece |
Piece or PieceName |
The piece to play: a module, or a name to load when it mounts. Required. |
options |
MountOptions |
The piece’s own options, plus fps and motion. |
label |
string |
What the picture shows, for screen readers. The piece’s name by default. |
mono |
boolean |
Draws a coloured piece as text in one colour, in a <pre>. |
className |
string |
A class for the <pre> or <canvas>. |
style |
CSSProperties |
Inline styles for the <pre> or <canvas>. |
Banner
function Banner(props: BannerProps): JSX.Element | null
Draws any text as a banner. Every option of banner() is a prop. If banner() throws, it renders nothing, and the console says why with console.warn: <Banner> could not draw: .... Guide: react.
| prop | type | what it does |
|---|---|---|
text |
string |
The text. Required. |
every BannerOptions field |
see banners | color, shadow, font, effect and the rest. |
label |
string |
What the picture shows, for screen readers. The text by default. |
mono |
boolean |
Draws a coloured banner as text in one colour, in a <pre>. |
fps |
number |
Overrides its frame rate. 0 is ignored: for a banner that doesn’t move, use effect="still". |
className |
string |
A class for the <pre> or <canvas>. |
style |
CSSProperties |
Inline styles for the <pre> or <canvas>. |
Types from ascii.rest/react
AsciiProps and BannerProps are the props above. BannerOptions, MountOptions, Piece and PieceName are exported here too, so one import is enough.
ascii.rest/astro
Two Astro components, each the default export of its own path. For a text piece or banner, a still frame is rendered on the server, so the page shows it before any script runs. A coloured one keeps its space until its canvas draws. Guide: astro.
---
import Ascii from "ascii.rest/astro";
import Banner from "ascii.rest/astro/banner";
---
<Banner text="hello" shadow="rounded" />
<Ascii piece="night-coast" fps={12} />
Ascii
import Ascii from "ascii.rest/astro"
Plays a piece. It renders an <ascii-art> tag.
| prop | type | what it does |
|---|---|---|
piece |
PieceName |
The piece’s name. It takes a name only, not a module. An unknown name throws when the page renders. Required. |
options |
MountOptions |
The piece’s own options, plus fps and motion. |
fps |
number |
Overrides its frame rate. |
label |
string |
What the picture shows, for screen readers. The piece’s name by default. |
mono |
boolean |
Draws a coloured piece as text in one colour. |
class |
string |
A class for the <ascii-art> tag. |
Banner
import Banner from "ascii.rest/astro/banner"
Draws any text as a banner. It renders an <ascii-banner> tag. If banner() throws, the error is thrown when the page renders.
| prop | type | what it does |
|---|---|---|
text |
string |
The text. Required. |
every BannerOptions field |
see banners | color, shadow, font, effect and the rest. |
label |
string |
What the picture shows, for screen readers. The text by default. |
mono |
boolean |
Draws a coloured banner as text in one colour. |
class |
string |
A class for the <ascii-banner> tag. |
This Banner has no fps prop.
ascii.rest/element
Importing this module defines two HTML tags, <ascii-art> and <ascii-banner>. On a server, where there is no DOM, it does nothing. The script https://ascii.rest/ascii.js is the same module, for a page with no build step. Guide: html.
import "ascii.rest/element";
const art = document.createElement("ascii-art"); // typed as AsciiArt
art.setAttribute("piece", "donut");
document.body.append(art);
AsciiArt
class AsciiArt extends HTMLElement
The <ascii-art> tag. Its attributes are piece, src, fps, options, label and mono. An unknown piece draws nothing and logs nothing. Guide: html.
AsciiBanner
class AsciiBanner extends HTMLElement
The <ascii-banner> tag. Its attributes are text, font, shadow, fill, effect, speed, color, shadow-color, pixel, gap, options, label and mono. An empty attribute counts as no attribute, except mono, which is on whenever it is there. If banner() throws, the tag draws nothing, and the console says why with console.warn: <ascii-banner> could not draw: .... Guide: html.
define()
define(tag?: string): void
Defines <ascii-art> under the name tag, and <ascii-banner>, if they aren’t defined yet. tag is "ascii-art" by default. Importing the module already calls define(), so call it yourself only to add another name, like define("my-art").
The module also tells TypeScript about both tags, so document.querySelector("ascii-art") has the type AsciiArt | null.
ascii.rest/svg
Turn any piece, or a banner, into an animated SVG string. An SVG plays where scripts can’t run, like a GitHub README or an <img>. It works in a browser, in Node, in a Worker or at build time. Guides: svg and github readme.
Most people only need svg() and bannerSvg(). The rest, from part() on, is for building your own SVG.
import { writeFileSync } from "node:fs";
import { bannerSvg, svg } from "ascii.rest/svg";
import { rust } from "ascii.rest/pieces";
writeFileSync("rust.svg", svg(rust));
writeFileSync("rust.dark.svg", svg(rust, { dark: true }));
writeFileSync("banner.svg", bannerSvg("my-project", { art: rust, color: "art", tagline: "fast, safe, fun" }));
svg()
svg(piece: Piece, options?: SvgOptions): string
Returns one loop of a piece as an animated SVG, on the piece’s meta.ground when it has one, as a scene does. It throws for an ink that isn’t #rrggbb, a scale that isn’t a number of 0 or more, or an fps outside 1 to 60. Guide: svg.
bannerSvg()
bannerSvg(text: string, options?: Omit<BannerOptions, "color"> & { color?: BannerSvgColor } & BannerSvgOptions): string
Returns a banner as an animated SVG, with an optional tagline under it, a piece beside or above it, and a background. Its options are every option of banner(), plus BannerSvgOptions. Its color also takes "art", the art’s own colour. Guide: svg.
It throws when banner() would, and also when:
backgroundortaglineColorisn’t#rrggbb, for either theme, whether or not it is used;taglineSize,spacing,padding,radius,artSizeorscaleisn’t a number of 0 or more;placeisn’t"left","right","above"or"below", oralignisn’t"start","center"or"end";fpsis outside 1 to 60;artis{ svg }with an SVG thatascii.rest/svgdidn’t write.
loopOf()
loopOf(piece: Piece, options?: Options): { every: number; from: number; once?: boolean }
The loop svg() plays: every, its length in seconds, and from, the time it starts. It is the first of these that applies:
- a banner’s own
motion(see BannerPiece motion); every: 0, for a still piece, one whosemeta.fpsis 0;- the piece’s
meta.loop; - for a logo, company or distro, the time between its glints or scans;
- 4 seconds.
part()
part(loop: Loop & { cell?: number }, prefix?: string): Part
Samples a Loop into frames and returns them as a Part, with its CSS class names starting with prefix. It throws for an fps outside 1 to 60. Use it to put frames of your own in an SVG.
wrap()
wrap(part: Part, label: string, scale?: number): string
Puts a Part in a complete <svg>, titled label for screen readers. scale is the pixels per cell width, 10 by default.
namespaced()
namespaced(svg: string, prefix: string): Part | null
Turns an SVG that this module wrote back into a Part, with its class names, and its fade’s gradient, under prefix. Use it to put two in one SVG, or two inline in one HTML page. It returns null for any other SVG.
inkOf()
inkOf(part: Part): string | null
The colour that inks the most cells of a part’s first frame, such as a logo’s main colour. bannerSvg() uses it for color: "art".
darkColor()
darkColor(hex: string): boolean
Returns true when a #rrggbb colour is dark. bannerSvg() uses it to pick light or dark colours for a background.
MONO and FACES
const MONO: string and const FACES: string
MONO is the CSS rule that every part’s text rows share. part() leaves it out of a part’s css, and wrap() adds it. Add it to your SVG’s <style> yourself if you put parts in an SVG without wrap().
FACES is the list of monospace fonts that MONO names. Use it to set text of your own, such as a caption, in the same fonts at another size.
Types from ascii.rest/svg
| type | what it is |
|---|---|
SvgOptions |
The options of svg(): dark, ink, seconds, from, fps, once, scale, label and options. |
BannerSvgOptions |
What bannerSvg() adds to the banner options: dark, tagline, taglineColor, taglineSize, art, place, artSize, spacing, align, background, padding, radius, scale, fps and label. |
BannerSvgColor |
What the color of bannerSvg() takes: anything the color of banner() takes, or "art". |
Loop |
Frames over time, for part(): cols, rows, palette, every, from and at(t), and optionally once and fps. |
Part |
A picture ready to sit in an SVG: { width, height, css, body }, in SVG units. |
Shot |
One frame: { text: string; color: Uint8Array }. color holds each cell’s palette index. |
ascii.rest/terminal
Play a piece, or print a banner, in a terminal: a splash screen for your CLI. It runs in Node and uses only Node’s built-in modules. Guide: terminal.
import { banner, play, still } from "ascii.rest/terminal";
await banner("my-cli", { color: ["#ff6a00", "#f778ba"], tagline: "v1.0" });
await play("donut", { seconds: 2 });
console.log(await still("donut"));
play()
play(piece: Piece | PieceName, options?: PlayOptions): Promise<Played>
Plays a piece in the middle of the terminal’s alternate screen. It resolves when it stops: after seconds, on any key, or on Ctrl+C. The terminal is put back however it stops. With no terminal to draw on, such as a pipe, it draws nothing and resolves at once. Guide: terminal.
banner()
banner(text: string, options?: PrintOptions): Promise<Bannered>
Prints a banner where the cursor is, moves it once, and leaves it in the scrollback. Piped, it prints at once with no colour. It keeps the banner a column narrower than the terminal. If even its narrowest letters don’t fit, it prints the text as one plain line. This is not the banner() from ascii.rest/banner: that one returns a piece, and this one prints. Guide: terminal.
still()
still(piece: Piece | PieceName, options?: { light?: boolean; options?: Options }): Promise<string>
Returns one frame as plain text, for a pipe or a log. It is the frame at meta.still, or the first. For a typed banner, that frame shows every letter.
Types from ascii.rest/terminal
| type | what it is |
|---|---|
PlayOptions |
The options of play(): seconds, mono, light, fps, options (the piece’s own) and out. |
Played |
What play() resolves to: cropped, interrupted, piece: { cols, rows } and terminal: { cols, rows }. |
PrintOptions |
The options of the terminal banner(): every BannerOptions field except size and max, plus seconds (1 by default), tagline, light and out. |
Bannered |
What the terminal banner() resolves to: cols, rows and interrupted. cols and rows are 0 when the terminal was too narrow and it printed plain text. |
Output |
Where to draw: process.stdout by default, or any object with write(text) and optionally isTTY, columns, rows, on and off. |
Over HTTP
Some of the package is also served from ascii.rest itself, with nothing to install. Every path below is on https://ascii.rest.
| path | what it is | guide |
|---|---|---|
/ascii.js |
The ascii.rest/element module, for a <script type="module"> tag. |
html |
/<module>.js |
Every compiled module, such as /mount.js, /banner.js or /pieces/donut.js, to import on a page with no build step. |
html |
/svg/<name>.svg |
Each logo, company and distro as an animated SVG. Add .dark before .svg for dark pages. |
github readme |
/banner/<text>.svg |
A banner as an animated SVG. Add .dark before .svg for dark pages. Its options go in the query: color, bg, font, shadow, fill, effect, speed, tagline, art, place and size. |
github readme, banner maker |
/r/<name>.json |
A shadcn registry item, for npx shadcn add or npx ascii.rest add. /r/registry.json lists them all. |
your own copy |
/og/<name>.png |
A piece’s share image, 1200 by 630 pixels. | |
/llms.txt, /llms-full.txt |
The docs as plain text, for an AI coding agent. | introduction |
Next
- typescript:
mount(), frames and the types, with examples. - banners: every option of
banner(). - cli: the
npx ascii.restcommand.