Overview
A portfolio for Twinkle Khandelwal, a UI/UX designer at Melange Digital. The visual language is light, minimal and neobrutalist: thick ink borders, hard offset shadows, draggable stickers and a palette of six accents. Her Behance projects flow in on their own, and the site has its own soundtrack, generated live in the browser.
Problem
A designer’s portfolio is itself a design sample, so it has to show personality without getting in the way of the work. It also had to stay current without her touching code, because new case studies go to Behance first.
My role
- Built the whole site on Next.js 15 with server components and incremental static regeneration.
- Wrote a server-side Behance integration with a dependency-free RSS parser and a static fallback.
- Turned the brief into a token-based design system in Tailwind CSS 4: colours, brutalist borders, offset shadows, highlighter boxes and outlined type.
- Choreographed the motion: a real-progress preloader, a kinetic variable-font hero, pinned scroll scenes and a horizontal work gallery.
- Built a generative lo-fi ambient engine on the Web Audio API.
Architecture
- FrameworkNext.js 15.5 App Router. An async server component fetches Behance and renders every section.
- ContentAll personal copy lives in one file, drawn from her résumé, so every section updates without touching a component.
- BehanceThe profile’s RSS feed, fetched on the server, parsed with a small regex parser and revalidated every six hours, with a snapshot as fallback.
- MotionGSAP and ScrollTrigger for pinned scenes, Framer Motion for springs, and Lenis driven by the GSAP ticker.
- SoundA Web Audio engine: chord pads, bass, a randomised pluck melody, delay, reverb and tape hiss.
Technology
Framework
- Next.js
- React
- JavaScript
- Tailwind CSS
Motion
- GSAP
- ScrollTrigger
- Framer Motion
- Lenis
Platform
- Web Audio API
- Behance RSS
- ISR
- Vercel
Engineering challenges
Live work without an API
Behance shut down its public API, but the portfolio still had to show her latest projects without anyone editing the site.
A loader that tells the truth
Most preloaders count to 100 on a timer, whether or not anything has loaded.
Music with no audio files
Background music normally means licensing, a large download and a loop you can hear repeat.
Smooth scroll that keeps pins in sync
Smooth scrolling and pinned ScrollTrigger scenes run on separate clocks, and pins drift or jitter.
Solution
- S1
Live work without an API
The server reads her profile’s RSS feed with a browser-like user agent, extracts title, link, date and a higher-resolution cover, and regenerates the page every six hours. If the feed fails, a static snapshot keeps the grid full.
- S2
A loader that tells the truth
The counter tracks real work: fonts, page resources and the key Behance covers. It reaches 100 only when they have loaded, with a 1.6-second minimum and a 10-second safety cap.
- S3
Music with no audio files
The soundtrack is synthesised live, so it never repeats exactly. It starts only from a click, remembers the visitor’s choice and fades out when the tab is hidden.
- S4
Smooth scroll that keeps pins in sync
Lenis is driven by the GSAP ticker, and every animation is cleaned up on unmount through gsap.context and gsap.matchMedia.
Performance
- Behance covers go through next/image, and the page is statically generated, then revalidated.
- Reduced motion turns off the intro, scroll pinning, marquees and the custom cursor, and shows content in its final state.
Product experience
- Letters of her name swell, thin and tilt away from the cursor along the variable font’s weight and width axes. Without a cursor, a soft wave drifts through instead.
- Process cards stack and spread on scroll, a pinned word switcher floods the screen with colour, and the work gallery scrolls sideways with 3D tilt.
- Client projects link to their Behance case study automatically when one exists.

