Skip to content
H
Next.jsTailwind CSSTypeScriptPortfolio

Building a Portfolio with Next.js 14 and Tailwind CSS

How I built ihimanshu.in — liquid glass navigation, MDX blog, dynamic OG images, and a contact form wired to Resend.

By Himanshu Yadav2 min readViews: 1
Why this matters: How I built ihimanshu.in — liquid glass navigation, MDX blog, dynamic OG images, and a contact form wired to Resend.

When I sat down to rebuild my portfolio, I had one rule: ship something I'd be comfortable showing a hiring manager and a developer peer. Fast, accessible, and visually interesting — without being try-hard about it.

Here's what I picked and why.

The stack

  • Next.js 14 (App Router) — server components by default, clean DX, deploys to Vercel without config
  • Tailwind CSS — no jumping between files to track styles, tokens stay consistent
  • Framer Motion — handles animations without a heavy runtime
  • Resend — powers the contact form; one API call, no server to manage

The navigation

The nav was the most fun part. iOS 26 introduced a "liquid glass" aesthetic — heavy backdrop blur, specular highlights, a shimmer on hover. I built it in pure CSS:

backdrop-filter: blur(50px);
background: rgba(255, 255, 255, 0.08); /* dark mode */
box-shadow: inset 0 1px 0 rgba(255,255,255,0.25), /* specular top */
            inset 0 0 0 1px rgba(255,255,255,0.15), /* border */
            0 8px 32px rgba(0,0,0,0.12); /* drop shadow */

The hover shimmer is a @keyframes animation — no JavaScript in the loop, which is why it stays smooth even on slower devices.

Blog: MDX in the repo

I didn't want a CMS. MDX files in /content/blog/ stay version-controlled alongside the code, there are no API calls at build time, and gray-matter handles frontmatter types without extra tooling.

Publishing requires a code push. For a personal blog, that's a reasonable trade.

OG images

Each post gets its own OG image through a dynamic route at /og. It takes title and description as query params and returns a 1200×630 ImageResponse via next/og — no external service, no pre-generation step.

What's left

I still want to run a proper Lighthouse audit and hit 90+. Performance feels good but I haven't measured it formally yet, which is overdue.

The source is on GitHub.