The site is a project too.
The system behind what you just scrolled through. Most of the examples are live.
Colour
The interface is neutral black, grey and white, with no tint. The warm colours below are only ever used as light: in the background, and glowing from beneath a few objects.
Click a swatch to copy its variable.
Type
Hanken Grotesk carries nearly everything, in four sizes. Monospace is kept for code and the occasional figure.
text-displayProblem to product
text-h2Selected outcomes
text-h3Shipped to production
text-leadEli Mora, product and design engineer.
Components
A small set, reused everywhere. These are the real ones, with their real hover, focus and press states.
A band of white light travels a button's edge on hover and focus, and pressing scales it to 97%. There is no accent colour: emphasis comes from white on black.
Motion
Movement here reports something: a state changed, or one thing caused another. If it reports nothing, it was cut.
ease-out-expoEntrances, reveals, anything arrivingease-in-out-softTravel between two resting pointsease-snapHover and press feedback
900ms each, slowed for comparison
- Transform and opacity only
- Nothing animates layout. Hover, focus, press and page entry are plain CSS.
- Reduced motion
- Decorative travel is removed and the background renders a single still frame. Every state change still happens, instantly.
The background
One motif for the whole site: molten light under a tilted wall of brushed-titanium blocks. On the home page the logo sits on a pane of smoked glass in the wall, and the heat comes from it. Move your pointer anywhere: it works as a torch.
Off. Scroll away from a lit screen and the wall fades to black. Your pointer still finds it.
Look behind this page while you switch.
- One shader, real metal
- Each plate is a distance field with a brushed grain, a bevel lit from the upper left and a soft sheen. Seams show the light directly, and shafts leave them toward you.
- Lit at both ends
- Bright on the opening and closing screens, with pulses running out from the logo and down into the footer. Everywhere in between it is dark and nothing is drawn, until your pointer passes over it.
- No 3D library
- About 4 KB of shader code at 30 frames a second, capped in resolution on very large screens. A 3D engine would add more than 150 KB.
- Graceful without it
- If WebGL is unavailable the wall keeps a static glow. No content depends on the canvas.
Decisions
The choices that shaped the build, and the reason for each.
- Static by default
- Every route is prerendered. Components are server components unless they need to respond to input.
- Content is data
- Case studies are typed objects and writing is MDX. One schema feeds the cards, the quick read and the deep dive.
- Real elements
- Every control is a button or a link, everything works from the keyboard, and nothing is hidden behind hover.
- Tested for access
- Automated accessibility scans run against every route, alongside keyboard-flow tests, on desktop and mobile.
- Small on purpose
- Next.js, TypeScript, Tailwind and one animation library. No UI kit, no icon font, no database.
- Built with AI, owned by a person
- An AI coding agent wrote much of the implementation from a written brief and was corrected from rendered screenshots. Direction and the quality bar were set by me.