Atelier Celadon ← Back to the studio
Guide · How this site was made

One vase, one glaze, one long scroll into the kiln.

Concept & art direction

Atelier Celadon is a fictional Copenhagen porcelain studio that has glazed in a single color for thirty years, and the site behaves the way the studio works: one object, examined slowly. The layout follows the life of a single pot — the object, its making, its firing, its collection — and the page’s only job is to get a collector of quiet objects onto the kiln-opening list. Museum-label restraint everywhere; all the drama saved for the kiln.

Palette

The whole celadon family, mist to deep jade, on porcelain white with green-black ink. Kiln-ember orange appears exactly once — inside the kiln, where it belongs.

Type pairing

Alegreya — a scholarly serif that reads like a book, not a brand.

Alegreya SC — true small capitals for museum labels

Alegreya Sans — the calm humanist voice for specs, captions, and 1305° of kiln data.

All three are one superfamily by Juan Pablo del Peral, drawn for long-form literature — which is exactly the register of a studio that writes two letters a year. Alegreya SC is a genuine small-caps cut (not faked with font-variant), so the labels have real small-cap proportions, like type on a museum wall.

Technique — the real 3D vase

The hero object is an actual GLB mesh, not a render. 3D: Higgsfield image-to-3D from a GPT Image 2 still. It loads into three.js, gets normalised to a known size, and lives on a single fixed, transparent canvas behind the whole page:

const box = new THREE.Box3().setFromObject(model);
const s = 2 / box.getSize(new THREE.Vector3()).y;   // height → 2 units
model.scale.setScalar(s);
model.position.sub(box.getCenter(new THREE.Vector3()).multiplyScalar(s));

Lighting is a three-point studio setup plus a PMREM RoomEnvironment so the glaze catches light like glass. Drag-to-turn is ten lines of pointer math with inertia — no OrbitControls, so the page never fights the scroll.

Technique — scroll-firing the kiln

The firing section is a 420vh track with a sticky 100vh stage. Every frame, scroll progress is read from getBoundingClientRect() and mapped to a real cone-10 reduction schedule: the vase descends onto the kiln shelf, the temperature ticks from 20° to 1305°, the key light lerps from studio-cool to ember, and Orton cones 8, 9 and 10 bend in the spy hole at their true temperatures (1263°, 1280°, 1305°).

const fireT = clamp(-rect.top / (rect.height - vh), 0, 1);
const temp  = 20 + smooth((fireT - 0.26) / 0.66) * 1285;
keyLight.color.copy(cool).lerp(ember, heat);
cone8.classList.toggle('bent', temp >= 1263);

Technique — crackle that draws itself

The crackle behind the museum label is generated at load: random walks seeded from the edges, occasionally branching, rendered as SVG paths. Each path animates stroke-dashoffset from its own length to zero when the label scrolls into view — the glaze cracking in real time.

const L = path.getTotalLength();
path.style.strokeDasharray  = L;
path.style.strokeDashoffset = L;          // invisible
// on intersection: strokeDashoffset → 0  // draws itself

Section breaks use the same logic in reverse: a “glaze dip” SVG wave with a tide-line stroke wipes across via clip-path when it enters the viewport. With prefers-reduced-motion, everything ships pre-drawn and the kiln stage rests in its final, fired state.

The three passes

  1. Pass 1 · CorrectnessFound the vase rendering behind the hero’s opaque background — restructured the z-stack so section backgrounds paint below the fixed canvas while their content rises above it. Cooled the tone-mapping and tinted the material so the glaze reads celadon instead of overexposed white, seated the vase exactly on the kiln shelf, and lifted the mobile vase clear of the headline.
  2. Pass 2 · ElevateMade the ware itself glow ember past 1000° (emissive ramp), fixed the Orton cones so they visibly bow in the spy hole (transform-box: fill-box), flipped the header light over the dark glaze section, faded the drag hint after the first drag, and let hovering the museum label grow new crackle lines — the negotiation continuing.
  3. Pass 3 · TasteChanel rule: removed a decorative dot from the spec table that encoded nothing. Added the orchestrated page-load rise for the hero copy, then verified reduced motion (kiln rests fired, nothing auto-plays), 390px layouts, keyboard focus, and zero console errors.

Do this yourself

  1. Pick one object, not a subject. A single vase gives you a narrative spine (made → fired → collected) that no grid of features can match.
  2. Get a real 3D asset. Generate a product still (GPT Image 2), lift it to a GLB with an image-to-3D model, and ask Claude for a three.js loader that normalises any mesh to a known size.
  3. Put the canvas behind the page. One fixed, transparent WebGL canvas; opaque sections scroll over it, transparent ones become windows. Ask for scroll choreography driven by getBoundingClientRect(), not scroll listeners with magic numbers.
  4. Make the data true. Real cone temperatures, real iron percentages, real firing stages. Truth reads as craft; filler reads as AI.
  5. Spend your accent once. Choose one color the palette is not allowed to touch except at the climax.
  6. Write like a curator. Short declaratives, specific numbers, no adjectives you couldn’t defend at an auction.
  7. Screenshot, critique, repeat — three times. Look at the renders like an art director, not a developer: spacing, contrast, what to remove.
  8. Test the quiet paths. Reduced motion, keyboard focus, 375px. A calm site that breaks quietly isn’t calm.

← Back to Atelier Celadon