# ascii.rest: animated ASCII art that stays inside one monospace face

> bas3line/ascii is a TypeScript package of 240 animated ASCII pieces that run in React, Next.js, Astro, plain HTML, SVG or a terminal, plus a kit for generating new ones. It is aimed at developers who want motion on a page without leaving a plain text aesthetic.

**bas3line/ascii** — Animated ascii art for web pages, in TypeScript: React, Next.js, Astro, or one HTML tag

- Repository: https://github.com/bas3line/ascii
- Website: https://ascii.rest
- Stars: 1,159 · Forks: 68
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/bas3line-ascii

## A quiet aesthetic with one moving part

The project description calls itself animated ascii art for web pages in TypeScript, and the README explains the motivation in unusually personal terms. The author says he has always liked Markdown files and terminal style websites: plain text, one monospace face, nothing that moves without a reason. The stated reference point is the quiet web that planetscale.com does well, and the target reader is someone who likes minimalism.

That framing matters more than the feature list. This is not a general purpose animation library, and it is not trying to be one. The pieces are ASCII drawings, they sit on a monospace grid, and the ambition is to add a small amount of motion to pages that otherwise look like a terminal. The package description in package.json widens the framing a little: animated ascii art for web pages, READMEs and terminals, in TypeScript, delivered as React, Next.js, Astro, one HTML tag, SVG, or copied into your project.

The catalog is large for a single purpose. The README states there are 240 pieces, ranging from full colour scenes to loaders, charts, language logos, Linux distros, spinning shapes and physics.

## One custom element, no build step, three frameworks

The most striking claim is that a piece turns on a page with a single tag. The README puts it directly: the donut turns on a page with one tag, `<ascii-art piece="donut"></ascii-art>`. The project topics list includes web components, and package.json exposes an `./element` entry pointing at a built file, with the package marked as having side effects for that file, which is the signature of a custom element that registers itself on import.

The same piece can also be imported directly, and the `./pieces` export path supports both a single piece and a wildcard for many. Because the pieces are ordinary module exports, the same file can serve a React app, an Astro page, a static HTML page, an SVG file or a terminal, and the README says the kit output is a normal piece that plays in all of those places.

That portability is the real architectural bet. Rather than shipping a canvas renderer per framework, the project appears to keep the drawing logic in one place and treat rendering as a surface. The README does not document the rendering internals, so how the frames are painted into a DOM node, into an SVG file or into a terminal cell grid is not something you can confirm from the documentation alone.

## Installing from npm, or copying the source in

The README gives three routes, and the choice between them determines how much of your page depends on somebody else's server.

The first is a normal package install:

```sh
npm install ascii.rest
```

The second is no install at all. The HTML tag path loads everything from ascii.rest, so a page with the element in it pulls its assets from the service instead of your bundle.

The third is copying the source into the repository so you can keep and change it, either through shadcn or through the project's own CLI:

```sh
npx shadcn@latest add https://ascii.rest/r/ascii.json https://ascii.rest/r/donut.json
npx ascii.rest add ascii donut
```

The two commands do the same job by different routes, shadcn pulling registry JSON, the CLI driving its own add command. The registry directory in the repository layout is consistent with the shadcn registry format. package.json also declares a `bin` entry mapping `ascii.rest` to `dist/cli.js`, which is how the `npx ascii.rest` invocation resolves. The docs at ascii.rest/docs are the stated place for every option.

## The kit builds pieces from words instead of coordinates

Beyond consuming the 240 finished pieces, the project offers a kit for making your own. The README pitches it as one line, by name, with options in words and no maths, and shows the shape of the API:

```ts
import { clockFace, plasma, sea, spinning, torus } from "ascii.rest/kit";

export const ocean = sea({ palette: "ocean" });
export const donut = spinning(torus(), { speed: "slow" });
export const hot = plasma({ palette: "fire" }).mask("HOT");
export default clockFace();
```

Three building blocks are visible here. Looks are the visual body, things like a sea, a plasma, aurora, flames, rain and a galaxy. Motions wrap a look so it spins, bounces or floats, as `spinning(torus(), { speed: "slow" })` shows. Widgets are the ready made interface pieces, namely a clock, a progress bar, a gauge and a chart, with `clockFace` being one of them.

When no recipe fits, the kit accepts a description instead. The README works through a glass of water as a cup made of glass, with water inside and bubbles rising, and writes the result to an SVG for a README file:

```ts
import { writeFileSync } from "node:fs";
import { svg } from "ascii.rest/svg";
import { bubbles, cup, emit, glass, inside, picture, shape, water } from "ascii.rest/kit";

const drink = inside(cup(), { fill: "half" });
const glassOfWater = picture([shape(cup(), glass()), shape(drink, water()), emit(bubbles(), { inside: drink })], { name: "glass of water", cols: 32, rows: 16 });
writeFileSync("glass.svg", svg(glassOfWater));
```

The `picture` call takes a list of parts and a `cols` and `rows` grid, so the piece is explicit about its dimensions. The README lists the deeper layers the kit exposes, down to fields, drawing, maths, 3D scenes, particles, effects, layouts, images, materials and SVG drawings.

## The CLI plays a piece in your terminal while you write it

Two commands cover the preview and export loop, and they take a file rather than a piece name:

```sh
npx ascii.rest play sea.ts --watch
npx ascii.rest svg sea.ts --out sea.svg
```

The first runs a file's piece in the terminal and keeps watching, so the loop is edit the file, see the frame change, repeat. The second writes the same piece out as SVG. Because the kit output is described as a normal piece, the file you are watching and the file you are exporting come from the same pipeline.

For a workflow where the art lives next to the code that generates it, that is the practical part of the kit. You get the drawing and the source in one repository, and the terminal is the fastest way to tell whether a palette choice or a motion speed reads correctly before it reaches a browser. The README does not document flags beyond these, so options such as frame rate for the CLI are not covered by the documentation and would have to be checked in the docs site.

## React usage with named pieces and options

The React entry point exposes an `Ascii` component and a `Banner` component, with pieces imported from the `./pieces` path:

```tsx
import { Ascii, Banner } from "ascii.rest/react";
import { donut } from "ascii.rest/pieces";

<Ascii piece={donut} />
<Ascii piece="night-coast" />                          // fetched by name when it mounts
<Ascii piece={donut} options={{ fps: 12 }} className="art" />
<Ascii piece="rust" mono />                            // a logo in one ink
```

Three behaviours are visible in those four lines. A piece can be passed as an imported object or as a name string, and the inline comment states that the named form is fetched by name when the component mounts, which is a network request at runtime rather than a bundler import. Options are passed as an object, and `fps` sets the frame rate. A `mono` flag renders in a single ink, which suits a language logo like the rust piece.

The `Banner` component is for text, and the README shows it taking a `text` prop and an array of `color` values, which is how the project builds the banner image used in its own README. package.json keeps `./banner` as its own export path, and `./terminal` and `./svg` are separate entries too, so the package is split by surface rather than shipping one bundle to everyone.

## Version 0.4.0, MIT terms, and a busy commit cadence

The package.json version field reads 0.4.0, and the repository has no GitHub releases, so upgrades arrive through the npm package rather than through tagged release notes. The licence field on the repository says MIT, and the package.json licence field agrees, so copying the source into your own project carries the same terms as using the dependency.

On maintenance, the picture is unusually current. The last push was on 2026-10-17, only days before the present, and the repository carries a CI badge and strict TypeScript configuration referenced from src/types.ts. The top level layout includes a `site` directory for the ascii.rest pages, a `registry` directory for the shadcn style registry, a `skills` directory, `examples` with a kit folder, and `scripts`.

Two costs are worth naming. A version below 1.0 means the public API can still move, so a pinning policy is worth having. And the fetch by name behaviour of the React component, combined with the HTML tag loading from ascii.rest, means part of your page can depend on a third party service at runtime unless you copy the source in.

## Conclusion

Use ascii.rest when you want a small animated ASCII surface inside a React, Next.js or Astro product and you are willing to depend on ascii.rest at runtime or copy the source in. Do not reach for it in a fully offline or air gapped page, because the plain HTML tag path loads assets from ascii.rest, and verify the `npm install ascii.rest` path and the `./pieces` export entry in your bundler before committing. The project is MIT licensed, the last push was on 2026-10-17, and the package version in package.json is 0.4.0, which still reads as pre one.

## FAQ

### How do I install ascii.rest?

The README lists three routes: `npm install ascii.rest`, using the HTML tag with no install at all, or copying the source in through shadcn or the CLI with `npx ascii.rest add ascii donut`. Full option lists are said to live in the docs at ascii.rest/docs.

### How do I show an animated ASCII piece in React or Next.js?

Import `Ascii` from `ascii.rest/react` and a piece from `ascii.rest/pieces`, then render `<Ascii piece={donut} />`. You can also pass a name string such as `piece="night-coast"`, which is fetched by name when the component mounts.

### Can I make my own ASCII animation instead of using a ready piece?

Yes. The `ascii.rest/kit` entry point exports looks, motions and widgets such as `sea`, `plasma`, `spinning` and `clockFace`, and you can describe a scene from parts when no recipe fits. The `npx ascii.rest play sea.ts --watch` command previews a file in the terminal as you edit it.

### Does ascii.rest work without a build step?

The README says the HTML tag loads everything from ascii.rest, so the `<ascii-art piece="donut"></ascii-art>` element needs no install. That path depends on the ascii.rest service being reachable at runtime.

### What licence is ascii.rest released under?

The licence field on the repository says MIT, and package.json lists the same MIT licence. The package version is 0.4.0 and the repository has no GitHub releases.

## Sources

- [bas3line/ascii on GitHub](https://github.com/bas3line/ascii)
- [Issues](https://github.com/bas3line/ascii/issues)
- [License: MIT](https://github.com/bas3line/ascii/blob/main/LICENSE)
- [Project website](https://ascii.rest)
- [README](https://github.com/bas3line/ascii/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bas3line-ascii
