Flight Log · Star Chart № 01

How NOCTURNE was built

NOCTURNE is one of ten design directions built for Nomadic Owls — the cinematic WebGL flagship. This log records the full chart: concept, design system, and the machinery of the flight, precise enough to rebuild from scratch.

§ 01

The Concept

The owl is a night navigator. NOCTURNE takes Nomadic Owls' line — "We send beautiful things to the Internet" — literally: the site is a single continuous night flight through a star field. Scrolling is flying. The journey has chapters: departure (the tagline rises out of darkness), the idea ("We have ideas / and send them to the Internet"), navigation (six services as six named stars — each one flares as the camera approaches), constellations (three projects drawn as connected star lines), and the landing (a horizon glow and a beacon: the contact CTA).

The typography is treated as a poster in motion — enormous Instrument Serif display lines rise letter-by-letter with expo easing over the WebGL sky, held together by small-caps gold labels with generous tracking.

§ 02

Design System

Palette

Gold is spent like fuel: labels, star flares, one beacon. Everything else stays in the blue-to-ink range so the gold moments read as events.

Type

Obsessively Curious.

Instrument Serif 400 (display; italic for celestial poetry moments) · Instrument Sans 400–600 (body, labels) · both self-hosted via @fontsource.

§ 03

Tech & Motion

Astro 5 + vanilla Three.js (no framework runtime). A fixed transparent canvas sits between a CSS nebula layer and the HTML content. All motion lives in src/scripts/nocturne.js.

Starfield shader

One THREE.Points draw call: 6,000 field stars plus a 350-star near-axis dust band on desktop (2,200 + 150 on mobile) — the dust hugs the flight path and streams past the camera as the speed cue. Each vertex carries aSize, aPhase, and aTemp attributes. The vertex shader does perspective size attenuation (150 / distance, clamped), a per-star twinkle (sin(uTime · (0.7 + phase · 2.4))), and near/far distance fades so stars never pop at the camera plane. The fragment shader draws a soft core plus a gaussian halo, and mixes color temperature from blue-white vec3(0.66, 0.74, 1.0) to gold vec3(1.0, 0.78, 0.42) — about a fifth of the field burns warm. Additive blending, no depth write.

Scroll-camera rig

z(scroll)  = Z_START − (scroll / maxScroll) · FLIGHT_DEPTH   // 14 → −286
smoothS   += (scrollY − smoothS) · (1 − 0.0028^dt)           // heavy lerp
camera.x   = sin(p·π·1.7)·3.2      // gentle lateral sway
camera.rz  = sin(p·π·2.6)·0.022    // banking roll

The page's real scroll height drives everything: each service panel's document-space center is measured, converted through z(scroll), and its star is parked 34 units ahead of where the camera will be when that panel is centered — so DOM and WebGL can never drift apart. Star flare intensity is simply proximity of the panel to the viewport center, smoothstepped and lerped.

Constellation lines

Each project is a small 2D point set (an aggregator hub-and-spokes, a ring, a conical hat) built as LineSegments with segments ordered like a pen stroke. Reveal = geometry.setDrawRange(0, drawnSegs · 2) driven by scroll progress through the panel, on a LineDashedMaterial whose dashOffset drifts slowly for shimmer. Constellation vertices reuse the star shader so they twinkle with the field.

Micro-events & texture

Accessibility & fallbacks

§ 04

AI Assets

The atmosphere layer is a single AI-generated image — nocturne-nebula — made with GPT Image 2 via the Higgsfield CLI (quality high, 2K, aspect ratio 16:9), then resized to 2048 px and compressed to a 107 KB WebP. The exact prompt, verbatim:

Vast deep-space nebula seen from within, extremely dark indigo and near-black sky, faint wisps of deep blue and violet gas, sparse tiny golden stars, one soft warm golden glow near the horizon line, cinematic, photorealistic astrophotography, very dark and subtle, no text, no letters, no watermark, no planets
The generated NOCTURNE nebula: a very dark indigo sky with faint blue and violet gas, sparse golden stars, and a soft warm golden glow near the horizon.

In the page it is blended, not pasted: edges are deepened with radial and linear gradients toward #070714, and the WebGL starfield moves over it, so the image reads as atmospheric depth rather than a background photo.

§ 05

How to Reproduce

  1. Scaffold Astro 5: npm create astro@latest (empty template).
  2. npm i three @fontsource/instrument-serif @fontsource/instrument-sans — no CDNs, no runtime Google Fonts.
  3. Generate the nebula with the prompt above (GPT Image 2 via Higgsfield CLI), convert to WebP ≤ 300 KB, place in public/.
  4. Layer order (all fixed): CSS nebula → transparent WebGL canvas → vignette + grain → scrolling HTML. Content defines scroll height; the camera maps to it.
  5. Build the starfield as one shader-driven Points object; park service stars and constellations at depths computed from measured DOM positions.
  6. Wire reveals with an IntersectionObserver and letter spans split at build time. Respect prefers-reduced-motion before starting the loop.
  7. npm run build && npm run preview — audit with Playwright.

Designed & built by Claude (Anthropic) for Nomadic Owls. One of ten directions — see the other nine at nomadic-ten.pages.dev.