Why Most Portfolios Don't Get Clients
Go to any Nigerian developer's portfolio and you'll see the same thing: a hero section with "Hi, I'm [Name], Full Stack Developer," three generic project cards, and a contact form that nobody uses. This is not a portfolio. This is a digital business card that nobody asked for.
Clients don't hire developers because of hero sections. They hire because you solved a problem like theirs before and you can prove it. Your portfolio is a sales page, not a resume.

The Free Stack
| Tool | Purpose | Free Limit | Cost After |
|---|---|---|---|
| Next.js 14 | Framework (SSR = SEO) | Free forever | Free forever |
| Tailwind CSS | Styling | Free forever | Free forever |
| Vercel | Hosting + CDN | Unlimited deploys | $20/month |
| Cloudflare | Custom domain + DNS | Free forever | Free forever |
| Resend | Contact form emails | 3,000/month | $20/month |
| Plausible | Privacy-friendly analytics | Self-hosted free | $9/month |
Total cost: $0/month (domain is ₦2,500–₦15,000/year)
Step 1: Structure Your Portfolio for Conversion
A portfolio that converts follows this structure:
- Hero — One sentence: what you do + who you help
- Social proof — Client logos or testimonials (above the fold)
- Case studies — 3 detailed project breakdowns with results
- Services — What you offer with clear pricing or starting prices
- About — Brief personal story that builds trust
- Contact — Simple form + direct email + WhatsApp link
portfolio/
├── app/
│ ├── layout.jsx
│ ├── page.jsx ← Hero + Social proof
│ ├── projects/
│ │ └── [slug]/
│ │ └── page.jsx ← Case study detail
│ └── api/
│ └── contact/
│ └── route.js ← Form handler
├── components/
│ ├── Hero.jsx
│ ├── CaseStudyCard.jsx
│ ├── Testimonials.jsx
│ └── ContactForm.jsx
└── content/
└── projects.js ← Project data
Step 2: Build the Hero Section
Your hero has 3 seconds to communicate value. No animations, no typing effects, no ambiguity.
// components/Hero.jsx
export default function Hero() {
return (
<section className="min-h-[80vh] flex items-center justify-center px-6">
<div className="max-w-3xl text-center">
<p className="text-sm font-medium text-blue-600 mb-4">
Available for new projects — March 2026
</p>
<h1 className="text-4xl md:text-6xl font-bold leading-tight mb-6">
I build web apps that<br />
<span className="text-blue-600">make businesses money</span>
</h1>
<p className="text-xl text-gray-600 mb-8 max-w-xl mx-auto">
Full-stack developer in Lagos. I help startups and SMEs build
SaaS products, e-commerce platforms, and internal tools.
</p>
<div className="flex gap-4 justify-center">
<a href="#contact" className="bg-black text-white px-8 py-3 rounded-lg font-medium">
Start a Project
</a>
<a href="#projects" className="border border-gray-300 px-8 py-3 rounded-lg font-medium">
See My Work
</a>
</div>
<div className="mt-12 flex gap-8 justify-center text-gray-400">
<span>12+ projects shipped</span>
<span>₦50M+ revenue generated for clients</span>
<span>0 missed deadlines</span>
</div>
</div>
</section>
)
}
Step 3: Write Case Studies That Sell
A case study is not a list of technologies. It's a story with numbers.
// content/projects.js
export const projects = [
{
slug: 'paystack-dashboard-clone',
title: 'Payment Dashboard for a Lagos Fintech',
client: 'Confidential Fintech Startup',
problem: 'Processing 5,000+ daily transactions with manual reconciliation. Staff spent 4 hours/day matching payments.',
solution: 'Built a real-time dashboard with automated reconciliation using Next.js, Supabase, and Paystack API.',
results: [
'Reconciliation time reduced from 4 hours to 12 minutes',
'₦2.3M monthly revenue previously lost to errors — recovered',
'Team of 3 accountants reallocated to growth activities'
],
tech: ['Next.js', 'Supabase', 'Paystack', 'Vercel'],
testimonial: {
text: "He shipped in 3 weeks what our previous developer couldn't finish in 3 months.",
author: 'CTO, Lagos Fintech'
},
image: '/images/projects/paystack-dashboard.png'
}
]
// components/CaseStudyCard.jsx
import Link from 'next/link'
export default function CaseStudyCard({ project }) {
return (
<div className="border rounded-xl overflow-hidden hover:shadow-lg transition">
<img src={project.image} alt={project.title} className="w-full h-48 object-cover" />
<div className="p-6">
<h3 className="text-xl font-bold mb-2">{project.title}</h3>
<p className="text-gray-600 mb-4">{project.problem}</p>
<ul className="space-y-1 mb-4">
{project.results.map((r, i) => (
<li key={i} className="text-sm text-green-700 flex items-start gap-2">
<span>✓</span> {r}
</li>
))}
</ul>
<div className="flex gap-2 flex-wrap mb-4">
{project.tech.map(t => (
<span key={t} className="text-xs bg-gray-100 px-2 py-1 rounded">{t}</span>
))}
</div>
<Link href={'/projects/' + project.slug}
className="text-blue-600 font-medium text-sm hover:underline">
Read full case study →
</Link>
</div>
</div>
)
}
Step 4: SEO That Gets You Found on Google
Most clients search "web developer Lagos" or "Next.js developer Nigeria." If you're not on page 1, you don't exist.
// app/layout.jsx
export const metadata = {
title: 'Your Name — Full-Stack Web Developer in Lagos, Nigeria',
description: 'I build SaaS products, e-commerce platforms, and web applications for startups and SMEs. 12+ projects shipped. ₦50M+ revenue generated for clients.',
keywords: ['web developer lagos', 'next.js developer nigeria', 'saas developer africa'],
openGraph: {
title: 'Your Name — Full-Stack Web Developer',
description: 'Building web apps that make businesses money.',
url: 'https://yourname.com',
siteName: 'Your Name',
type: 'website'
}
}
// app/sitemap.js
export default function sitemap() {
return [
{ url: 'https://yourname.com', lastModified: new Date(), changeFrequency: 'monthly', priority: 1 },
{ url: 'https://yourname.com/projects/paystack-dashboard-clone', lastModified: new Date(), priority: 0.8 },
]
}
Step 5: Contact Form That Actually Works
// app/api/contact/route.js
export async function POST(req) {
const { name, email, message, budget } = await req.json()
if (!name || !email || !message) {
return Response.json({ error: 'All fields required' }, { status: 400 })
}
// Send via Resend (free: 3,000 emails/month)
const res = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.RESEND_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: 'portfolio@yourname.com',
to: 'your-email@gmail.com',
subject: 'New inquiry from ' + name,
html: '<p><strong>Name:</strong> ' + name + '</p>' +
'<p><strong>Email:</strong> ' + email + '</p>' +
'<p><strong>Budget:</strong> ' + (budget || 'Not specified') + '</p>' +
'<p><strong>Message:</strong> ' + message + '</p>'
})
})
if (res.ok) {
return Response.json({ ok: true })
}
return Response.json({ error: 'Failed to send' }, { status: 500 })
}
Step 6: Deploy and Connect Your Domain
# Deploy to Vercel
npx vercel
# Follow prompts, connect your GitHub repo
Buy a domain (₦2,500–₦15,000/year depending on TLD). Point it to Vercel. Add it in Vercel Dashboard → Settings → Domains.
Domain Strategy for African Developers
| Domain | Cost/Year | Vibe | Best For |
|---|---|---|---|
| yourname.dev | $15 | Developer-native | Tech-focused freelancers |
| yourname.com | ₦10,000 | Professional | General consulting |
| yourname.com.ng | ₦2,500 | Local credibility | Nigerian businesses |
| yourname.africa | $20 | Pan-African | Continental ambitions |
Portfolio Conversion Benchmarks
| Metric | Poor | Average | Great |
|---|---|---|---|
| Time on site | <30s | 1–2 min | 3+ min |
| Contact form submissions | 1/500 visits | 1/100 visits | 1/50 visits |
| Google ranking for key terms | Page 3+ | Page 2 | Top 5 |
| Monthly organic traffic | <50 | 200–500 | 1,000+ |
If you're getting 200 visits/month and converting 1/50, that's 4 inquiries/month. At a ₦500,000 average project, closing 25% = ₦500,000/month from your portfolio alone.
Common Mistakes
| Mistake | What Happens | Fix |
|---|---|---|
| No case studies, just tech logos | Clients can't tell if you can solve their problem | Write 3 case studies with real results |
| Generic "I'm a developer" hero | Blends in with every other portfolio | Specify who you help and what outcome you deliver |
| No contact form, just email link | High friction, most visitors won't copy your email | Add a form + WhatsApp + email |
| No SEO metadata | Invisible on Google | Add title, description, and sitemap |
| Using a template unchanged | Looks like 500 other portfolios | Customize colors, copy, and case studies |

