I wanted a portfolio that reflected my work at the intersection of sound, design, and code. Not just a static showcase, but something that felt alive and demonstrated the kind of experiences I build. Here's how it came together.
The Stack
- **Next.js 14** — React framework with App Router for routing and static generation
- **TypeScript** — Type safety throughout
- **Tailwind CSS** — Utility-first styling
- **Framer Motion** — Smooth animations and transitions
- **Three.js** — 3D graphics via React Three Fiber
- **wavesurfer.js** — Audio waveform visualization
Design Philosophy: Dark & Glassy
I wanted a dark interface with depth—something that felt modern without being flashy. The solution was a glassy UI pattern:
- **Semi-transparent backgrounds** using Tailwind's opacity modifiers
- **Backdrop blur** for that frosted glass effect
- **Subtle borders** at low opacity for definition
- **Consistent color tokens** defined in Tailwind config
The background color (#1a1a2e, an "ink black" with a blue undertone) pairs well with the glassy cards at 80% opacity. Everything feels cohesive because it all references the same base colors.
The 3D Hero
The landing page features an interactive Three.js scene. React Three Fiber made this surprisingly painless to integrate with the rest of the React app. The scene runs in a fixed background layer while the content scrolls over it.
Key considerations:
- **Performance** — Lazy loading the 3D scene with Next.js dynamic imports
- **Fallbacks** — Loading spinner while the scene initializes
- **Responsiveness** — The scene adapts to viewport size
Category System
Projects are tagged with categories: Sound, Design, and Code. Each has an associated color (red, blue, green). The filtering system on the Work page lets you combine categories, and the Clear button shows a mixed color based on your selection—literally blending the RGB values of the selected categories.
What I Learned
Building your own portfolio is a good exercise in restraint. It's tempting to over-engineer everything, but the goal is showcasing work, not the portfolio itself. I tried to keep things simple:
- No CMS—content lives in TypeScript files
- Minimal dependencies
- Components that do one thing well
The site will evolve as my work does. That's the point.