Personal project · 2023 — Present
Portfolio experiments lab
Where interaction ideas get tested before they reach client work
- Next.js
- React Three Fiber
- three.js
- Motion
- Canvas 2D
- TypeScript
The problem
Interaction ideas are cheap to describe and expensive to discover halfway through a client build. I needed somewhere to find out what a technique actually costs — in frame budget, in bundle size, in accessibility debt — before proposing it to anyone paying for it.
The approach
This site is the lab. A React Three Fiber scene with GLTF models, a full-viewport Canvas 2D glitch effect, pointer-tracked glow surfaces and scroll-linked timelines all exist here first, which is how I learned which of them survive contact with a mid-range phone and which do not.
The outcome
A working set of judgements rather than opinions: which effects are worth their cost, which need capability gating, and which need to be switched off entirely when someone has asked for reduced motion. The refresh documented in docs/portfolio-refresh-audit.md is the result of turning that lens on my own code.
Architecture moves
- React Three Fiber scenes loaded as lazy client islands via next/dynamic, kept out of the initial bundle.
- Motion tokens centralised in lib/motion so durations, easings and springs are shared values rather than magic numbers.
- Capability and reduced-motion gating handled at the provider level, so individual components do not each reimplement the check.
- Canvas effects driven by a single requestAnimationFrame loop rather than per-component intervals.
Performance levers
- Heavy 3D and canvas work is dynamically imported, so the first paint does not wait for it.
- Animation restricted to transform and opacity wherever the effect allows.
- Scroll and pointer listeners throttled and passive, and the number of simultaneously animating elements capped on small screens.
- Effects disabled outright on touch and low-power devices instead of merely slowed down.
Engineering impact
- Turned a portfolio into a test bed, which makes the technique choices in client work evidence-based.
- Produced the reusable motion and gating primitives this site now runs on.
- Gave me a documented audit of my own animation defects — including the ones I had shipped.
Challenges conquered
- Wanting a cinematic feel while keeping first paint fast, which is mostly a fight about what is allowed to block rendering.
- Making reduced motion a genuine alternative rather than the same animation played slowly.
- Accepting that some effects I liked were not worth their cost on a mid-range Android.