Building This Portfolio: The Engineering Behind the Design

Building This Portfolio: The Engineering Behind the Design

A deep dive into the technical decisions, interactive features, and design philosophy behind my portfolio site — from D3.js maps to Framer Motion page transitions.

MK
Manav Kaneria
/
3 min read

Building This Portfolio

Every developer portfolio tells two stories: the content you put on it, and the engineering decisions behind it. This post is about the second story.

Why Not a Template?

Templates are fast. But they signal that you chose speed over craft. For a site that's supposed to showcase engineering ability, I wanted every pixel to be intentional — and every interaction to demonstrate real technical depth.

The Stack

  • Next.js 15 with App Router for file-based routing and server components
  • Tailwind CSS v4 with CSS-only theme configuration (no tailwind.config.ts)
  • Framer Motion for page transitions, scroll animations, and micro-interactions
  • D3.js + TopoJSON for the interactive world map ("MyAtlas")
  • Color themes (Midnight, Blueprint, Terminal, Test) driven by CSS custom properties

The Atlas: D3 Meets React

The interactive map was the most complex piece. D3 wants to own the DOM. React wants to own the DOM. Making them coexist required a clear contract:

  1. React owns the container <svg ref={svgRef}>
  2. D3 renders inside it via useEffect
  3. State (which country, which city) lives in React hooks
  4. D3 re-renders when props change

The "bloom from dot" interaction — where clicking a city dot causes an experience card to scale up from that exact position — required converting SVG coordinates to screen coordinates using getBoundingClientRect() math.

Performance Decisions

  • Dynamic imports for the D3 atlas — code-split so it doesn't block initial paint
  • Native browser scrolling — no smooth-scroll library, so behavior matches OS defaults
  • The home page JS bundle dropped from 29kB to 7kB after adding next/dynamic

Micro-interactions That Matter

Small details that elevate the experience:

  • Magnetic buttons that pull toward your cursor
  • Film grain texture at 3% opacity — barely visible, but adds editorial depth
  • Scroll-linked UI (e.g. experience timeline) tied to scroll position without extra smoothing
  • Cursor glow that follows your mouse across the page
  • Text reveal animations that blur-in word by word

The Theme System

Three themes, zero JavaScript for color switching. Each theme is a set of CSS custom properties under a [data-theme] selector. Tailwind v4's @theme block registers them as first-class tokens:

@theme inline {
  --color-accent: var(--color-accent);
  --color-bg-primary: var(--color-bg-primary);
}

This means bg-bg-primary generates background-color: var(--color-bg-primary) — and switching themes is just changing one attribute on <html>.

What's Next

  • Individual project case study pages with architecture diagrams
  • Blog with MDX (you're reading the proof it works)
  • Guestbook with GitHub OAuth
  • About page with bento grid layout

Building this was an exercise in restraint as much as ambition. Every animation earns its place. Every component has a purpose. And the code is structured so that adding a new project or blog post is just adding a data entry — no layout work required.


Thanks for reading. If you want to discuss the engineering decisions or have suggestions, reach out via the contact page.

SYSTEMS THAT SCALE.

CODE THAT SHIPS.

I'm available for co-ops & internships.

I care about clean architecture, reliable systems, and shipping things that actually work.