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.
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.
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:
Get latest source from repository
Set up GitHub Pages environment
Speed up builds with intelligent caching
Install Node 20 with npm cache
npm ci for clean, fast installs
npm run build → static export
Package /out directory for 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.
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.ts • skills.ts
Key Insight: Structure your data and code to serve multiple audiences—this demonstrates strategic thinking that employers value.
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" />
}
• 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.
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)
}
• 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>
)}
• 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>
• 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);
}
}
• 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
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.
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.
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.
Strategic Lazy Loading
Complex 3D animations loaded only when needed with intelligent cleanup. 'use client' only when necessary, maintaining static generation benefits.
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