# Server rack

A data-centre rack in box-drawing glyphs, with drive LEDs that flicker in busy spells, a slow heartbeat, port lights and light pulses running along the fibres.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. The asciicn agent skill, for building any ASCII effect on the engine, is at [/.well-known/agent-skills/asciicn/SKILL.md](/.well-known/agent-skills/asciicn/SKILL.md).

> **This is an example, not the only option.** It is one component built on the asciicn engine. Install it when it is what you were asked for. For any other look, don't stretch its props to fit: write your own field on `AsciiShader` ([Write your own](/docs/engine/write-your-own.md)), or draw a CPU grid with `AsciiGrid`, and read this example's source for technique. Its full source is in [https://asciicn.dev/r/server-rack.json](https://asciicn.dev/r/server-rack.json), under `files[].content`.

## Installation [#installation]

```bash
npx shadcn@latest add https://asciicn.dev/r/server-rack.json
```

## Usage [#usage]

```tsx
import { ServerRack } from "@/components/asciicn/server-rack";

export function StatusHero() {
  return (
    <section className="relative isolate min-h-[520px]">
      <ServerRack intensity={0.5} className="absolute inset-0 -z-10" />
      <h1>All systems nominal</h1>
    </section>
  );
}
```

The rack is seen from the front. A fibre patch panel and a 48-port core switch sit at the top, a UPS at the bottom, and between them a mix of 1U web servers, 2U GPU nodes with fans turning behind the grille, 2U storage shelves and blanking plates. Rack numbers run up the left rail and a power strip with one outlet per unit runs beside it.

Every light keeps its own rhythm. Drive LEDs go quiet, then blink a couple of times a second for a few seconds, the way real disk I/O comes in spells. Fewer than half are busy at once, so the rack hums rather than strobes. Each machine's health LED beats twice and rests. Switch ports stay green while their link is up and blink dark with traffic. The locator LED turns blue now and then. Each machine's uplink fibre runs out to the cable channel on the right and climbs out through the roof, and slow pulses of light travel along it both ways.

`activity` sets how busy it all looks. At 0 the drives sit still and only the heartbeats and steady links remain. At 1 more drives blink and the fibres carry two streams each. `alert` blinks one unit amber, about every two seconds: its bezel, name and status LED. Pass `true` to flag the first storage shelf, or a rack position counted from the bottom, like the numbers on the rail.

It draws in `cp437` by default: box drawing for the cabinet and bezels, shades for the drive sleds, `≡` for vents, and doubled lines where a pulse passes. `standard` swaps every glyph for plain ASCII, for fonts and terminals without box drawing. When the box is wider than one rack, neighbouring racks fill the aisle on both sides, dimmer the further out they stand.

## Examples [#examples]

### Incident card [#incident-card]

`alert={5}` flags the storage shelf at U05 on a status card, while `activity={0.85}` keeps the rest of the rack busy.

```tsx title="examples/server-rack-incident.tsx"
import { ServerRack } from "@/components/asciicn/server-rack";

// An on-call status card: the rack flags the shelf that raised the page.
export default function ServerRackIncident() {
  return (
    <div className="w-full max-w-2xl overflow-hidden rounded-lg border bg-background font-mono text-xs">
      <div className="flex items-center justify-between gap-3 border-b px-3 py-2">
        <span className="text-foreground">rack b-07 · u05 nas-01</span>
        <span className="text-[color:var(--ascii-color-orange)]">
          degraded · disk 3 rebuilding
        </span>
      </div>
      <ServerRack
        units={12}
        alert={5}
        activity={0.85}
        cell={11}
        className="relative h-[340px] w-full"
      />
    </div>
  );
}
```

### Plain ASCII on a phosphor [#plain-ascii-on-a-phosphor]

`charset="standard"` and `phosphor="p1"` draw the rack in green ASCII on dark glass, with a CRT finish from `fx`. `intensity={0.5}` keeps the headline on top easy to read.

```tsx title="examples/server-rack-terminal.tsx"
import { ServerRack } from "@/components/asciicn/server-rack";

// Plain ASCII on a green phosphor, behind a status headline.
export default function ServerRackTerminal() {
  return (
    <section className="relative isolate flex size-full flex-col items-start justify-end gap-2 p-8">
      <ServerRack
        charset="standard"
        phosphor="p1"
        intensity={0.5}
        activity={0.4}
        units={24}
        fx={{ bloom: 0.4, scanlines: 0.35, vignette: 0.5 }}
        className="absolute inset-0 -z-10"
      />
      <h3 className="rounded bg-black/70 px-2 py-1 font-mono text-2xl text-[#33ff66]">
        All systems nominal
      </h3>
      <p className="rounded bg-black/70 px-2 py-1 font-mono text-sm text-[#33ff66]/80">
        412 hosts · 99.998% uptime this quarter
      </p>
    </section>
  );
}
```

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `units` | `number` | `18` | Height of the rack in rack units, 1 to 48. Each unit is two rows of glyphs. A rack taller than the box is cropped top and bottom. |
| `activity` | `number` | `0.6` | How busy the machines are, from 0 (idle) to 1. Drives the drive LEDs, port lights and fibre pulses. |
| `alert` | `boolean \| number` | `false` | true blinks the first storage shelf amber. A number flags the unit at that rack position, counted from the bottom. |
| `intensity` | `number` | `1` | How much of the scene shows, from 0 (empty paper) to 1. Lower it under text. |
| `charset` | `"cp437" \| "standard"` | `"cp437"` | cp437 draws box drawing, shades and bullets. standard uses plain ASCII only. |
| `colorMode` | `"truecolor" \| "mono"` | `"truecolor", or "mono" with a phosphor` | truecolor lights LEDs and fibres in colour. mono draws every glyph in the ink, so lit LEDs stand out by glyph and brightness. |
| `phosphor` | `"p1" \| "p3" \| "ibm" \| "blueprint"` | `–` | A CRT ink and glass that replace the ink and paper. |
| `background` | `"paper" \| "transparent"` | `"paper"` | "transparent" draws the glyphs only, over your own surface. |
| `fx` | `PostFx` | `–` | CRT finish: scanlines, bloom, curvature, glitch, flicker and vignette, each 0 to 1. |
| `cell` | `number` | `12` | Height of one glyph cell in CSS pixels. |
| `speed` | `number` | `1` | How fast the lights and pulses move. |
| `animate` | `boolean` | `true` | false holds one still frame. |
| `stillTime` | `number` | `4.2` | The moment drawn when motion is off or reduced, in seconds. |
| `handle` | `RefObject<AsciiHandle \| null>` | `–` | Filled with a handle that reads back the current frame, for export to text, ANSI, SVG or PNG. |
| `className` | `string` | `–` | Size and position. The scene fills this box. |

## Notes [#notes]

* It is decorative and hidden from assistive technology. Put real status text next to it or on top of it, not inside it.
* It ignores the pointer, so moving the mouse over it changes nothing.
* With reduced motion turned on, it draws one still frame at `stillTime`, with some LEDs lit and a few pulses mid-fibre.
* It draws on the CPU at up to 30 fps and pauses when scrolled out of view or when the tab is hidden. Every frame is a few thousand cell writes, so it costs little even full-screen.
* The unit names and readouts are glyphs on a canvas, not text. Copy or export them with `handle`.