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.
- Display:
clamp(3.2rem, 11.5vw, 9.6rem), line-height 1.02. -
Labels: 0.72rem Instrument Sans 600, uppercase, letter-spacing
0.34em, gold. - Body: 1rem/1.6 Instrument Sans on
#AAB0CF–#F2EFE6.
§ 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
- Shooting stars every 8–15 s: a glow sprite head plus a two-vertex tail line whose far vertex color is black — under additive blending, black is transparent, so the tail fades for free.
-
Cursor comet trail (fine pointers only): a 2D canvas overlay stamping pre-rendered
radial-gradient sprites with
globalCompositeOperation: "lighter". - Film grain: an inline SVG
feTurbulencetile at 5% opacity, fixed. -
Letter-rise headlines are split into spans at build time in Astro — each
letter gets
transition-delay: i · 26mswithcubic-bezier(0.16, 1, 0.3, 1); an IntersectionObserver adds one class.
Accessibility & fallbacks
-
prefers-reduced-motion: the RAF loop never starts — one static frame is rendered (twinkle frozen, flares at rest), all reveals forced visible, shooting stars and cursor trail off. - No WebGL: the canvas hides; a CSS star layer (130 spans) is generated over the nebula image so content never sits on a void.
- Semantic landmarks, skip link, visible focus rings, ≥ 4.5:1 text contrast.
§ 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
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
- Scaffold Astro 5:
npm create astro@latest(empty template). -
npm i three @fontsource/instrument-serif @fontsource/instrument-sans— no CDNs, no runtime Google Fonts. -
Generate the nebula with the prompt above (GPT Image 2 via Higgsfield CLI), convert
to WebP ≤ 300 KB, place in
public/. - Layer order (all fixed): CSS nebula → transparent WebGL canvas → vignette + grain → scrolling HTML. Content defines scroll height; the camera maps to it.
-
Build the starfield as one shader-driven
Pointsobject; park service stars and constellations at depths computed from measured DOM positions. -
Wire reveals with an IntersectionObserver and letter spans split at build time.
Respect
prefers-reduced-motionbefore starting the loop. 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.