Next.jsTypeScriptPortfolio DevelopmentWeb DevelopmentLessons Learned

5 Key Lessons I Learned from Making This Website (So You Don't Have To)

Five critical lessons I discovered while building my developer portfolio with Next.js, TypeScript, and modern web technologies - and how you can apply them to your own projects.

Sami MelhemJune 28th, 20259 min read

Building a developer portfolio isn't just about showcasing your work, but a worthwhile journey that teaches you as much about software development as any ongoing project that you might be working on. Over the past 3 weeks, I've built this website from scratch and discovered that the real value of creating this portfolio is not just the final product, but the lessons learned along the way. Here are my 5 most critical insights that can save you days and weeks of development time.

1

Framer Motion + TypeScript = Animation Perfection

The Problem I Solved: I needed to have professional page transitions without sacrificing website performance, plus type-safe animations that wouldn't break during refactoring.

The Magic Combination

Using `AnimatePresence` with `usePathname` hook creates seamless route transitions, while timeline-based animations prevent double animations when users visit pages.

<AnimatePresence mode="wait">
  <motion.main
    key={pathname}
    initial={{ opacity: 0, y: 20 }}
    animate={{ opacity: 1, y: 0 }}
    exit={{ opacity: 0, y: -20 }}
    transition={{ duration: 0.3 }}
  />
</AnimatePresence>

The timeline-based approach ensures each page animation completes before the next begins, preventing the jarring experience of overlapping animations.

Hero Section

// Hero.tsx - Elements appear in sequence
<motion.h1 
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.6, delay: 0.4 }}
>
  Hi, I'm Sami Melhem
</motion.h1>

<motion.p 
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.6, delay: 0.6 }}
>
  Senior at Texas A&M University...
</motion.p>

<motion.div 
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.6, delay: 0.8 }}
>
  {buttons.map((button, index) => (
    <motion.div
      key={button.href}
      initial={{ opacity: 0, x: index === 0 ? -20 : 20 }}
      animate={{ opacity: 1, x: 0 }}
      transition={{ duration: 0.4, delay: 1.0 + index * 0.1 }}
    >
      {button.label}
    </motion.div>
  ))}
</motion.div>

Notice how each element has an increasing delay (0.4s → 0.6s → 0.8s → 1.0s+), creating a smooth cascade effect that guides the user's attention naturally down the page.

Key Insight: Type-safe animations with proper timing create professional interactions that recruiters notice and remember.

2

CI/CD Pipeline Automation Saves Hours Every Week

The Problem I Solved: Manual deployments were time-consuming and error-prone. I needed a deployment strategy that is fast, free, and replicable.

The Complete Pipeline Solution

GitHub Actions Automation:

Push to main → automatic build → deploy in minutes

The 8-Step Automation Process

Here's the exact workflow that runs automatically on every push:

📁1.Checkout code

Get latest source from repository

⚙️2.Configure Pages

Set up GitHub Pages environment

3.Cache Next.js build

Speed up builds with intelligent caching

📦4.Setup Node.js

Install Node 20 with npm cache

🔧5.Install dependencies

npm ci for clean, fast installs

🏗️6.Build

npm run build → static export

📤7.Upload artifact

Package /out directory for Pages

🚀8.Deploy to Pages

Live site updated automatically

Total Time: <2 minutes from push to live site

Custom Domain Setup:

Bought "samimelhem.com" and routed it to "samimelhem.github.io" for professional branding while keeping GitHub's fast, free hosting.

Time Savings

No more manual deployments

Cost: $0

GitHub Pages handles traffic spikes

Career Showcase

Demonstrates DevOps skills

Key Insight: Choose GitHub Pages over Vercel when you want to demonstrate automation skills AND provide a completely free template others can follow.

3

The "Key Details" Philosophy

The Problem I Solved: Recruiters need quick assessment tools to evaluate candidates online professionally, developers wanted implementation details that they could understand and learn from, and generic portfolios don't differentiate candidates.

Data Architecture That Serves Everyone

For Recruiters:

  • • Quantified achievements
  • • Clear proficiency levels
  • • Measurable business impact

For Developers:

  • • Technical deep dives
  • • Problem-solving examples
  • • Replicable code patterns

Smart Integration Examples

Contact System: Platform-Specific Optimizations

Advanced email client integration with intelligent platform detection and fallback mechanisms:

const emailServices = [
  {
    name: 'Gmail',
    icon: SiGmail,
    color: 'text-red-400',
    getUrl: (subject, body) => 
      `https://mail.google.com/mail/?view=cm&fs=1&to=samilmelhem23@gmail.com&subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`
  },
  {
    name: 'Outlook',
    icon: MdEmail,
    color: 'text-blue-500',
    getUrl: (subject, body) => {
      const userAgent = navigator.userAgent.toLowerCase()
      // On Windows, try desktop app first
      if (userAgent.includes('windows')) {
        return `ms-outlook://compose?to=samilmelhem23@gmail.com&subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`
      }
      // On Mac/iOS, use web version
      return `https://outlook.live.com/mail/0/deeplink/compose?to=samilmelhem23@gmail.com&subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`
    }
  },
  {
    name: 'Apple Mail',
    icon: SiApple,
    color: 'text-gray-300',
    getUrl: (subject, body) => 
      `mailto:samilmelhem23@gmail.com?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`,
    isAvailable: () => {
      const userAgent = navigator.userAgent.toLowerCase()
      return userAgent.includes('mac') || userAgent.includes('iphone') || userAgent.includes('ipad')
    }
  }
]
🪟 Windows Outlook Optimization

Desktop-First Strategy: Attempts `ms-outlook://` protocol to open native app
Intelligent Fallback: 1-second timeout before opening web version
Best User Experience: Preserves user's preferred email environment

🍎 Apple Ecosystem Integration

Device Detection: Only shows Apple Mail on Mac/iPhone/iPad devices
Native Protocol: Uses `mailto:` for seamless system integration
Cross-Device Sync: Leverages iCloud email synchronization

📧 Gmail Web Optimization

Universal Compatibility: Works across all platforms and browsers
Pre-filled Forms: Automatic subject/body population with URL encoding
Professional Routing: Direct compose interface bypass

⚡ Technical Implementation

Real-Time Detection: `navigator.userAgent` parsing for accurate platform identification
Security-First: `encodeURIComponent()` prevents injection attacks
UX Enhancement: Dynamic dropdown positioning to prevent off-screen rendering
Performance: Client-side processing eliminates server dependencies

💡 See it in action to try the platform detection and experience the optimizations firsthand

File Organization: Professional Structure

Clear separation of concerns that recruiters immediately recognize:

samimelhem-portfolio/
├── components/              # 14 reusable UI components
│   ├── AboutPreview.tsx     # Homepage about section
│   ├── BlogCard.tsx         # Blog post preview cards
│   ├── BlogListClient.tsx   # Blog listing page
│   ├── CarlaIcon.tsx        # CARLA project icon
│   ├── ClientLayout.tsx     # Page transitions & animations
│   ├── ContactIcons.tsx     # Social media links
│   ├── ConvexIcon.tsx       # Convex database icon
│   ├── FeaturedInFront.tsx  # Homepage featured content
│   ├── Footer.tsx           # Site footer
│   ├── Hero.tsx             # Landing page hero section
│   ├── Navbar.tsx           # Navigation header
│   ├── ProjectCard.tsx      # Project preview cards
│   ├── SkillIcon.tsx        # Technology skill badges
│   └── VantaNet.tsx         # Animated background
├── data/                    # Structured data layer
│   ├── projects.ts          # Project metadata & achievements
│   └── skills.ts            # Technical expertise & experience
├── src/app/                 # Next.js 14 app router structure
│   ├── about/page.tsx       # Personal background & education
│   ├── blog/                # Content management system
│   │   └── page.tsx         # Blog listing page
│   ├── contact/page.tsx     # Smart contact form
│   ├── projects/            # Dynamic project showcase
│   │   ├── [slug]/          # Individual project pages
│   │   └── page.tsx         # Projects listing
│   ├── skills/              # Technical expertise display
│   │   ├── [slug]/          # Individual skill deep-dives
│   │   └── page.tsx         # Skills overview
│   ├── globals.css          # Global styles & animations
│   ├── layout.tsx           # Root layout & metadata
│   └── page.tsx             # Homepage
├── types/                   # TypeScript definitions
└── .github/workflows/       # CI/CD automation

💡 Explore the structure - Full source code and implementation details

Documentation: Technical + Business Value

Project Example: SaveGas App

{
  title: 'SaveGas',
  description: 'Real-time gas price tracking application that helps users save up to $0.30 per gallon',
  
  // For recruiters: Clear business metrics
  achievements: [
    'Real-time gas price tracking that helps users save an average of $0.15-$0.30 per gallon',
    'Interactive map interface with turn-by-turn navigation to selected stations',
    'Secure authentication system processing 100+ gas station data points in real-time'
  ],
  
  // For developers: Technical implementation
  techs: ['React', 'TypeScript', 'Convex', 'Auth0', 'Vite', 'Tailwind CSS'],
  longDescription: 'Built a real-time gas price tracking application with 60-second refresh system to optimize API calls while maintaining strict privacy standards...'
}

Skill Example: Python Expertise

{
  name: 'Python',
  proficiency: 'Advanced',
  experience: '4+ years',
  
  // For recruiters: Experience metrics
  internships: 4,
  researchRoles: 2,
  publications: 1,
  
  // For developers: Technical deep dive
  technicalDeepDive: `**Core Concepts I'm Proficient In:**
  - Advanced Pandas operations for DataFrame manipulation
  - Async/await patterns for full-stack communication
  - Type hints implementation with Pydantic for LLM training pipelines
  
  **Complex Problem-Solving Examples:**
  Architected comprehensive carbon footprint tracking system at INTERA 
  that automated data collection using Selenium, processed environmental 
  datasets with Pandas, and created interactive visualizations...`
}

💡 Browse the data structure: projects.tsskills.ts

Key Insight: Structure your data and code to serve multiple audiences—this demonstrates strategic thinking that employers value.

4

Performance Optimization Through Strategic Lazy Loading

The Problem I Solved: Complex animations and components were slowing initial page load, while needing maintainable architecture and static generation benefits.

The Three-Pillar Approach

Strategic Lazy Loading: VantaNet Background

Complex 3D animations loaded only when needed with intelligent cleanup:

// components/VantaNet.tsx - Strategic lazy loading implementation
'use client'

import { useState, useRef, useEffect } from 'react'
import NET from 'vanta/dist/vanta.net.min'
import * as THREE from 'three'

export default function VantaNet() {
  const [vantaEffect, setVantaEffect] = useState<VantaNetEffect | null>(null)
  const ref = useRef<HTMLDivElement>(null)

  useEffect(() => {
    // Only load when element is mounted and effect doesn't exist
    if (!vantaEffect && ref.current) {
      setVantaEffect(
        NET({
          THREE,                  // Heavy 3D library
          el: ref.current,        // DOM element binding
          color: 0x0fffff,        // Optimized settings
          backgroundColor: 0x0,   
          points: 12.0,           // Performance-balanced config
          maxDistance: 25.0,
          spacing: 18.0
        })
      )
    }
    
    // Critical cleanup prevents memory leaks
    return () => {
      if (vantaEffect) vantaEffect.destroy()
    }
  }, [vantaEffect])

  return <div ref={ref} className="fixed inset-0 -z-10" />
}
Key Optimizations:
Conditional Loading: Only creates effect when DOM element exists
Memory Management: Proper cleanup prevents memory leaks
Performance Settings: Balanced points/spacing for smooth animation
Client-Side Only: 'use client' ensures no SSR performance impact

💡 View full component - See this exact implementation running on every page

Component Architecture:

'use client' only when needed—server components by default for better performance

Next.js Static Generation:

output: 'export' for lightning-fast static sites with dynamic capabilities

Load Speed

First contentful paint under 1 second

User Experience

Smooth interactions without penalties

SEO Benefits

Static generation improves rankings

Key Insight: Architecture decisions made early determine your app's performance ceiling—optimize from day one, not as an afterthought.

5

Mobile-First Responsive Design Prevents Redesign Later

The Problem I Solved: Desktop-first designs break on mobile devices, touch interactions need different UX patterns, and responsive design as an afterthought creates expensive technical debt.

The Mobile-First Strategy

Responsive State Management:

const [isMobile, setIsMobile] = useState(false)
useEffect(() => {
  const checkMobile = () => setIsMobile(window.innerWidth < 768)
  window.addEventListener('resize', checkMobile)
}, [])

Touch-First Interactions:

Advanced swipe navigation with live drag preview and intelligent gesture detection:

Swipe Navigation with Live Preview
// components/FeaturedInFront.tsx - Touch interaction system
const [touchStart, setTouchStart] = useState<number | null>(null)
const [touchEnd, setTouchEnd] = useState<number | null>(null)
const [dragOffset, setDragOffset] = useState(0)

const onTouchStart = (e: React.TouchEvent) => {
  setTouchEnd(null)
  setTouchStart(e.targetTouches[0].clientX)
  setDragOffset(0)
}

const onTouchMove = (e: React.TouchEvent) => {
  if (!touchStart) return
  
  const currentTouch = e.targetTouches[0].clientX
  setTouchEnd(currentTouch)
  
  // Live drag preview - user sees movement immediately
  const offset = currentTouch - touchStart
  setDragOffset(offset)
}

const onTouchEnd = () => {
  if (!touchStart || !touchEnd) {
    setDragOffset(0)
    return
  }
  
  const distance = touchStart - touchEnd
  const isLeftSwipe = distance > minSwipeDistance
  const isRightSwipe = distance < -minSwipeDistance

  if (isLeftSwipe && currentIndex < featured.length - 1) {
    setCurrentIndex(currentIndex + 1)
  }
  if (isRightSwipe && currentIndex > 0) {
    setCurrentIndex(currentIndex - 1)
  }
  
  setDragOffset(0)
}
Key Features:
Live Preview: Users see content move as they drag
Gesture Detection: 50px minimum distance prevents accidental swipes
State Management: Tracks touch lifecycle with proper cleanup
Visual Feedback: Immediate response to touch input
Mobile-Optimized Layout Switching
{isMobile ? (
  // Mobile: Full-width swipeable carousel
  <div className="w-full px-4">
    <div className="overflow-hidden rounded-xl">
      <div 
        className="flex transition-transform duration-300 ease-out"
        style={{ 
          transform: `translateX(calc(-${currentIndex * 100}% + ${dragOffset}px))`,
          scrollbarWidth: 'none', 
          msOverflowStyle: 'none' 
        }}
        onTouchStart={onTouchStart}
        onTouchMove={onTouchMove}
        onTouchEnd={onTouchEnd}
      >
        {featured.map((proj) => (
          <div className="flex-shrink-0 w-full">
            <ProjectCard {...proj} />
          </div>
        ))}
      </div>
    </div>
  </div>
) : (
  // Desktop: Fixed-width centered display with arrow navigation
  <div className="w-[450px] lg:w-[500px] xl:w-[550px]">
    <ProjectCard {...featured[currentIndex]} />
  </div>
)}
Architecture Decisions:
Conditional Rendering: Completely different components for mobile vs desktop
Touch Zones: Full-width touch areas on mobile for easier interaction
Performance: CSS transforms for smooth 60fps animations
Accessibility: Maintains keyboard navigation and screen reader support
Mobile Navigation Menu
// components/Navbar.tsx - Touch-optimized mobile menu
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)

// Prevent body scroll when mobile menu is open
useEffect(() => {
  if (mobileMenuOpen) {
    document.body.style.overflow = 'hidden'
  } else {
    document.body.style.overflow = 'unset'
  }
  return () => {
    document.body.style.overflow = 'unset'
  }
}, [mobileMenuOpen])

// Animated hamburger with touch feedback
<button
  className="md:hidden flex flex-col justify-center items-center w-8 h-8 space-y-1.5 z-50"
  onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
  aria-label="Toggle mobile menu"
>
  <motion.span
    className="w-6 h-0.5 bg-white transition-all duration-300"
    animate={mobileMenuOpen ? { rotate: 45, y: 6 } : { rotate: 0, y: 0 }}
  />
  <motion.span
    className="w-6 h-0.5 bg-white transition-all duration-300"
    animate={mobileMenuOpen ? { opacity: 0 } : { opacity: 1 }}
  />
  <motion.span
    className="w-6 h-0.5 bg-white transition-all duration-300"
    animate={mobileMenuOpen ? { rotate: -45, y: -6 } : { rotate: 0, y: 0 }}
  />
</button>
UX Enhancements:
Visual Feedback: Animated hamburger ↔ X transformation
Touch Targets: 44px minimum touch target size for accessibility
Body Lock: Prevents background scrolling when menu is open
Backdrop Dismiss: Touch outside menu to close
Touch-Optimized Interactive Elements
// Touch-friendly button sizing and spacing
const buttonStyle = {
  // Minimum 44px touch target (iOS/Android guidelines)
  minHeight: '44px',
  minWidth: '44px',
  // Adequate spacing between touch targets
  margin: '8px',
  // Visual feedback for touch states
  transform: 'scale(1)',
  transition: 'all 0.2s ease'
}

// Hover effects adapted for touch
.touch-friendly-button {
  @media (hover: hover) {
    &:hover { transform: scale(1.05); }
  }
  
  // Touch-specific interactions
  &:active { 
    transform: scale(0.95);
    background-color: rgba(255, 255, 255, 0.1);
  }
}
Implementation Details:
Touch Guidelines: Follows iOS/Android 44px minimum touch target
Hover Detection: Uses CSS @media (hover: hover) to detect touch devices
Active States: Immediate feedback on touch with scale animation
Spacing: Generous gaps prevent accidental touches

💡 Try it yourself - Visit the homepage on mobile and swipe through the featured projects, or test the mobile navigation menu

The Cost of Desktop-First:

  • • 60%+ of portfolio views are mobile
  • • Expensive redesigns later
  • • Poor user experience

Mobile-First Benefits:

  • • Progressive enhancement
  • • No technical debt
  • • Professional standard

Key Insight: Design for mobile constraints first, then enhance for desktop—this prevents expensive redesigns and ensures professional quality across all devices.

Key Takeaways: 5 Lessons That Transform Development

1

Timeline-Based Animations

Framer Motion + TypeScript creates professional page transitions with sequential delays (0.4s → 0.6s → 0.8s → 1.0s+) that guide user attention naturally.

2

Automated CI/CD Pipeline

GitHub Actions deploys in <1 minute with 8-step automation: checkout → build → deploy. Free hosting + custom domain = professional presence without costs.

3

Dual-Audience Data Architecture

Structure content for both recruiters (business metrics) and developers (technical deep-dives). Smart contact integration, organized file structure, and comprehensive documentation.

4

Strategic Lazy Loading

Complex 3D animations loaded only when needed with intelligent cleanup. 'use client' only when necessary, maintaining static generation benefits.

5

Touch-First Mobile Design

Advanced swipe navigation with live drag preview, 44px touch targets, and conditional rendering. Design for mobile constraints first, enhance for desktop.

The Meta-Lesson: Every architectural decision compounds. Choose technologies and patterns that serve multiple purposes and scale with your growth.

Ready to Build Your Own Portfolio?

These 5 lessons can save you weeks of development time and technical debt. From timeline-based animations to CI/CD automation, touch-first design to strategic architecture—build something that scales with your career.

Let's Connect