Building a portfolio as a developer is both exciting and surprisingly tricky. You want it to be fast, look great, and actually rank on Google. Here's how I built mine from scratch.
Why Next.js?
Next.js gives you the best of both worlds — static generation for performance and server rendering when you need dynamic data. For a portfolio + blog, this is ideal:
- The homepage is fully static (blazing fast)
- Blog posts are statically generated at build time
- The contact form uses a serverless API route
The Tech Stack
Here's what I used:
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Styling | Vanilla CSS with design tokens |
| Blog | MDX files (local, no CMS) |
| Animations | Framer Motion |
| Contact | Resend + Upstash rate limiting |
| Deployment | Vercel |
Setting Up MDX
The simplest way to add a blog to a Next.js app is MDX — write markdown, push to git, and it's live.
npm install @next/mdx @mdx-js/loader @mdx-js/react gray-matter reading-time
Each post is just a .mdx file with frontmatter:
---
title: "My Post Title"
excerpt: "A short description shown on the blog listing page."
publishedAt: "2026-05-11"
categories: ["React"]
tags: ["react", "tips"]
---
Your post content goes here in **markdown**.
Performance Optimizations
A few things I did to get a 100 Lighthouse score:
- Used
next/fontfor zero-layout-shift fonts - Set
optimizePackageImportsforlucide-reactandframer-motion - All blog pages are statically generated with
generateStaticParams - Images are served via Next.js
Imagecomponent with correct dimensions
SEO & GEO
Every blog post automatically gets:
- Dynamic
<title>and<meta description>from frontmatter - Open Graph image auto-generated with
ImageResponse(no image files needed) - JSON-LD structured data for Google rich results and AI crawlers
- Canonical URL to prevent duplicate content issues
- Sitemap generated on every build via
next-sitemap
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Building a Full Stack Portfolio with Next.js 16",
"author": {
"@type": "Person",
"name": "Abhishek Sharma"
}
}
Deploying to Vercel
Push to GitHub, connect to Vercel, add your environment variables. Done. Every git push triggers a new deploy with a fresh sitemap.
Conclusion
The MDX + Next.js combo is honestly the cleanest developer blog setup I've found. No CMS to manage, no API keys to configure, no third-party service to worry about going down. Just write, commit, push.
Abhishek Sharma
Full Stack Engineer