Lecture : 10 minutes · Niveau : intermédiaire · Mise à jour : avril 2026
Un portfolio développeur efficace ne ressemble pas à un site d’agence. Il convertit parce qu’il respecte le temps du visiteur : un client met 15 secondes à décider s’il vous contacte. Ce guide construit un portfolio Next.js déployable en 1 heure, qui coche les cases qui comptent.
Sommaire
- Ce qu’un client regarde réellement (et ce qu’il ignore)
- Architecture du portfolio : 4 sections, c’est tout
- Stack technique recommandée en 2026 (informations vérifiées en avril 2026, susceptibles d’évoluer)
- Initialiser le projet Next.js 15
- Le code minimal de chaque section
- SEO de base : metadata, sitemap, OG image
- Déploiement Vercel gratuit
- Domaine personnalisé et HTTPS
- FAQ
1. Ce qu’un client regarde réellement (et ce qu’il ignore)
Études d’usabilité après études d’usabilité, les comportements convergent : un client (ou recruteur) qui arrive sur votre portfolio fait, dans cet ordre :
- Lit le headline (3 secondes) — qui êtes-vous, que faites-vous ?
- Scanne 2-3 projets visuellement (10 secondes) — la qualité visuelle prime sur la prose
- Cherche un moyen de contact (5 secondes) — email visible, lien LinkedIn, calendly
- Décide : vous contacter, vous ignorer, partir.
Ce qu’il ignore :
– Animations de chargement spectaculaires
– Navigation à 7 onglets
– Page « À propos » de 800 mots
– Formulaire de contact à 9 champs
– Carrousel de 25 logos d’« anciens clients »
Construisez en conséquence : simple, rapide, contactable.
2. Architecture du portfolio : 4 sections, c’est tout
Un portfolio efficace tient en une seule page (landing) avec ancres, divisée en 4 sections :
| Section | Contenu | Longueur |
|---|---|---|
| Hero | Headline + sub-headline + 1 CTA primaire (contact) | < 5 lignes |
| Projects | 3 à 6 projets, chacun avec : titre, description courte, stack, lien live, lien repo | 1-2 paragraphes par projet |
| About | 1 paragraphe court (qui vous êtes, votre parcours, votre disponibilité) | 100-150 mots |
| Contact | Email + LinkedIn + GitHub + (optionnel) Calendly | 4-5 liens |
C’est tout. Pas de blog, pas de page services, pas de témoignages éparpillés. Si vous voulez ajouter, ajoutez un lien dans le header. La page d’accueil reste minimale.
3. Stack technique recommandée en 2026
Pour un portfolio :
- Framework : Next.js 15 (App Router) — SEO solide, déploiement Vercel sans configuration
- Styling : Tailwind CSS — rapide, maintenance simple, looks moderne par défaut
- Composants UI : shadcn/ui (optionnel) — composants pré-fabriqués, copiables, sans dépendance lourde
- Hébergement : Vercel (offre Hobby gratuite suffit pour un portfolio)
- Domaine : Namecheap, Porkbun, OVH, ou votre registrar habituel
- Analytics (optionnel) : Vercel Analytics ou Plausible (privacy-friendly)
4. Initialiser le projet Next.js 15
Prérequis : Node.js 20+ installé.
# Création du projet
npx create-next-app@latest mon-portfolio --typescript --tailwind --app --eslint
cd mon-portfolio
# Lancer en dev
npm run dev
# Ouvrir http://localhost:3000
Structure de fichiers à créer :
mon-portfolio/
├── app/
│ ├── layout.tsx
│ ├── page.tsx ← landing (toutes les sections)
│ ├── globals.css
│ ├── opengraph-image.tsx ← image OG dynamique
│ └── sitemap.ts ← sitemap.xml dynamique
├── components/
│ ├── Hero.tsx
│ ├── Projects.tsx
│ ├── About.tsx
│ └── Contact.tsx
├── lib/
│ └── projects.ts ← liste des projets en data
└── public/
└── (vos images)
5. Le code minimal de chaque section
lib/projects.ts — vos projets en data
export type Project = {
slug: string;
title: string;
description: string;
stack: string[];
liveUrl?: string;
repoUrl?: string;
image?: string; // chemin /public
};
export const projects: Project[] = [
{
slug: 'commerce-african-marketplace',
title: 'Marketplace e-commerce',
description: 'Place de marché pour artisans avec paiement multi-devises, gestion vendeurs, recherche full-text.',
stack: ['Next.js', 'Stripe Connect', 'PostgreSQL', 'Algolia'],
liveUrl: 'https://exemple-live.com',
repoUrl: 'https://github.com/vous/repo',
image: '/projects/marketplace.png',
},
// … 2 à 5 autres projets
];
components/Hero.tsx
export default function Hero() {
return (
<section className="min-h-[80vh] flex flex-col justify-center max-w-3xl mx-auto px-6 py-24">
<p className="text-sm uppercase tracking-wider text-neutral-500 mb-4">
Senior Next.js Developer · Disponible
</p>
<h1 className="text-5xl md:text-6xl font-bold tracking-tight mb-6">
Je construis des produits web qui chargent vite et convertissent.
</h1>
<p className="text-xl text-neutral-600 dark:text-neutral-300 mb-8">
Spécialiste Next.js, Stripe, et performance front-end. Je travaille avec
des équipes produit ambitieuses entre l'Europe et l'Afrique de l'Ouest.
</p>
<div className="flex gap-4">
<a
href="mailto:vous@domaine.com"
className="bg-black text-white px-6 py-3 rounded-lg hover:opacity-80 transition"
>
Discutons de votre projet
</a>
<a href="#projects" className="px-6 py-3 underline underline-offset-4">
Voir mes projets
</a>
</div>
</section>
);
}
components/Projects.tsx
import { projects } from '@/lib/projects';
import Image from 'next/image';
export default function Projects() {
return (
<section id="projects" className="max-w-5xl mx-auto px-6 py-24">
<h2 className="text-3xl font-bold mb-12">Projets sélectionnés</h2>
<div className="space-y-16">
{projects.map((p) => (
<article key={p.slug} className="grid md:grid-cols-2 gap-8 items-start">
{p.image && (
<Image
src={p.image}
alt={p.title}
width={800}
height={500}
className="rounded-lg"
/>
)}
<div>
<h3 className="text-2xl font-semibold mb-2">{p.title}</h3>
<p className="text-neutral-600 dark:text-neutral-300 mb-4">{p.description}</p>
<div className="flex flex-wrap gap-2 mb-4">
{p.stack.map((s) => (
<span key={s} className="text-xs bg-neutral-100 dark:bg-neutral-800 px-2 py-1 rounded">
{s}
</span>
))}
</div>
<div className="flex gap-4 text-sm">
{p.liveUrl && <a href={p.liveUrl} className="underline">Voir le projet →</a>}
{p.repoUrl && <a href={p.repoUrl} className="underline">Code source →</a>}
</div>
</div>
</article>
))}
</div>
</section>
);
}
components/About.tsx
export default function About() {
return (
<section id="about" className="max-w-3xl mx-auto px-6 py-24">
<h2 className="text-3xl font-bold mb-6">À propos</h2>
<p className="text-lg text-neutral-700 dark:text-neutral-300">
Développeur basé à Dakar, je travaille avec des équipes produit pour livrer
des interfaces web rapides, accessibles et maintenables. 5 ans d'expérience
sur la stack moderne JavaScript, dont 3 sur Next.js. Disponible pour des
missions de 1 à 6 mois, en remote, avec un fort recouvrement sur les
horaires européens.
</p>
</section>
);
}
components/Contact.tsx
export default function Contact() {
return (
<section id="contact" className="max-w-3xl mx-auto px-6 py-24 text-center">
<h2 className="text-3xl font-bold mb-6">Travaillons ensemble</h2>
<p className="text-lg text-neutral-600 mb-8">
Réponse sous 24h en jour ouvré.
</p>
<div className="flex justify-center gap-6 text-lg">
<a href="mailto:vous@domaine.com" className="underline">Email</a>
<a href="https://www.linkedin.com/in/vous" className="underline">LinkedIn</a>
<a href="https://github.com/vous" className="underline">GitHub</a>
</div>
</section>
);
}
app/page.tsx
import Hero from '@/components/Hero';
import Projects from '@/components/Projects';
import About from '@/components/About';
import Contact from '@/components/Contact';
export default function HomePage() {
return (
<main>
<Hero />
<Projects />
<About />
<Contact />
</main>
);
}
6. SEO de base : metadata, sitemap, OG image
app/layout.tsx — metadata globale
import type { Metadata } from 'next';
import './globals.css';
export const metadata: Metadata = {
title: {
default: 'Votre Nom — Senior Next.js Developer',
template: '%s | Votre Nom',
},
description:
'Développeur Next.js basé à Dakar, je construis des produits web rapides et fiables pour des équipes ambitieuses.',
openGraph: {
title: 'Votre Nom — Senior Next.js Developer',
description: 'Développeur freelance Next.js, Stripe, performance front-end.',
url: 'https://votre-domaine.com',
siteName: 'Votre Nom',
locale: 'fr_FR',
type: 'website',
},
twitter: {
card: 'summary_large_image',
creator: '@votre_handle',
},
alternates: { canonical: 'https://votre-domaine.com' },
};
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="fr">
<body className="bg-white dark:bg-neutral-950 text-neutral-900 dark:text-neutral-100">
{children}
</body>
</html>
);
}
app/sitemap.ts — sitemap.xml automatique
import type { MetadataRoute } from 'next';
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: 'https://votre-domaine.com',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 1,
},
];
}
app/opengraph-image.tsx — image OG dynamique
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export const alt = 'Votre Nom — Senior Next.js Developer';
export const size = { width: 1200, height: 630 };
export const contentType = 'image/png';
export default async function Image() {
return new ImageResponse(
(
<div
style={{
background: 'linear-gradient(135deg, #0f172a 0%, #1e293b 100%)',
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
color: 'white',
fontFamily: 'system-ui',
}}
>
<div style={{ fontSize: 80, fontWeight: 700 }}>Votre Nom</div>
<div style={{ fontSize: 40, marginTop: 20, opacity: 0.8 }}>
Senior Next.js Developer
</div>
</div>
),
{ ...size }
);
}
7. Déploiement Vercel gratuit
Étape 1 — Pousser sur GitHub
git init
git add .
git commit -m "Initial portfolio commit"
git branch -M main
gh repo create mon-portfolio --public --source=. --push
# Ou créer le repo manuellement sur github.com puis :
git remote add origin https://github.com/vous/mon-portfolio.git
git push -u origin main
Étape 2 — Importer dans Vercel
- Allez sur vercel.com, connectez-vous avec GitHub
- Cliquez Add New → Project
- Sélectionnez votre repo
mon-portfolio - Vercel détecte automatiquement Next.js — laissez les paramètres par défaut
- Cliquez Deploy
En 60 secondes, votre portfolio est en ligne sur une URL *.vercel.app. Tout git push sur main redéploie automatiquement.
8. Domaine personnalisé et HTTPS
Acheter un domaine
Choisissez un domaine court, mémorisable. Préférence : votre nom ou un dérivé (ex: prenomnom.dev, prenomnom.com). Registrars fiables : Namecheap, Porkbun, OVH, Google Domains (selon disponibilité dans votre pays).
Connecter le domaine à Vercel
- Vercel Dashboard → votre projet → Settings → Domains
- Ajoutez votre domaine (
prenomnom.com) - Vercel affiche les enregistrements DNS exacts à créer chez votre registrar (un
Arecord pour l’apex et unCNAMEpourwww, ou des nameservers Vercel pour une délégation complète). Suivez les valeurs affichées par Vercel à ce moment-là — elles sont parfois mises à jour. - Une fois propagé (quelques minutes à quelques heures), HTTPS est automatique via Let’s Encrypt.
💡 Doc officielle à jour : vercel.com/docs/projects/domains
Votre portfolio est en ligne avec un domaine pro et HTTPS. Total : 1 heure de travail, 0 € de coût hors domaine (~10 €/an).
9. FAQ
Combien de projets afficher dans mon portfolio ?
3 à 6, jamais plus. Au-delà, le visiteur scanne et oublie. Choisissez ceux qui démontrent le mieux votre niche cible — pas vos plus anciens, pas tous les projets que vous avez faits.
Faut-il afficher mon CV en téléchargement ?
Optionnel. Si vous ciblez surtout des recrutements salariés, oui. Si vous ciblez des missions freelance, le CV ajoute peu — votre portfolio est votre CV.
Faut-il un blog sur le portfolio ?
Pas au démarrage. Concentrez-vous sur la conversion. Vous pourrez ajouter un blog plus tard si vous publiez régulièrement (1 article par mois minimum) — sinon il sera vu comme « abandonné ».
Combien coûte l’hébergement Vercel sur le long terme ?
L’offre Hobby (gratuite) couvre largement les besoins d’un portfolio personnel : 100 Go de bande passante, builds illimités, HTTPS, déploiement automatique. Vous n’avez besoin de l’offre Pro que si vous dépassez ces quotas (rare pour un portfolio).
Puis-je utiliser un autre framework que Next.js ?
Oui. Astro est excellent pour un portfolio purement statique. SvelteKit est très bien aussi. Le code de cet article est facilement transposable. Next.js a l’avantage d’une intégration parfaite avec Vercel et d’un écosystème très large pour les évolutions futures.
Articles liés (cluster Freelance dev en Afrique)
- 👉 Devenir freelance développeur en Afrique de l’Ouest : le guide pratique — l’article guide général
- 👉 Trouver ses 5 premiers clients tech sur Upwork depuis l’Afrique
- 👉 Se faire payer en USD/EUR depuis Dakar : Wise, Payoneer, Deel comparés
Article mis à jour le 25 avril 2026. Pour signaler une erreur ou suggérer une amélioration, écrivez-nous.