# Paris

Paris at blue hour, built in 3D and printed in dots: the Seine runs between stone quays and Haussmann blocks to the Eiffel Tower, lit gold from within, its reflection broken by slow ripples.

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

## Installation [#installation]

```bash
npx shadcn@latest add https://asciicn.dev/r/paris.json
```

## Usage [#usage]

```tsx
import { Paris } from "@/components/asciicn/paris";

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

The scene is modelled in 3D and raymarched for every dot, then printed as a halftone. You stand at the water's edge, three metres above the Seine, looking downstream. The river runs away between stone quays, 150 m apart, towards the Eiffel Tower on the right bank about 700 m off. Perspective does the rest: the near blocks are tall at the edges of the frame, the far ones shrink towards the vanishing point, and the tower rises over them at its true height.

The tower follows the real measurements: four legs splayed 125 m apart at the foot, the great arch on each face, the first floor at 58 m, the legs closing to the second floor at 116 m, the long tapering shaft to the top floor at 276 m, then the campanile and the antenna to 330 m. It is lit gold from within. The face turned towards you burns brightest, the face turned to the river sits in deeper amber, and the iron on the far side and inside the legs falls into shadow. The lattice is open, so the sky shows through the gaps, most of all through the far side. Its glow warms the haze around it, and the beacon on top swells slowly about every eleven seconds.

Along both quays stand rows of Haussmann blocks: pale limestone facades with floors of tall windows, some lit warm, iron balconies on the second and fifth floors, grey-blue zinc mansards with dormers, and chimney stacks on the party walls. The right bank faces the last of the afterglow and stands paler; the left bank is in cooler shade. Street lamps line the tops of the quay walls, and the Pont d'Iéna crosses the river at the tower's feet.

The Seine reflects all of it by tracing each view ray back up off the water, bent by slow ripples, so the reflections are darker than the scene and break into long dashes. Haze thickens with distance, so the far blocks fade towards the sky. Every dot's colour then snaps to a palette of 40 colours (night blues, limestone, zinc, the tower's gold and the warm light of windows), and ordered dithering blends the dot sizes, which is what makes it look printed rather than smoothly shaded.

Motion is slow: the ripples drift, the beacon glows, a few windows turn on or off every few minutes, thin clouds drift, stars twinkle faintly, and one bateau-mouche comes up the river towards you, about six minutes from the haze to the edge of the frame. The pointer does nothing.

On wide boxes the camera turns so the tower stands right of centre and the middle stays calm sky for a headline. On tall boxes it turns to put the tower in the middle, with the river below.

It draws in `dots` by default on square 7px cells, about 200 across a 1440px screen. `square={false}` returns to text cells, twice as tall as wide. Other ramp charsets read the same tones as typed glyphs. `braille` and `quadrants` light a dot only above half tone, so they keep the tower, the windows and the lamps. In `truecolor`, the default, the scene paints its own night blue paper in both themes. `mono` with a `phosphor` and `duotone` with a `ramp` read the same scene by tone alone.

`intensity` dims the colours in step and shrinks the dots more gently, so the shapes keep their place behind text.

## Examples [#examples]

### Hero [#hero]

`intensity={0.85}` quiets the scene a little behind a centred headline and two buttons. The tower stands right of the text on wide screens, and the sky behind the text stays calm.

```tsx title="examples/paris-hero.tsx"
import { Paris } from "@/components/asciicn/paris";

export default function ParisHero() {
  return (
    <section className="relative isolate flex size-full min-h-[420px] flex-col items-center justify-center gap-5 px-6 text-center text-white">
      <Paris intensity={0.85} className="absolute inset-0 -z-10" />
      <h3 className="max-w-xl text-3xl font-medium tracking-[-0.03em] text-balance sm:text-5xl">
        Ship it before the lights come on
      </h3>
      <p className="max-w-md text-sm text-pretty text-white/75 sm:text-base">
        A launch week in Paris, with the tower lit gold beside the headline.
      </p>
      <div className="flex flex-wrap items-center justify-center gap-3">
        <a
          href="#get-started"
          className="rounded-full bg-[#fcb442] px-5 py-2 text-sm font-medium text-[#1a1206]"
        >
          Get started
        </a>
        <a
          href="#docs"
          className="rounded-full border border-white/25 bg-white/5 px-5 py-2 text-sm font-medium text-white backdrop-blur-sm"
        >
          Read the docs
        </a>
      </div>
    </section>
  );
}
```

### Finer dots [#finer-dots]

`cell={5}` packs more dots into a small card, so the lattice of the tower holds its detail. `boat={false}` leaves the river still.

```tsx title="examples/paris-fine.tsx"
import { Paris } from "@/components/asciicn/paris";

// A 5px cell packs more dots into a small card, so the tower keeps its
// lattice; the river stays still without the boat.
export default function ParisFine() {
  return (
    <div className="relative isolate h-96 w-full max-w-2xl overflow-hidden rounded-xl">
      <Paris cell={5} boat={false} className="absolute inset-0" />
    </div>
  );
}
```

### On a phone [#on-a-phone]

In a tall box the camera turns so the tower stands in the middle of the frame, with the river and its reflection below.

```tsx title="examples/paris-portrait.tsx"
import { Paris } from "@/components/asciicn/paris";

// A tall card, the shape of a phone screen: the tower stands in the middle
// with the river below it.
export default function ParisPortrait() {
  return (
    <div className="relative isolate h-[560px] w-[264px] overflow-hidden rounded-[2rem] border border-white/10">
      <Paris className="absolute inset-0" />
    </div>
  );
}
```

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `intensity` | `number` | `1` | How strongly the city draws, from 0 to 1. Lower it to keep text on top readable. |
| `beacon` | `boolean` | `true` | The slow glow of the beacon at the top of the tower. |
| `boat` | `boolean` | `true` | The bateau-mouche coming up the river. |
| `paper` | `AsciiColor` | `–` | The surface behind the glyphs. Without it, truecolor, ansi16 and duotone sit on a deep night blue; 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 blue hour. |
| `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. |
| `edgeThreshold` | `number` | `0.22` | Edge charset: how strong a change in tone must be to draw - / \| or \. |
| `dither` | `"none" \| "bayer2" \| "bayer4" \| "bayer8" \| "blue-noise"` | `"bayer4"` | Ordered dithering between neighbouring glyph levels. Ramp charsets default to bayer4; braille and quadrants to none. |
| `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` | Cells as wide as they are tall, so the dots lie in an even lattice. false uses text cells, twice as tall as wide. Braille and quadrants default to false. |
| `speed` | `number` | `1` | How fast the ripples, the clouds, the lights and the boat move. |
| `animate` | `boolean` | `true` | false stops the motion: a still frame if it starts off, the current frame if it was moving. |
| `fps` | `number` | `24` | Frame rate cap. |
| `stillTime` | `number` | `300` | The moment drawn when motion is off or reduced, in seconds. At 300 the boat is about 300 m off, coming towards you. |
| `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 flat blue-hour gradient.
* The whole scene is raymarched on the GPU every frame, at 24 frames a second by default. Rays that rise above the roofs skip the march, so the sky is cheap; water samples trace a second, reflected ray, so the river costs about twice as much as the buildings. It is the heaviest of the city backgrounds: on slow GPUs lower `fps` or raise `cell`. `braille` samples eight times per cell and `quadrants` four. See [Performance](/docs/engine/performance).