“The Ascent” is a single continuous WebGL climb from a dawn cloudscape to the Kármán line, built with no framework, no build step, and only one dependency (Three.js). This page is the reproducible recipe: every technique on the site, in the order you'd rebuild it.
Altior is Latin for higher; the brand line is “We Elevate.”
So the site doesn't illustrate elevation — it performs it. The page is a vertical
journey through real atmospheric layers (Troposphere → Exosphere), the scrollbar is an altimeter,
and every visual system — colour, particles, type, copy — is driven by one number:
progress ∈ [0,1], your altitude. When one scalar drives everything, the piece feels
inevitable rather than decorated. That is the whole trick.
The entire background — dawn gradient, sun, sea of clouds, noctilucent wisps, aurora, star field,
and the Earth's limb at the top — is a single fullscreen ShaderMaterial.
Each phenomenon is a small block gated by an altitude window, all blended by the same
uProgress uniform:
float meso = smoothstep(0.45, 0.62, pr) * (1.0 - smoothstep(0.72, 0.95, pr));
float aur = smoothstep(0.62, 0.80, pr) * (1.0 - smoothstep(0.88, 1.0, pr));
float limb = smoothstep(0.80, 1.00, pr);
fbm(q + fbm(q) * 0.9))
inside a Gaussian vertical band whose centre sinks as you climb, so the cloud sea falls away below you.±0.006 hash dither. Dark gradients band badly on
cheap panels; one line of noise fixes it.
The updraft is a single THREE.Points with three attributes: a seed, a size, and a
y-position. Everything else happens in the vertex shader: particles rise forever via
mod(y + t·speed, H), sway with layered sines, and sit inside a radius envelope that is a
tight cone (a mountain silhouette) at ground level and relaxes into a wide open veil
at altitude. Colour lerps from ember to glacier with the same uProgress.
Additive blending, no depth-write, DPR clamped at 2 — it runs full-frame on integrated graphics.
The orbital ring and its five service nodes are two more Points draw calls sharing the same
additive-glow approach.
Native scrolling is kept (accessibility, momentum, keyboard), but the page you see is a
position: fixed main element translated by a lerped copy of scrollY
(cur += (target − cur) × 0.085). That one exponential gives the whole site its
inertial, “heavy” feel. The same smoothed value drives the WebGL camera's rise, the altimeter,
and the marquee's velocity — so DOM and canvas can never drift out of sync.
Reveal triggers use getBoundingClientRect() in the rAF loop rather than
IntersectionObserver, so they respect the transform.
Display type is Fraunces, a variable serif with optical-size, softness and — genuinely —
a WONK axis that swaps in crooked, hand-drawn alternates. Headlines run at
opsz 144, WONK 1 for maximum character; on hover the principles soften live
(SOFT 0 → 70) — animation inside the letterforms themselves, no extra assets.
Labels are Space Grotesk, letter-spaced like instrument markings, with tabular numerals in the HUD.
Both are self-hosted variable WOFF2s: three files, ~290 KB, the entire type system.
Two temperatures, one journey: ember (dawn, ground, effort) cooling into glacier (space, clarity) as you rise, over an ink base that is never pure black — it leans violet so the ember reads warm against it. Text is bone, not white; at 90 % of white the glow of the shader still reads as light behind the page. Accents stay under ~10 % of any viewport, which is what keeps it feeling engineered instead of decorated.
uServe so the ring
rotates each node to face you while the copy crossfades. Pinning is manual (a
translate inside the inertial scroll), because position:sticky can't survive a
transformed ancestor.data-alt value, displayed with a spring-lerped counter and a needle on a tick rail.
A scrollbar that tells you your altitude.feTurbulence tile stepped through 4
positions at 0.9 s. Kills the “too clean” digital look for ~0 cost.offsetTop after document.fonts.ready, then masked and slid up
with per-line delays. Splitting before fonts load is the classic bug — lines re-wrap and the
masks are wrong.
Everything above could still look like a tech demo. What stops it: one typeface pair, one accent
hue per temperature, hairline borders at 14 % opacity, generous dead space, copy written in the
client's actual constitutional language (“research, analyse, learn, iterate”), and
prefers-reduced-motion honoured throughout — reveals settle instantly and the inertial
scroll steps aside. A flagship is a system with taste, not a pile of effects.
index.html, one CSS file, two JS modules, a vendored
three.module.min.js, three WOFF2s. No bundler.progress means, then make every
system read it.vercel deploy . --prod. The included vercel.json adds
immutable caching for fonts and vendor files.