← All work

Interactive 3D · WebGL · 2026

Lakeside

A portfolio you can walk into.

A mountain lake built in Three.js: Gerstner waves, a spruce forest in a shared wind field, a lake house with a working door and a physics-driven fire, and a day/night switch. Every section is a place you travel to.

  • UI/UX
  • Frontend
  • QA

Visit the live site ↗

Role
Self-initiated · design + Three.js
Year
2026
Disciplines
UI/UX · Frontend · QA
lakeside.app

01 The problem

Portfolio sites all scroll the same way. I wanted navigation that feels like moving through a place, without losing the basics: readable text, fast loading and a frame rate that holds on a laptop.

02 Key decisions

01

One world, two moods

Day is a soft teal sky with cumulus and blue-teal haze; night swaps in stars, a textured moon, lantern light and fireflies. The panels change palette with the sky.

02

Night is lit by the scene itself

Lanterns, the cabin window and the fire are the light sources, and the lake reflects them. Nothing is painted on.

03

About, out on the dock

About flies you to the end of the dock. The panel is deep lake-teal glass with a copper accent, dark enough to read over the bright water and sky.

04

Contact lives inside the house

Clicking Contact walks you across the porch, swings the door open and steps into a room lit by a particle fire with buoyancy and cooling. The card appears by the fire.

05

Cards that belong to the forest

Daylight project cards use a misty-forest palette (pine to moss, cream text, one gold accent) so they read clearly without fighting the scene.

03 Built in code

world/waves.js
 1// one wave field drives the GPU surface and the boat's buoyancy
 2function waterHeight(x, z, t) {
 3  const g = waveGust() * shoreDamp(x, z)
 4  let y = 0
 5  for (const [dx, dz, L, A] of WAVES) {
 6    const k = (Math.PI * 2) / L, c = Math.sqrt(9.8 / k)   // deep-water dispersion
 7    y += A * g * Math.sin(k * (dx * x + dz * z - c * t))
 8  }
 9  return y
10}

04 Then I tried to break it

CaseDesktopPhoneTabletLandscape
Holds ~60 fps✓✓✓✓
Text readable over the scene✓✓✓✓
Day and night switch✓✓✓✓
Walk in and out of the house✓✓✓✓
  • Wider field of view on narrow screens
  • Finger-sized targets and safe areas on touch
  • Resolution steps down if the frame rate dips
  • Reflections, shadows and the fire only update when needed

✦ By the numbers

60 fpson laptop, phone and tablet, while 60,000 blades of grass move in the wind
1.6 sfrom tapping Contact to standing by the fire, door swinging open on the way
135 KBof hand-written code builds the whole world. No 3D models, no photos.
One windmoves the grass, trees, waves, chimney smoke and the sound, gust by gust

Measured on the live build in Chrome, on laptop, phone and tablet sizes.

→ What I’d do next

Seasons: snow on the peaks and a frozen lake in winter, autumn colour in the forest.

Next case studyKovaMaking a six-figure payroll feel boring.
→