The client — a UI/UX designer — had a portfolio that existed only as a Figma
file. Design work is judged on craft, so a template or a static export would
have actively undersold him: prospective clients would see a designer whose own
site felt cheaper than the work inside it.
The site had to prove competence in the first five seconds, on any device, and
every animation had to be evidence of care rather than decoration.
- 01Figma-to-code at 1:1 fidelity — spacing, type and color read straight from the design file
- 02Scroll-linked SVG arrows that draw themselves along the process timeline
- 03Sticky-scroll services section where cards deal themselves into place
- 043D tilt cards that lean toward the pointer
- 05Word-by-word headline reveals with staggered spring entrances
- 06Custom cursor with hover-state morphing
- 07Seamless infinite marquees for client logos, testimonials and the studio gallery
- 08Lenis smooth scroll driven off Motion's frame loop, not a competing RAF
- 09Responsive from 320px to 1920px with zero horizontal overflow
- 10Calendly booking and mailto contact wired into every CTA
Pixel-perfect from a moving target. The designer kept editing the Figma file
mid-build. I settled into a repeatable sync loop: locate the changed node in the
metadata dump, prove its placement by comparing sibling y-offsets, export that
node, byte-compare against the shipped asset to isolate what actually changed,
then implement and screenshot-verify.
Figma's numbers do not always survive contact with a browser. The hero headline
is specified as a 1179px-wide text node two lines tall — but 66px Outfit renders
that sentence in three lines at that width. The design file's node height was
stale. Building it literally pinned the card to a fixed height that its own
content overflowed, pushing the headline out through the top edge above 1728px.
Fixed by making the Figma height a floor rather than a cap and deriving the
padding from the frame's own flex-end math.
Smooth scroll owns the scroll position. Lenis silently ignores window.scrollTo
on touch contexts, which broke automated screenshotting and left a fixed navbar
stuck in its hidden state. Resolved by driving the test harness with real wheel
events and polling until the position settles.
Verifying responsiveness instead of assuming it. A scripted overflow probe
across every breakpoint caught fixed widths and hard min-width floors in the
hero, services and contact sections that only broke at 320px and in the narrow
1024–1280px band.
Next.js 16 App Router with Turbopack, React 19 and TypeScript throughout. Two
routes — Home and About — composed from 15 section components, each a pure
presentational unit fed by typed content modules in src/lib, so copy and case
studies change without touching layout code.
Tailwind CSS v4 with the design system expressed as @theme tokens taken straight
from the Figma variables — brand, ink, muted, surface — so the palette has one
source of truth.
Animation sits in six reusable primitives (SplitText, Reveal, TiltCard, Counter,
Magnetic, Cursor) built on Motion, rather than being scattered through sections.
Lenis handles smooth scroll and is stepped from Motion's own frame.update loop,
so there is a single requestAnimationFrame driving the page instead of two
fighting for it.
Playwright does double duty: responsive and accessibility verification during
the build, and video capture for the promotional cut afterward.
~4,100 lines across 107 files, deployed on Vercel.