Building My Portfolio Website with Next.js 13
Learn about the tech stack, architecture decisions, and implementation details of my personal portfolio website.
I recently rebuilt my portfolio website using modern web technologies. In this post, I'll walk you through the tech stack, architecture decisions, and key features.
Tech Stack
- Next.js 13: For server-side rendering and routing with App Router
- TypeScript: For type safety and better developer experience
- Tailwind CSS: For styling with utility-first approach
- MDX: For blog posts with React components
- React Icons: For beautiful icons and social media integration
- Sugar High: For syntax highlighting in code blocks
- Gray Matter: For MDX frontmatter parsing
- Next Sitemap: For SEO optimization
- PWA Support: For installable web app experience
Key Features
1. Dynamic Blog with MDX and Syntax Highlighting
I implemented a blog system using MDX with Sugar High for beautiful code highlighting:
// lib/blog.ts
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
export function getPostBySlug(slug: string) {
const fullPath = path.join(process.cwd(), 'app/blog/posts', `${slug}.mdx`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
const { data, content } = matter(fileContents)
return {
slug,
content,
...data
}
}
2. Responsive Navigation
The navigation system adapts to different screen sizes:
'use client'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { useState } from 'react'
import { FiMenu, FiX } from 'react-icons/fi'
import { SITE_DATA } from '../../lib/shared'
export default function Navbar() {
const pathname = usePathname()
const [isMenuOpen, setIsMenuOpen] = useState(false)
const toggleMenu = () => setIsMenuOpen(!isMenuOpen)
return (
<>
<nav className="fixed top-0 left-0 right-0 bg-black/80 backdrop-blur-md z-50 border-b border-white/10">
<div className="max-w-6xl mx-auto px-4 flex justify-between items-center py-4">
<Link href="/" className="text-2xl font-bold">iambhvsh</Link>
<button
onClick={toggleMenu}
className="p-2 hover:bg-white/10 rounded-lg transition-colors"
aria-label="Toggle menu"
>
{isMenuOpen ? <FiX className="w-6 h-6" /> : <FiMenu className="w-6 h-6" />}
</button>
</div>
</nav>
<div
className={`fixed top-[73px] left-0 right-0 bottom-0 z-40 bg-black/95 backdrop-blur-md transition-all duration-200 ease-out transform-gpu ${
isMenuOpen ? 'translate-y-0 opacity-100' : '-translate-y-4 opacity-0 pointer-events-none'
}`}
>
<div className="max-w-6xl mx-auto px-4 py-6 space-y-2">
{SITE_DATA.pages.map(({ path, icon: Icon, name }) => (
<Link
key={path}
href={path}
onClick={toggleMenu}
className={`flex items-center gap-3 px-4 py-3 rounded-lg transition-colors ${
pathname= path ? 'bg-white/10 text-white' : 'text-gray-400 hover:bg-white/5 hover:text-white'
}`}
>
<Icon className="w-5 h-5" />
{name}
</Link>
))}
</div>
</div>
</>
)
}
3. Dark Mode Design
I chose a dark theme for better readability and modern aesthetics.
4. Search Functionality
Implemented a search system that works across pages and blog posts:
// api/search/route.ts
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const query = searchParams.get('q')
// Search implementation
const results = await searchContent(query)
return NextResponse.json(results)
}
Performance Optimizations
- Image Optimization:
<Image
src={post.coverImage}
alt={post.title}
width={1200}
height={630}
className="rounded-xl"
priority
/>
- Code Splitting:
const MDXContent = dynamic(() => import('@/components/MDXContent'), {
loading: () => <div>Loading...</div>
})
Deployment
The site is deployed on Vercel, which provides:
- Automatic deployments
- Edge functions
- Analytics
- Great performance out of the box
Lessons Learned
-
TypeScript is Worth It: While it requires more initial setup, TypeScript caught many bugs before they reached production.
-
MDX for Content: Using MDX for blog posts provides great flexibility in mixing markdown with React components.
-
Tailwind's Utility-First Approach: Tailwind CSS made styling consistent and maintainable across the project.
Future Improvements
- Add authentication for a comment system
- Implement a newsletter
- Add more interactive components
- Improve search with better algorithms
Conclusion
Building this portfolio was a great learning experience. The combination of Next.js, TypeScript, and Tailwind CSS proved to be powerful and developer-friendly.
Feel free to check out the source code on GitHub and let me know what you think!
"The best way to learn is to build" - Every Developer Ever
I hope this post helps others who are looking to build their own portfolio websites. If you have any questions, feel free to reach out!