How "Nightwatch" was made

An expedition journal read beneath a live aurora. One idea, executed deeply: the northern lights overhead are drawn frame by frame on a canvas from a small amount of light physics — not a video, not an image — and the writing underneath describes the real thing accurately.

What it demonstrates

That an atmospheric, expensive-looking hero can be a few hundred lines of honest canvas code, and that a "moody" site can still teach something true. The aurora is generative, so it never loops or repeats; the copy carries real science — emission wavelengths, altitudes, substorms, the Kp scale — rather than vibes.

The techniques, honestly named

Reduced-motion visitors get a single still aurora frame and no parallax; the loop pauses when the tab is hidden; devicePixelRatio is capped at 2.

Recreate it

Give this prompt to your AI coding tool and iterate from what it returns.

Recreation prompt
Build a single self-contained index.html: a winter expedition journal set at 69.6 degrees N in Tromso, Norway, read beneath a live canvas aurora. A fictional narrator; every physical mechanism described is real.

Art direction: near-black night background (#04060c with a faint vertical gradient toward #060a14), soft off-white ink (#e3e9f2), a muted slate for secondary text (#9fabbd), one aurora green accent (#8fe0b0). An editorial serif (Spectral, weights 300-500 plus a 300 italic) for the reading voice over a clean sans (Inter) for labels and UI. Journal entries in translucent dark panels (rgba(6,10,18,.78)) with a hairline border, max-width about 37rem, centered.

Hero technique, executed honestly: a live aurora drawn on a canvas, not a video or image.
- Three curtain layers. For each, build a 1x128 vertical gradient strip (transparent at top, brightening through green to a bright lower hem, transparent again) and tile it across the canvas in narrow columns; the lower edge and ray length of each column follow layered sine waves so the curtain folds and breathes.
- Composite the curtains with globalCompositeOperation = 'lighter' so overlapping light adds the way real emission does.
- Render the aurora on a low-resolution canvas (about one-third of viewport pixels) and let CSS filter: blur(3px) upscale and soften it.
- Drift the base hue slowly (green, wandering toward teal and yellow-green over minutes, not seconds).
- A separate static star canvas behind it (regenerated only on resize), and two SVG mountain ridges pinned to the bottom with gentle scroll parallax.

Content: a five-entry journal. Weave in accurate science: green from atomic oxygen at 557.7 nm brightest ~100-250 km; red from oxygen at 630 nm above ~250 km where the ~2-minute metastable transition can complete; pink-violet nitrogen at the lower hem below ~100 km; substorms driven by magnetotail reconnection releasing energy in minutes; the planetary K-index (Kp 0-9, three-hour blocks) and the auroral oval centred on the geomagnetic pole; coronal holes and fast solar wind versus coronal mass ejections; the Sun's ~11-year cycle. State on the page that the narrator is invented and the physics is real.

Quality bar: semantic HTML with a skip link; visible focus states; WCAG-AA contrast; prefers-reduced-motion renders a single aurora frame and disables parallax; requestAnimationFrame only, paused when the tab is hidden; devicePixelRatio capped at 2; no horizontal scroll at any width; fully usable and beautiful at 390 px.