# Redwood light

A redwood forest in early morning: giant trunks fading into blue-green haze, golden light shafts slanting onto a fern floor, and slow motes drifting in the light.

> 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/redwood-light.json](https://asciicn.dev/r/redwood-light.json), under `files[].content`.

## Installation [#installation]

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

## Usage [#usage]

```tsx
import { RedwoodLight } from "@/components/asciicn/redwood-light";

export function Hero() {
  return (
    <section className="relative isolate min-h-[480px]">
      <RedwoodLight intensity={0.6} className="absolute inset-0 -z-10" />
      <h1>Your headline</h1>
    </section>
  );
}
```

The view is from the forest floor, looking up. Two huge trunks frame the view, dark red-brown and furrowed, with a warm rim of light on the side that faces the sun. Three medium trunks stand a little behind them, then three rows of thinner trunks recede into the haze, each row paler and cooler than the one in front: a few broad trunks and many thin ones. Every trunk leans towards one point high above the middle of the box, and each also has its own lean, bow and taper, with bark breaking both edges, so the forest reads as seen from below and never as a row of strips. Sprays of far foliage and drifting mist hide parts of the distant trunks.

Three layers of canopy overlap overhead, far to near: clumped masses with ragged, leafy edges, the nearest hanging low in sprays at the sides.

The sun shines through the canopy, upper right, as a small soft halo, and the leaves around it glow gold where it backlights them. Four soft-edged shafts of light fall from it, nearly straight down, broken into dapples by the leaves in their way, and the air around them is a soft green-gold. Fern clumps get smaller and hazier towards the far edge of the floor, and a row of fronds crosses the bottom of the box.

The motion is slow. Dust and pollen drift through the shafts and catch the light, each mote fading in and out. The shafts brighten and dim a little, and a thin mist drifts between the far trunks. Nothing reacts to the pointer.

The middle of the box is calm green air between the trunks. The light stays upper right and the shafts fade where they near the middle, so a centred headline sits on quiet ground. On tall boxes the giants narrow, the halo shrinks and the shafts dim, so a phone shows the light above the headline and the trunks beside it.

It draws in `dots` by default on square 7px cells, about 200 columns across a 1440px screen, so the dots sit on an even lattice like a halftone screen. `square={false}` goes back to the font's narrower cells. Dot size carries the light and `truecolor` gives every dot its own colour, while the shade falls to the smallest dots, close to the paper, or to none. `braille` and `quadrants` draw the same forest in finer dots. In `truecolor`, `ansi16` and `duotone` it paints on its own dark green shade, so it looks the same on the light and dark site themes. `mono` with a `phosphor` and `duotone` with a `ramp` read the scene by tone alone.

`intensity` dims the colours and shrinks the dots together. Around 0.6 the forest falls back behind a headline.

## Examples [#examples]

### Behind a headline [#behind-a-headline]

`intensity={0.6}` keeps the light shafts and the giants but lets a centred headline and two buttons read first.

```tsx title="examples/redwood-light-hero.tsx"
import { RedwoodLight } from "@/components/asciicn/redwood-light";

// Full bleed behind a centred headline and two buttons, dimmed so the copy reads first.
export default function RedwoodLightHero() {
  return (
    <section className="relative isolate flex size-full min-h-[520px] flex-col items-center justify-center gap-4 px-6 text-center">
      <RedwoodLight intensity={0.6} className="absolute inset-0 -z-10" />
      <h3 className="max-w-xl text-4xl font-medium tracking-[-0.03em] text-balance text-white sm:text-5xl">
        Grow something that lasts
      </h3>
      <p className="max-w-sm text-sm text-pretty text-white/80 [text-shadow:0_1px_8px_rgb(0_0_0/0.9)]">
        At 0.6 intensity the forest falls back and the light stays.
      </p>
      <div className="mt-2 flex flex-wrap items-center justify-center gap-3">
        <a
          href="#get-started"
          className="rounded-md bg-[#fcb442] px-4 py-2 text-sm font-medium text-black"
        >
          Get started
        </a>
        <a
          href="#learn-more"
          className="rounded-md border border-white/30 bg-black/30 px-4 py-2 text-sm font-medium text-white backdrop-blur-sm"
        >
          Learn more
        </a>
      </div>
    </section>
  );
}
```

### Sepia duotone [#sepia-duotone]

`colorMode="duotone"` with `ramp="sodium"` reads the forest by brightness alone, in warm amber like an old print. `mist={false}` leaves the far trunks clear.

```tsx title="examples/redwood-light-sepia.tsx"
import { RedwoodLight } from "@/components/asciicn/redwood-light";

// The same forest read by tone alone, through the sodium ramp: an old photograph.
export default function RedwoodLightSepia() {
  return (
    <div className="relative isolate h-96 w-full max-w-2xl overflow-hidden rounded-xl">
      <RedwoodLight
        colorMode="duotone"
        ramp="sodium"
        mist={false}
        className="absolute inset-0"
      />
    </div>
  );
}
```

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `intensity` | `number` | `1` | How strongly the forest draws, from 0 to 1. Lower it to keep text on top readable. |
| `motes` | `boolean` | `true` | Dust and pollen drifting through the light shafts. |
| `mist` | `boolean` | `true` | The mist drifting between the far trunks. |
| `paper` | `AsciiColor` | `–` | The surface behind the glyphs. Without it, truecolor, ansi16 and duotone sit on a deep green shade; mono and palette use the theme's paper or the phosphor's. |
| `fallback` | `ReactNode` | `a gradient` | Shown without WebGL and until the first frame. |
| `charset` | `CharsetName` | `"dots"` | Which glyphs draw the tones. See Charsets. |
| `chars` | `string` | `–` | A custom ramp from empty to dense, such as " .oO@". Wins over charset. |
| `colorMode` | `"mono" \| "truecolor" \| "ansi16" \| "duotone" \| "palette"` | `"truecolor"` | How glyphs are coloured. truecolor paints the scene's own colours; mono uses one ink or a phosphor; duotone runs tone through a ramp. |
| `phosphor` | `"p1" \| "p3" \| "ibm" \| "blueprint"` | `–` | A CRT ink and glass. Setting one switches the default colour mode to mono. |
| `ramp` | `RampName \| string[]` | `"sodium"` | In duotone mode, the colour ramp from dark to light. The default draws gold on the shade. |
| `ansi` | `"vga" \| "xterm"` | `"vga"` | In ansi16 mode, which 16-colour table. |
| `grade` | `Grade` | `–` | Brightness, contrast, gamma and saturation applied to tones before glyphs are picked. |
| `invert` | `boolean` | `false` | Dense glyphs for dark tones instead of bright ones. |
| `threshold` | `number` | `0.5` | Braille and quadrants: the tone that lights a dot. |
| `dither` | `"none" \| "bayer2" \| "bayer4" \| "bayer8" \| "blue-noise"` | `"none"` | Ordered dithering between neighbouring glyph levels. |
| `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` | `7` | Height of one glyph cell in CSS pixels. |
| `square` | `boolean` | `true` | Square cells, as wide as they are tall, so the dots form an even lattice. false uses the font's narrower cells. |
| `speed` | `number` | `1` | How fast the motes, the shafts and the mist move. |
| `animate` | `boolean` | `true` | false stops the motion: a still frame if it starts off, the current frame if it was moving. |
| `fps` | `number` | `30` | Frame rate cap. |
| `stillTime` | `number` | `12` | 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 background fills this box. |

## Notes [#notes]

* It is decorative and hidden from assistive technology. Put real text on top of it, not inside it.
* It ignores the pointer: no parallax and no hover effect.
* With reduced motion turned on, it draws one still frame at `stillTime` and stops.
* It pauses when scrolled out of view or when the tab is hidden, and releases its WebGL context when far offscreen. Without WebGL it shows a soft gradient of the scene.
* The whole forest is one shader pass on the GPU, one sample per cell in `dots`. `braille` samples eight times per cell and `quadrants` four. See [Performance](/docs/engine/performance).