Deploying a Next.js Portfolio Site on Vercel
My portfolio site at iletai.qzz.io↗ is built with Next.js 16 and deployed on Vercel. Here are the key lessons from building and deploying it.
Architecture Overview
Frontend (Vercel) Backend (Cloudflare Workers)
┌─────────────────┐ ┌────────────────────────┐
│ Next.js 16 │ ──────>│ API (TypeScript) │
│ - SSG pages │ REST │ - Clean Architecture │
│ - Admin panel │<────── │ - Supabase for data │
│ - Blog │ │ - JWT Auth │
└─────────────────┘ └────────────────────────┘
Static Generation for Performance
Most pages are statically generated at build time:
1// app/projects/page.tsx
2export default async function ProjectsPage() {
3 const projects = await api.getProjects();
4 return <ProjectGrid projects={projects} />;
5}This means the projects page loads instantly — the HTML is pre-built and served from Vercel's CDN.
Dynamic Routes for Blog Posts
Individual blog posts use dynamic routes:
1// app/blog/[slug]/page.tsx
2export default async function BlogPost({ params }: { params: { slug: string } }) {
3 const post = await api.getPostBySlug(params.slug);
4 if (!post) notFound();
5
6 return (
7 <article>
8 <h1>{post.title}</h1>
9 <MDXContent content={post.content} />
10 </article>
11 );
12}The Cloudflare Bot Fight Mode Gotcha
During deployment, I encountered 403 errors in build logs:
[API Error] 403 Forbidden - https://api.iletai.qzz.io/v1/projects/featured
body: '<!DOCTYPE html><html><head><title>Just a moment...</title>...'
The response was a Cloudflare challenge page. Vercel's build servers were being blocked by Cloudflare's Bot Fight Mode.
Solution: Disable Bot Fight Mode in the Cloudflare dashboard, or create a WAF rule to allowlist Vercel's IP ranges.
Admin Panel with Client-Side Auth
The admin panel uses client-side authentication:
1'use client';
2
3export default function AdminLayout({ children }) {
4 const { user, loading } = useAuth();
5
6 if (loading) return <LoadingSpinner />;
7 if (!user) redirect('/admin/login');
8
9 return <AdminShell>{children}</AdminShell>;
10}Environment Variables
Configure the API URL per environment:
1# .env.production
2NEXT_PUBLIC_API_URL=https://api.iletai.qzz.io
3
4# .env.development
5NEXT_PUBLIC_API_URL=http://localhost:8787Vercel Configuration
Key settings in my Vercel project:
- Framework: Next.js (auto-detected)
- Build Command:
next build - Node.js Version: 20.x
- Edge Middleware: Disabled (using Cloudflare instead)
Performance Optimizations
- Image optimization — Next.js
<Image>with Unsplash loader - Font optimization —
next/fontfor zero layout shift - Code splitting — automatic per-route splitting
- Prefetching —
<Link>prefetches on hover
Lighthouse Scores
After optimization:
- Performance: 98
- Accessibility: 100
- Best Practices: 100
- SEO: 100
Conclusion
Next.js + Vercel is a powerful combination for portfolio sites. The static generation gives you incredible performance, the admin panel works great with client-side auth, and deployment is as simple as pushing to main. Just watch out for Cloudflare Bot Fight Mode if your API is behind Cloudflare!