Skip to content
Rahul Nainala
LiveOn my own · 202612 / 15

The Instrument

My portfolio in 3D: a scroll down through a stylised dilution refrigerator, one cold stage for each layer of how I build.

The Instrument's second stage: a copper plate with cables and coax lines rendered in WebGL, beside copy about the services layer and a card listing the plate's material and temperature
Stage 02: the services layer, beside the hardware it borrows its shape from.
scroll-linked stages, from interfaces to personal projects
10
scales, 100 mm and 1 mm per unit, cut between
2
quality tiers, stepped down at runtime
3
Playwright smoke tests in CI
5

Overview

The Instrument is a spatial take on this portfolio. You scroll down through a stylised dilution refrigerator, the gold chandelier that cools superconducting quantum computers, and each stage holds one layer of how I build: interfaces, services, GPU servers, edge devices, digital twins and personal projects. It's a static Next.js export rendered live with React Three Fiber and custom GLSL. The hardware is procedural, and every physical number on it is a typical published value with its source on a sources page.

Problem → built → result

Problem
A 3D portfolio that still works as a page, for screen readers, slow phones and weak GPUs.
Built
Ten scroll-linked stages in React Three Fiber, a camera rig across two scales, posters from the scene.
Result
10 stages · a static path for no WebGL and reduced motion

Features

  • All copy is DOM; the canvas is aria-hidden and every stage has a screen-reader description of what the scene shows
  • “Skip descent” is the first focusable element, and “Read as a page” removes the scene entirely
  • Three quality tiers (pixel ratio, particle count, materials, post-processing), stepped down at runtime by a performance monitor
  • Fully procedural hardware, no model files; shaders compile before the canvas fades in over the poster
  • A sources page generated from the same data as the scene, so every number on screen has a citation

Decisions

  1. 1

    Two spaces, one camera.

    The large scene works at 1 unit = 100 mm and the chip at 1 unit = 1 mm. The camera cuts between them behind a short black veil, so no frustum spans metres and micrometres and no logarithmic depth buffer is needed.

  2. 2

    Scroll-linked, not scroll-jacked.

    Native scroll, smoothed by Lenis, is the only input; nothing intercepts the wheel or snaps. The camera damps its position on the curve, not the scroll, and J / K and 0–9 jump between stages.

  3. 3

    React never renders per frame.

    Per-frame values are mutated in place and read in the render loop; UI state lives in a tiny useSyncExternalStore store, so scrolling never triggers a React render.

  4. 4

    Posters first.

    A script renders one still per stage from the real scene. The stills are the LCP image, and the whole visual on the static path: no WebGL2, Save-Data, a blocklisted GPU or reduced motion.

Why it's shaped this way

A 3D site is only as good as its worst device. The scene is an enhancement over real HTML: every stage reads as text, and anything that can't run WebGL well gets the posters instead of a stutter.