VERRE
Build notes — one of 25 sites

White until refracted.

Concept

The page's single job

VERRE is a fictional two-person glass studio on Refshaleøen, Copenhagen, selling hand-blown one-offs to people who buy few, careful things. The page has one job: make you believe that colour here exists only inside glass. So the site is near-white everywhere — and every trace of chroma you meet arrives through a rendered or simulated piece of glass.

Palette

Three inks and a hidden field

Gallery white
#FAFAF8 — the wall every piece is shown against.
Fog
#E8EAEA — shadowless depth; panels, hairlines, the backdrop gradient.
Ink
#1A1C1E — warm-neutral near-black; all text, one weight of authority.
The field
Cyan → violet → rose → amber. Never applied to UI — it exists only behind or inside glass.

The discipline is the point: if the prism hues ever touched a button or a heading, the hero's claim ("colour lives only in the glass") would be a slogan instead of a fact.

Typography

Fraunces, blown thin

Display is Fraunces at optical size 144 and weight 300 — at that end of its axes the hairline contrast turns glassy, and the italic swashes bend like hot rods of crystal. One italicised phrase per heading is the typographic bravery budget; the giant outlined VERRE in the footer spends the rest of it. Inter carries body and the tracked small-cap labels, set at a deliberate scale (11 / 13 / 17 px) so the serif display always wins the room.

Techniques

One plane, two faces

The signature element is a three.js torus knot in MeshPhysicalMaterial with transmission: 1, lit by a PMREM-filtered RoomEnvironment. Behind it sits a single shader plane with a split personality. three.js renders transmissive scenes in two passes: first the opaque scene is drawn into an internal buffer that the glass then samples for refraction, then the scene is drawn to screen. Inside the plane's onBeforeRender, renderer.getRenderTarget() is non-null only during that internal pass — so a uPass uniform flips the fragment shader between a quiet white-to-fog gradient (what you see) and a vivid drifting colour field (what only the glass sees). Colour therefore reaches the eye exclusively through refraction. Pressing the hero briefly lerps the two faces together, letting you glimpse the bare field.

Iteration log

Three passes with a fine-tooth comb

Pass 1 — Craft

  • The hero canvas met the page with a visible seam: the backdrop plane was being ACES-tonemapped while the page was not. Removed tone mapping from the plane's shader and authored its colours in exact linear equivalents of #FAFAF8/#E8EAEA, with the gradient easing back to page-white in the bottom 14%. The seam is gone.
  • The knot sat on a fixed x-offset and collided with the headline at middling aspect ratios. Its position and scale are now derived from the camera frustum per resize.
  • Strengthened the hidden field's saturation (the first build refracted skim milk) and lowered glass roughness 0.06 → 0.03 for a harder, wetter surface.
  • Copy tightened: every price in DKK with tabular numerals, one metadata line per piece, banned filler adjectives.

Pass 2 — Depth

  • Added press-to-peek: pointerdown on the hero drives a smoothstep envelope on a uReveal uniform, crossfading the quiet face into the bare colour field for ~2.5 seconds — the site briefly confesses how the trick works.
  • Gave the knot a 1.4% breathing scale and pointer-coupled tilt so it reads blown, not lathed.
  • Second-read details: the catalogue vessels keep their colour secret until hover, and the spectrum-lens divider rewards a wandering cursor between Process and Studio.
  • Retimed the intro: line masks on power4.out at 1.5s with 0.14s stagger, supporting copy trailing by half a second.

Pass 3 — Hardening

  • Fraunces' long italic descenders were clipped by the line-reveal masks — fragments of the g-tails floated under the headline. Masks now carry .32em of forgiveness.
  • On portrait screens the knot filled the viewport behind the text; the true extent of a (2,3) torus knot is ~1.95× its nominal radius, not 1.45×. The narrow layout now measures the copy block's offset and fits the knot into the space above it. Verified at 375, 768, 1440.
  • Chanel rule: removed the catalogue cards' hover lift and shadow — the colour reveal is the interaction; the jump was noise.
  • Reduced motion: CSS media query kills keyframes and transitions; JS renders one static frame, skips GSAP, and never starts the rAF loop. The loop also pauses on document.hidden and when the hero scrolls out of view; DPR is capped at 2; WebGL failure falls back to a CSS-gradient glass ring.