Un cours pratique pour développeurs front-end débutants
Next.js de zéro jusqu'à votre premier site statique
Vous connaissez un peu de HTML, de CSS et de JavaScript. Vous avez 14 jours. Les 6 premiers, vous apprenez Next.js avec ce cours. Le reste du temps, vous construisez et livrez le site web d'une vraie entreprise, que votre formateur vous confiera.
L'idée la plus importante de tout ce cours
Dans Next.js, les dossiers sont vos URLs. Si vous comprenez cette phrase, tout le reste du cours n'est que du détail.
Sommaire du cours
Comment utiliser ce cours
- Tapez chaque exemple de code vous-même. Pas de copier-coller. C'est en tapant que la syntaxe entre dans les doigts.
- Faites chaque exercice avant d'ouvrir la solution. Être bloqué 10 minutes apprend plus qu'une heure de lecture.
- Les cases à cocher se sauvegardent automatiquement dans votre navigateur : vous pouvez fermer cette page et reprendre plus tard.
- Suivez le planning ci-dessous. Un jour à la fois. Si vous êtes en retard d'un jour, ce n'est pas grave ; si vous êtes en retard de trois, dites-le à votre formateur.
- Bloqué plus de 15 minutes ? Chaque chapitre se termine par un bouton vert WhatsApp : il ouvre une conversation avec votre formateur, avec le chapitre déjà indiqué. Ajoutez votre question et envoyez.
Votre planning · 14 jours au total
| Jours | À faire | Vous savez que c'est bon quand... |
|---|---|---|
| 1 | Chapitres 01 + 02 : comprendre Next.js, installer les outils | node --version affiche un numéro |
| 2 | Chapitre 03 : React (prenez la journée entière, c'est la base de tout) | L'exercice 01 est fait sans regarder la solution |
| 3 | Chapitres 04 + 05 + 06 : créer le projet, les pages, la navigation | Votre site d'entraînement a 4 pages reliées entre elles |
| 4 | Chapitres 07 + 08 : layouts et style | Nav et footer partout, écrits une seule fois, et ça ressemble à un vrai site |
| 5 | Chapitres 09 + 10 : images et "use client" | Les FAQ s'ouvrent et se ferment |
| 6 | Chapitres 11 + 12 + 13 : données, métadonnées, export statique | npm run build passe sans erreur |
| 7 à 12 | Chapitre 14 : LE VRAI PROJET, le site de l'entreprise confiée par votre formateur, un jalon par jour | Chaque jalon coché avant de passer au suivant |
| 13 | Retours du formateur, corrections, finitions | Le build passe et le site est propre en largeur mobile |
| 14 | Livraison et présentation du site | Vous savez expliquer chaque fichier du projet |
Le rythme est soutenu, c'est voulu : le cours ne contient que ce dont vous aurez besoin pour le vrai projet. Rien de ce que vous lisez ici n'est optionnel.
Chapitre 01
C'est quoi Next.js, et pourquoi ça existe ?
Objectif : savoir expliquer en une phrase ce qu'est Next.js et pourquoi une équipe le choisirait plutôt que des fichiers HTML classiques.
Partons de ce que vous connaissez
Imaginez que vous construisez un site à l'ancienne : un fichier HTML par page. index.html, about.html, contact.html. Ça marche. Mais trois problèmes apparaissent très vite :
- La répétition. Votre barre de navigation et votre pied de page sont copiés dans chaque fichier. Changez un lien du menu et vous devez modifier toutes les pages. Avec 30 pages, vous en oublierez une, et le site devient incohérent.
- Pas de composants. Vous avez une belle « carte » utilisée 20 fois. En HTML pur, ce sont 20 copies du même code. Impossible de dire « voici ma Carte, réutilise-la ».
- Les données, c'est pénible. Si vos articles de menu vivent dans une liste quelque part, le HTML ne sait pas boucler dessus. Vous écrivez chaque élément à la main.
React résout ces problèmes. React est une bibliothèque JavaScript qui permet de construire une page à partir de briques réutilisables appelées composants, et de générer du HTML à partir de données. Nous apprendrons juste ce qu'il faut de React au chapitre 3.
Et Next.js dans tout ça ?
React seul n'est qu'une bibliothèque. Il ne répond pas aux questions : comment fonctionnent les URLs ? Comment avoir plusieurs pages ? Comment rendre le site rapide ? Comment le mettre sur un vrai serveur ? Avant, chaque équipe répondait elle-même à ces questions, différemment, et souvent mal.
Next.js est un framework construit au-dessus de React qui répond à toutes ces questions pour vous. Il vous donne :
| Vous avez besoin de | Next.js vous donne |
|---|---|
| Plusieurs pages avec des URLs propres | Le routing par fichiers : créez un dossier, obtenez une URL |
| Navigation et pied de page partagés | Les layouts : écrits une fois, toutes les pages en héritent |
| Un développement confortable | npm run dev avec rechargement instantané à chaque sauvegarde |
| Des pages rapides pour les visiteurs | Les pages sont pré-construites en HTML avant toute visite |
| Images, polices, métadonnées optimisées | Des composants et une configuration intégrés |
| Un moyen de livrer | Une commande produit un dossier hébergeable n'importe où |
La définition en une phrase
Next.js est un framework qui prend des composants React et les transforme en un site web complet, rapide et multi-pages, en gérant pour vous le routing, les layouts et le build.
« Statique » veut dire pré-construit
Dans ce cours, nous construisons un site statique. Statique signifie : quand vous lancez la commande de build, Next.js génère des fichiers HTML, CSS et JavaScript finis. Le navigateur du visiteur ne fait que les télécharger. Pas de base de données, pas de code serveur exécuté à chaque visite. Résultat : un site extrêmement rapide, très peu cher à héberger et difficile à pirater. C'est parfait pour les portfolios, restaurants, agences, pages vitrines et documentations.
Vérifiez-vous : votre client a un site vitrine de 25 pages et se plaint que modifier le pied de page prend une heure. Quelle fonctionnalité de Next.js règle ça ?
Vérifiez-vous : Next.js remplace-t-il React ?
Chapitre 02
Installer les outils
Objectif : une installation Node.js qui fonctionne, un éditeur de code, et de l'aisance dans le terminal.
1. Node.js
Next.js tourne sur Node.js, qui permet d'exécuter du JavaScript sur votre ordinateur et pas seulement dans un navigateur. Téléchargez la version LTS (la version stable, actuellement 22.x) sur nodejs.org et installez-la avec les options par défaut.
Ensuite, ouvrez un terminal et vérifiez :
$ node --version
v22.11.0
$ npm --version
10.9.0Si vous voyez des numéros de version (les vôtres peuvent différer légèrement), c'est bon. npm est venu automatiquement avec : c'est l'outil qui télécharge les paquets JavaScript, y compris Next.js lui-même.
2. Un éditeur de code
Prenez VS Code sur code.visualstudio.com sauf si vous avez déjà un favori. Extensions recommandées : ES7+ React snippets et Prettier (formate automatiquement le code à la sauvegarde, fini les débats sur l'indentation).
3. Kit de survie du terminal
Vous n'avez besoin que de cinq commandes pour tout ce cours :
| Commande | Ce qu'elle fait |
|---|---|
cd mon-dossier | Entrer dans un dossier (« change directory ») |
cd .. | Remonter d'un dossier |
ls (Mac/Linux) ou dir (Windows) | Lister le contenu du dossier courant |
npm run dev | Lancer le serveur de développement (vous la taperez tous les jours) |
Ctrl + C | Arrêter ce qui tourne dans le terminal |
L'erreur de débutant la plus fréquente
Lancer les commandes dans le mauvais dossier. Si npm run dev répond quelque chose comme « no such file package.json », vous n'êtes pas dans le dossier du projet. Faites d'abord cd mon-projet, puis réessayez.
Chapitre 03
React en 30 minutes
Objectif : comprendre les composants, le JSX, les props, le state et l'affichage de listes. C'est tout le React nécessaire pour ce cours.
Les composants : des fonctions qui retournent du HTML
Un composant React est simplement une fonction JavaScript dont le nom commence par une majuscule et qui retourne quelque chose qui ressemble à du HTML. Cette syntaxe retournée s'appelle le JSX.
function Welcome() {
return <h1>Bonjour l'équipe !</h1>;
}Une fois le composant créé, vous l'utilisez comme une balise HTML personnalisée : <Welcome />. C'est le super-pouvoir que le HTML n'a jamais eu : inventer vos propres balises.
JSX : cinq règles qui couvrent 95 % des cas
- Retournez un seul élément racine. S'il en faut plusieurs, enveloppez-les dans une
<div>ou dans un enveloppeur vide<> ... </>(appelé fragment). classdevientclassName, carclassest un mot réservé en JavaScript. De même,fordevienthtmlFor.- Toute balise doit se fermer.
<img>devient<img />,<br>devient<br />. - Les accolades
{ }signifient « ici, du JavaScript ». Dedans, vous pouvez mettre une variable, un calcul ou un appel de fonction. - Les commentaires dans le JSX s'écrivent
{/* comme ça */}, pas<!-- comme ça -->.
function Greeting() {
const name = "Sara";
const hour = 14;
return (
<div className="greeting">
{/* accolades = porte d'entrée vers le JavaScript */}
<h1>Bonjour, {name} !</h1>
<p>{hour < 12 ? "Bonne matinée" : "Bon après-midi"}</p>
</div>
);
}Les props : passer des données à un composant
Un composant devient vraiment réutilisable quand on peut lui passer des données, comme les balises HTML acceptent des attributs. On appelle ça les props (« properties »). Le composant les reçoit dans un objet unique, qu'on déballe en général directement :
function ProfileCard({ name, job }) {
return (
<div className="card">
<h2>{name}</h2>
<p>{job}</p>
</div>
);
}
// Utilisé trois fois, avec des données différentes :
function Team() {
return (
<section>
<ProfileCard name="Sara" job="Designer" />
<ProfileCard name="Ali" job="Développeur" />
<ProfileCard name="Lina" job="Cheffe de projet" />
</section>
);
}Un seul design de carte, écrit une fois, rempli avec des données différentes. C'est la promesse « fini le copier-coller » du chapitre 1, tenue.
Afficher une liste avec .map()
Quand vos données vivent dans un tableau, vous transformez chaque élément en JSX avec la méthode .map(). Chaque élément généré doit avoir une prop key avec une valeur unique, pour que React puisse suivre les éléments.
const team = [
{ name: "Sara", job: "Designer" },
{ name: "Ali", job: "Développeur" },
{ name: "Lina", job: "Cheffe de projet" },
];
function Team() {
return (
<section>
{team.map((person) => (
<ProfileCard key={person.name} name={person.name} job={person.job} />
))}
</section>
);
}Ajouter un membre de l'équipe, c'est désormais ajouter une ligne de données, pas copier un bloc de HTML. Relisez ce code lentement jusqu'à ce qu'il soit clair : c'est le motif que vous utiliserez le plus dans le travail réel.
Le state : des valeurs qui changent quand l'utilisateur interagit
Les props arrivent de l'extérieur et ne changent pas. Quand un composant a besoin de sa propre valeur changeante (un compteur, un menu ouvert/fermé, le texte d'un champ), il utilise le state via la fonction useState :
"use client"; // obligatoire dans Next.js, expliqué au chapitre 10
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Cliqué {count} fois
</button>
);
}Lisez-le ainsi : « donne-moi une valeur count qui démarre à 0, et une fonction setCount pour la changer ». Quand setCount s'exécute, React réaffiche le composant avec la nouvelle valeur. Vous ne touchez jamais le DOM vous-même : vous changez la donnée, React met l'écran à jour.
Penser en composants
Voir la solution
function MenuItem({ name, price }) {
return (
<li>
{name} · {price} €
</li>
);
}
const items = [
{ name: "Espresso", price: 2.5 },
{ name: "Cappuccino", price: 3.5 },
{ name: "Croissant", price: 2.0 },
];
function Menu() {
return (
<ul>
{items.map((item) => (
<MenuItem key={item.name} name={item.name} price={item.price} />
))}
</ul>
);
}Si votre version diffère un peu mais affiche trois éléments de liste, c'est correct.
Chapitre 04
Créer le projet, et visite guidée de chaque fichier
Objectif : un projet Next.js qui tourne sur votre machine, et vous savez à quoi sert chaque fichier.
Une commande crée tout
$ npx create-next-app@latest mon-premier-siteL'installateur pose quelques questions. La formulation exacte change selon les versions ; répondez avec ce tableau et vous serez aligné avec ce cours :
| Question | Réponse | Pourquoi |
|---|---|---|
| TypeScript ? | No | On apprend d'abord en JavaScript pur. TypeScript viendra plus tard dans votre carrière. |
| ESLint / linter ? | Yes | Il vous signale les erreurs pendant que vous tapez. |
| Tailwind CSS ? | No | On apprend d'abord le vrai CSS pour comprendre ce que fait n'importe quel outil en dessous. |
Dossier src/ ? | No | Moins de dossiers à gérer mentalement. |
| App Router ? | Yes | La méthode moderne. Tout ce cours l'utilise. |
| Turbopack ? | Yes | Serveur de dev plus rapide. Acceptez le défaut. |
| Import alias ? | No | Gardez le défaut. |
Puis lancez le serveur de développement :
$ cd mon-premier-site
$ npm run dev
▲ Next.js
- Local: http://localhost:3000Ouvrez http://localhost:3000 dans votre navigateur. Vous devriez voir la page d'accueil de Next.js. localhost:3000 signifie « un site servi par mon propre ordinateur, sur le port 3000 ». Vous seul pouvez le voir. Laissez ce terminal tourner pendant que vous travaillez ; faites Ctrl + C pour l'arrêter.
Visite du projet
Deux fichiers comptent aujourd'hui. D'abord, app/page.js est votre page d'accueil. Une page n'est qu'un composant React exporté par défaut :
export default function Home() {
return (
<main>
<h1>Mon premier site Next.js</h1>
<p>Il est vivant !</p>
</main>
);
}Sauvegardez le fichier et regardez le navigateur : il se met à jour instantanément, sans que vous rafraîchissiez. C'est le rechargement à chaud (hot reload), et c'est pour ça que le serveur de dev reste allumé.
Ensuite, app/layout.js est le cadre autour de chaque page. Remarquez qu'il affiche {children} ; c'est là que le contenu de chaque page apparaît. Nous le travaillerons sérieusement au chapitre 7.
Le rythme quotidien
Chaque session de travail à partir de maintenant, c'est : ouvrir le dossier du projet dans VS Code, ouvrir le terminal, lancer npm run dev, modifier des fichiers, regarder le navigateur se mettre à jour. C'est tout le workflow.
Faites-en le vôtre
Chapitre 05
Pages et routing : les dossiers deviennent des URLs
Objectif : créer de nouvelles pages et prédire exactement quelle URL chaque fichier obtiendra.
La règle
Souvenez-vous du schéma en haut de ce cours. Voici la règle complète :
La règle du routing
Dans app/, chaque dossier devient un segment d'URL, et le fichier page.js du dossier est ce que les visiteurs voient à cette URL. Pas de page.js dans un dossier = pas de page à cette URL.
Donc pour créer une page « À propos » à l'adresse /about, vous créez un dossier app/about/ contenant un fichier page.js :
export default function AboutPage() {
return (
<main>
<h1>À propos de nous</h1>
<p>Nous sommes une petite équipe qui aime le web.</p>
</main>
);
}Sauvegardez, puis visitez localhost:3000/about. C'est tout. Aucun fichier de configuration, aucun enregistrement de route. La structure des dossiers est la configuration.
Les dossiers s'imbriquent, et les URLs aussi : app/services/design/page.js est servi à /services/design.
Cliquez sur un fichier. Le faux navigateur montre l'URL qu'il créerait.
Les noms de fichiers spéciaux dans app/
Next.js réserve quelques noms de fichiers. Chacun a un seul rôle :
| Fichier | Rôle |
|---|---|
page.js | Le contenu d'une page. Obligatoire pour que l'URL existe. |
layout.js | Le cadre partagé autour des pages (chapitre 7). |
not-found.js | Votre page 404 personnalisée. |
Il en existe d'autres (loading.js, error.js...), mais ces trois-là suffisent pour tout ce cours. Tout fichier portant un autre nom (comme hero.js ou data.js) est ignoré par le routeur : pas de risque de créer une URL par accident.
Faites grandir le site à quatre pages
Voir la solution
Chaque page.js est un petit composant exporté par défaut, comme l'exemple « À propos » ci-dessus.
Chapitre 06
Naviguer avec <Link>
Objectif : relier vos pages avec une navigation rapide, digne d'une application.
Vous pourriez relier les pages avec une balise <a href="/about"> classique, et ça marcherait. Mais un <a> brut force le navigateur à jeter toute la page et à retélécharger la suivante de zéro : écran blanc, lenteur.
Next.js fournit à la place un composant <Link>. Il ressemble à un lien et se comporte comme un lien (clic droit, ouvrir dans un nouvel onglet, suivi par les moteurs de recherche), mais Next.js remplace le contenu de la page sans rechargement complet, et pré-charge même les pages que le visiteur va probablement ouvrir. Même HTML en dessous, expérience bien plus rapide.
import Link from "next/link";
export default function Home() {
return (
<main>
<h1>Mon premier site Next.js</h1>
<p>
En savoir plus <Link href="/about">sur nous</Link>.
</p>
</main>
);
}Lire la ligne d'import
import Link from "next/link" signifie : « apporte le composant Link du paquet Next.js dans ce fichier ». Tout composant ou fonction venant d'un autre fichier doit être importé en haut. Si vous oubliez, l'erreur dit « Link is not defined » : ce message est votre rappel.
La règle pratique : <Link> pour les pages internes à votre site, un <a> normal pour les sites externes (comme un lien vers Instagram).
Un composant de navigation
Une barre de navigation est le composant personnalisé idéal pour commencer. Créez un dossier components/ à la racine du projet (à côté de app/, pas dedans) pour ranger les briques réutilisables :
import Link from "next/link";
export default function Nav() {
return (
<nav>
<Link href="/">Accueil</Link>
<Link href="/about">À propos</Link>
<Link href="/contact">Contact</Link>
</nav>
);
}Et utilisez-le dans une page. Comme Nav.js est notre propre fichier (pas un paquet), le chemin d'import commence par des points qui décrivent où est le fichier par rapport au fichier courant :
import Nav from "../components/Nav";
export default function Home() {
return (
<main>
<Nav />
<h1>Mon premier site Next.js</h1>
</main>
);
}../ signifie « remonte d'un dossier » : de app/ vers la racine du projet, puis dans components/. Se tromper de chemin d'import est l'erreur de débutant numéro un ; quand ça arrive, le message d'erreur nomme le chemin introuvable, alors vérifiez d'abord les points.
Mais attendez : faut-il maintenant importer <Nav /> dans chaque page ? Ce serait à nouveau le problème du copier-coller. Non. Le chapitre suivant le règle proprement.
Branchez tout
Chapitre 07
Les layouts : construire le cadre une seule fois
Objectif : un en-tête et un pied de page partagés sur chaque page, écrits exactement une fois.
Ouvrez app/layout.js. Simplifié, il ressemble à ceci :
import "./globals.css";
export const metadata = {
title: "Mon premier site",
description: "Construit en apprenant Next.js",
};
export default function RootLayout({ children }) {
return (
<html lang="fr">
<body>{children}</body>
</html>
);
}Voici le modèle mental. Le layout est un cadre de tableau ; chaque page est le tableau. Quand quelqu'un visite /about, Next.js prend le layout et insère la page À propos exactement là où se trouve {children}. Visitez /contact, et le même cadre reçoit la page Contact à la place.
children est une prop que React remplit automatiquement avec ce qui est imbriqué à l'intérieur. Vous ne l'appelez jamais vous-même ; vous marquez seulement sa place.
Mettez la nav et le footer dans le cadre
import "./globals.css";
import Nav from "../components/Nav";
export const metadata = {
title: "Mon premier site",
description: "Construit en apprenant Next.js",
};
export default function RootLayout({ children }) {
return (
<html lang="fr">
<body>
<Nav />
{children}
<footer>© 2026 Mon premier site</footer>
</body>
</html>
);
}Supprimez maintenant <Nav /> (et son import) de votre page d'accueil : sinon il apparaîtrait deux fois. Naviguez dans le site. Chaque page a la nav et le footer, et aucun fichier de page ne les mentionne. C'est la solution au problème du copier-coller du chapitre 1. La mise à jour du footer sur 25 pages qui prenait une heure est devenue une modification d'une ligne.
Un dernier fait à retenir : le layout racine est le seul endroit de toute l'application avec les balises <html> et <body>. Les pages ne les incluent jamais.
Vérifiez-vous : vous voulez ajouter une bannière « Fermé en août » visible sur toutes les pages. Dans quel fichier l'écrivez-vous ?
app/layout.js, juste au-dessus de {children}. Une seule modification, toutes les pages l'affichent. Si vous avez pensé « dans chaque page », relisez ce chapitre.Un cadre pour tout
Chapitre 08
Le style : CSS global et CSS Modules
Objectif : savoir où vont les styles de tout le site, où vont les styles d'un composant, et pourquoi les deux sont séparés.
Le CSS global : les règles de tout le site
app/globals.css est déjà importé par votre layout racine, donc tout ce qu'il contient s'applique partout. C'est le bon endroit pour les fondations : polices, couleur de fond, couleur des liens, resets. Remplacez son contenu par quelque chose de petit et lisible :
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: #1f2933;
background: #ffffff;
}
main {
max-width: 720px;
margin: 0 auto;
padding: 24px;
}Les CSS Modules : des styles qui ne peuvent pas fuir
Voici un accident d'équipe classique : vous écrivez .card { padding: 20px } pour le menu, et un mois plus tard un collègue nomme autre chose .card sur la page contact. Les styles entrent en collision et une page casse mystérieusement.
Les CSS Modules empêchent ça. Nommez un fichier Quelquechose.module.css et Next.js rend chaque classe privée au composant qui l'importe, en renommant les classes en coulisses en quelque chose d'unique comme Nav_card__x7Kd2. Deux fichiers peuvent utiliser .card sans jamais se gêner.
.nav {
display: flex;
gap: 24px;
padding: 16px 24px;
border-bottom: 1px solid #e2e8f0;
}
.nav a {
text-decoration: none;
color: #1f2933;
font-weight: 600;
}
.nav a:hover {
color: #0e7c5b;
}import Link from "next/link";
import styles from "./Nav.module.css";
export default function Nav() {
return (
<nav className={styles.nav}>
<Link href="/">Accueil</Link>
<Link href="/about">À propos</Link>
<Link href="/contact">Contact</Link>
</nav>
);
}Lisez le motif : on importe la feuille de style comme un objet appelé styles, puis on écrit className={styles.nav}. Le nom de classe vient du JavaScript (d'où les accolades), et il correspond à la règle .nav du fichier module.
La règle d'équipe
CSS global pour les fondations qui s'appliquent partout (polices, couleurs, resets). Un CSS Module à côté de chaque composant pour son apparence propre. Dans le doute, choisissez le module : les styles qui fuient causent les bugs les plus déroutants dans les projets d'équipe.
Donnez-lui un vrai look
Chapitre 09
Les images et le dossier public/
Objectif : ajouter des images au site de la bonne façon, celle de Next.js.
Le dossier public/
Tout ce que vous mettez dans public/ est servi depuis la racine de votre site, tel quel. Un fichier public/logo.png est accessible dans le navigateur à /logo.png. Notez que l'URL n'inclut pas le mot « public ».
Le composant <Image>
Vous pourriez utiliser une balise <img> classique, mais Next.js fournit un composant <Image> amélioré qui charge les images paresseusement (elles ne se téléchargent qu'en arrivant à l'écran) et empêche la page de sauter pendant le chargement. Ce saut est un vrai problème de référencement et d'ergonomie appelé « layout shift », et c'est pourquoi width et height sont obligatoires : ils réservent l'espace à l'avance.
import Image from "next/image";
export default function AboutPage() {
return (
<main>
<h1>À propos de nous</h1>
<Image
src="/images/team.jpg"
alt="Notre équipe devant le bureau"
width={720}
height={480}
/>
</main>
);
}srccommence par/et c'est le chemin danspublic/.altdécrit l'image pour les visiteurs non-voyants et pour les moteurs de recherche. Écrivez-le comme si vous décriviez la photo au téléphone. Image purement décorative ? Utilisezalt="".widthetheightsont des nombres entre accolades (des nombres JavaScript, pas des chaînes). Respectez les vraies proportions de l'image.
À retenir pour le chapitre 13
Sur un serveur classique, <Image> redimensionne et compresse aussi les images à la volée. Un export statique n'a pas de serveur, donc au chapitre 13 nous désactiverons cette seule fonctionnalité avec une ligne de configuration. Tout le reste de <Image> continue de fonctionner.
Ajoutez de vraies images
Chapitre 10
Composants Server et Client
Objectif : savoir quand un fichier a besoin de "use client" en première ligne, et pourquoi la plupart n'en ont pas besoin.
Chaque composant du dossier app/ est, par défaut, un Server Component : Next.js le transforme en HTML fini à l'avance. Ce HTML est léger et instantané pour le visiteur. Toutes les pages que vous avez construites jusqu'ici sont des Server Components, et c'est exactement ce qu'il faut pour un site statique.
Mais certaines choses ne peuvent se passer que dans le navigateur du visiteur : réagir aux clics, mémoriser un état, lire la taille de la fenêtre. Un composant qui fait cela doit être un Client Component, et on le marque en écrivant une ligne tout en haut du fichier :
"use client";
import { useState } from "react";
export default function FaqItem({ question, answer }) {
const [open, setOpen] = useState(false);
return (
<div>
<button onClick={() => setOpen(!open)}>{question}</button>
{open && <p>{answer}</p>}
</div>
);
}Deux nouveautés dans ce code : setOpen(!open) bascule la valeur entre vrai et faux, et {open && <p>...</p>} signifie « n'affiche ce paragraphe que quand open est vrai ».
La décision est mécanique
| Le composant... | Type | Marqueur |
|---|---|---|
| affiche du texte, des images, des liens, des listes de données | Server (défaut) | rien |
utilise useState, useEffect, ou un onClick / onChange | Client | "use client" en ligne 1 |
utilise des choses du navigateur comme window ou localStorage | Client | "use client" en ligne 1 |
En pratique, vous n'avez même pas à mémoriser ce tableau : si vous utilisez useState dans un fichier sans le marqueur, Next.js s'arrête avec une erreur qui vous dit littéralement d'ajouter "use client". Lisez les erreurs ; ce sont généralement des instructions.
Gardez l'ambre petit
Le bon style Next.js : garder les pages en Server Components et ne rendre « client » que la petite pièce interactive. La page À propos reste rendue côté serveur ; seul le petit FaqItem à l'intérieur porte "use client". Ne collez jamais "use client" en haut de chaque fichier « au cas où » : vous jetteriez la vitesse que Next.js vous offre gratuitement.
Et oui, les Client Components fonctionnent dans notre export statique. Leur HTML est pré-construit comme tout le reste, et leur JavaScript s'exécute dans le navigateur du visiteur pour les rendre interactifs.
Vérifiez-vous : un Footer qui affiche l'année, et un menu hamburger mobile qui s'ouvre au toucher. Lequel a besoin de "use client" ?
useState et onClick. Le footer ne fait qu'afficher du contenu, il reste un Server Component sans marqueur.Votre premier composant interactif
Voir la solution du bonus
<button onClick={() => setOpen(!open)}>
{open ? "-" : "+"} {question}
</button>Le motif condition ? a : b choisit entre deux valeurs. C'est le même que dans l'exemple Greeting du chapitre 3.
Chapitre 11
Des données à l'interface
Objectif : garder le contenu dans un fichier de données et l'afficher avec des composants, comme sont construits les vrais sites.
Les vrais sites séparent le contenu de la présentation. Les prix du menu vivent dans un fichier de données ; les composants décident de leur apparence. Quand le client dit « le cappuccino passe à 4 euros », vous changez un nombre, pas du HTML.
Créez un dossier de données à la racine du projet :
export const menuItems = [
{ id: 1, name: "Espresso", price: 2.5, desc: "Court et corsé." },
{ id: 2, name: "Cappuccino", price: 3.5, desc: "Le classique crémeux." },
{ id: 3, name: "Flat White", price: 3.8, desc: "Soyeux et doux." },
{ id: 4, name: "Croissant", price: 2.0, desc: "Cuit chaque matin." },
];Notez que c'est un export nommé (pas de default). Un fichier peut avoir plusieurs exports nommés, et on les importe avec des accolades portant le nom exact.
Maintenant, un composant carte et une page qui combine tout ce que vous avez appris :
import styles from "./MenuCard.module.css";
export default function MenuCard({ name, price, desc }) {
return (
<article className={styles.card}>
<div className={styles.top}>
<h3>{name}</h3>
<span className={styles.price}>{price.toFixed(2)} €</span>
</div>
<p>{desc}</p>
</article>
);
}import { menuItems } from "../../data/menu";
import MenuCard from "../../components/MenuCard";
export default function MenuPage() {
return (
<main>
<h1>Notre carte</h1>
{menuItems.map((item) => (
<MenuCard
key={item.id}
name={item.name}
price={item.price}
desc={item.desc}
/>
))}
</main>
);
}Racontez le flux à voix haute, c'est la boucle centrale du front-end moderne : fichier de données → import du tableau → .map() dessus → un composant par élément → les props remplissent le composant. Chaque grille de produits, page d'équipe ou tableau de prix que vous construirez un jour est ce même motif avec un autre CSS.
Pourquoi key={item.id} ?
React a besoin d'une identité stable pour chaque élément d'une liste, afin de mettre à jour le bon quand les données changent. Utilisez un id venant des données. Évitez l'index du tableau comme key ; il se comporte mal quand les éléments sont réordonnés ou supprimés.
La page pilotée par les données
Chapitre 12
Les métadonnées : titres, descriptions et l'onglet du navigateur
Objectif : donner à chaque page son propre titre et sa description, que Google et les réseaux sociaux lisent.
Les métadonnées sont des informations sur la page : le titre dans l'onglet du navigateur, la description que Google affiche sous un résultat de recherche. Dans Next.js, vous n'écrivez jamais de balises <head> à la main ; vous exportez un objet metadata et Next.js génère les balises.
Vous avez déjà des métadonnées pour tout le site dans app/layout.js. Chaque page peut exporter les siennes, qui remplacent celles du layout pour cette page :
export const metadata = {
title: "Notre carte | Le Petit Café",
description: "Espresso, cappuccino et viennoiseries fraîches au cœur de la ville.",
};
export default function MenuPage() {
// ...identique à avant
}Les règles pratiques dont vos futurs collègues SEO vous remercieront :
- Chaque page a un titre unique, au format
Nom de la page | Nom du site. - La description est une phrase honnête et précise. C'est votre publicité dans les résultats de recherche.
Nommez chaque page
Chapitre 13
L'export statique : transformer le projet en un dossier de fichiers
Objectif : compiler le site en fichiers HTML/CSS/JS purs, hébergeables n'importe où.
Un seul changement de configuration
Dites à Next.js que vous voulez un export statique. Ouvrez next.config.mjs et ajoutez deux réglages :
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "export",
images: { unoptimized: true },
};
export default nextConfig;output: "export"signifie : au moment du build, génère un dossier de fichiers statiques finis.images: { unoptimized: true }, c'est la promesse du chapitre 9 : le redimensionnement d'images à la volée exige un serveur, un site statique n'en a pas, donc on désactive cette seule fonctionnalité.
Compilez
$ npm run build
Route (app)
┌ ○ /
├ ○ /about
├ ○ /contact
└ ○ /menu
○ (Static) prerendered as static contentChaque cercle ○ (Static) est une page pré-construite en HTML. Le résultat atterrit dans un nouveau dossier appelé out/ :
Ouvrez out/about.html dans votre éditeur et regardez-le. C'est du vrai HTML fini contenant votre texte. Voilà ce que « statique » voulait dire au chapitre 1 : le travail s'est fait sur votre machine au moment du build, le navigateur du visiteur reçoit des fichiers instantanés.
Prévisualiser et héberger
Pour prévisualiser le site compilé en local :
$ npx serve outPour le mettre sur Internet, envoyez le contenu de out/ sur n'importe quel hébergeur statique. Options gratuites : glissez le dossier sur netlify.com/drop, ou poussez le projet sur GitHub et importez-le dans Vercel ou Cloudflare Pages (ils lancent npm run build pour vous à chaque push). Aucun serveur à gérer, rien à maintenir, rien à se faire pirater à 3 h du matin.
Ce qu'un export statique ne peut pas faire
Pas de système de connexion, pas d'écriture en base de données, pas de traitement de formulaire sur votre propre serveur (les formulaires passent par un service externe comme Formspree, ou une fonctionnalité de l'hébergeur comme Netlify Forms). Quand un projet a besoin de tout ça, on déploie la même application Next.js sur un serveur Node au lieu de l'exporter, et on débloque ses fonctionnalités serveur. Même framework, monde plus grand : c'est un cours pour plus tard.
Livrez le site d'entraînement
Chapitre 14 · Le vrai projet
Construisez le site d'une vraie entreprise
Objectif : livrer seul un site statique complet pour un vrai client, du dossier vide jusqu'au build exporté. C'est votre livrable de fin de stage.
Ici, on ne s'entraîne plus. Votre formateur vous remet le brief d'une vraie entreprise : son nom, son activité, ses textes, son logo et ses photos. Votre travail des jours 7 à 12 est de transformer ce contenu en site web fini, en appliquant exactement ce que vous avez appris. Construisez-le de zéro dans un nouveau projet (ne réutilisez pas le projet d'entraînement ; repartir d'une page blanche fait partie du métier). Essayez de travailler sans relire les chapitres, et traitez-les comme votre documentation quand vous bloquez.
Les pages attendues
Le contenu exact vient du brief de votre formateur, mais un site d'entreprise suit presque toujours ce plan. Adaptez les noms si le brief le demande :
| Page | URL | Doit contenir |
|---|---|---|
| Accueil | / | Grand titre avec le nom de l'entreprise, une photo, un court texte de présentation, un Link stylé en bouton vers les services |
| Services | /services | Les services ou produits de l'entreprise issus d'un fichier de données via .map(), chacun en carte stylée |
| À propos | /about | L'histoire de l'entreprise, une section équipe depuis un fichier de données, et 3 questions FAQ qui s'ouvrent et se ferment |
| Contact | /contact | Adresse, horaires (depuis un fichier de données), e-mail, et un lien externe vers une carte |
Exigences pour tout le site (c'est sur ça que vous serez évalués) :
- Nav et footer sur chaque page, via le layout racine, jamais répétés dans un fichier de page.
- Chaque composant stylé avec son propre CSS Module ; seulement les fondations dans
globals.css. - Chaque image via
<Image>avec un vrai textealt. - Des
metadatauniques sur chaque page. - Exactement un fichier dans tout le projet contient
"use client"(l'élément FAQ). - Le build passe avec
npm run buildet le site fonctionne servi depuisout/.
Structure de projet suggérée
Un jalon par jour
Les professionnels ne construisent pas tout d'un coup. Un jalon par jour, vérifié dans le navigateur avant de passer au suivant. Si un jalon est fini en avance, prenez de l'avance sur le suivant. Cochez au fur et à mesure :
Du dossier vide au site livré
Objectifs bonus, seulement si vous finissez en avance
- Ajoutez une page 404 personnalisée avec
app/not-found.js. - Groupez les services par catégorie - indice : deux tableaux, ou
.filter()avant.map().
Comment votre formateur évaluera le projet
Pas au pixel près. Les questions de la revue sont : le layout est-il écrit une seule fois ? Le contenu est-il dans des fichiers de données ? Les styles sont-ils dans des modules ? "use client" est-il utilisé exactement une fois et au bon endroit ? Le build passe-t-il ? Ces cinq réponses montrent si vous pensez en Next.js.
Annexe A
Anti-sèche
Commandes
npx create-next-app@latest nomnouveau projetnpm run devdévelopper sur localhost:3000npm run buildcompiler pour la productionnpx serve outprévisualiser l'export statiqueCtrl + Carrêter le serveur
Routing
- Dossier dans
app/= segment d'URL page.js= la page à cette URLlayout.js= cadre partagé, affiche{children}not-found.js= 404 personnalisée
Imports quotidiens
import Link from "next/link"import Image from "next/image"import { useState } from "react"import styles from "./X.module.css"
Pièges du JSX
className, pasclass- Un seul élément racine par return (ou
<>...</>) - Fermez chaque balise :
<Image /> { }= du JavaScript dans le balisagekeysur chaque élément d'un.map()
Server vs Client
- Défaut = Server Component (rapide, statique)
- Clics ou state ?
"use client"en ligne 1 - Gardez les composants client petits et bas dans l'arbre
Export statique
output: "export"dans next.config.mjsimages: { unoptimized: true }- Résultat dans
out/, hébergeable partout
Annexe B
Les erreurs courantes, décodées
| L'erreur dit | Ça veut dire | Solution |
|---|---|---|
| « npm: command not found » | Node.js n'est pas installé, ou le terminal était ouvert pendant l'installation | Installez Node LTS, puis ouvrez un nouveau terminal |
| « Could not read package.json » | Vous êtes dans le mauvais dossier | Faites cd vers le dossier du projet d'abord |
| « X is not defined » | Vous utilisez un composant ou une fonction sans l'importer | Ajoutez la ligne import en haut |
| « Module not found: Can't resolve '../components/Nav' » | Le chemin d'import ou le nom du fichier est faux | Comptez les sauts ../ ; vérifiez l'orthographe et les majuscules |
| « You're importing a component that needs useState... » | Du state ou des événements dans un Server Component | Ajoutez "use client" en ligne 1 de ce fichier |
| « Adjacent JSX elements must be wrapped... » | Votre return a deux éléments racines | Enveloppez-les dans une <div> ou <>...</> |
| « Each child in a list should have a unique 'key' prop » | Un .map() sans keys | Ajoutez key={item.id} à l'élément mappé le plus externe |
| La page affiche 404 alors que le dossier existe | Le fichier à l'intérieur ne s'appelle pas exactement page.js | Renommez-le ; seul page.js crée une URL |
| L'image affiche une icône cassée | Mauvais chemin dans src | Le chemin part de public/ : le fichier public/images/a.jpg devient src="/images/a.jpg" |
| « Port 3000 already in use » | Un ancien serveur de dev tourne encore | Retrouvez ce terminal et faites Ctrl + C, ou acceptez le port 3001 proposé |
Méthode générale de débogage : lisez la première erreur (les suivantes ne sont souvent que ses échos), notez le nom de fichier et le numéro de ligne mentionnés, et relisez exactement cette ligne. Neuf fois sur dix, c'est une faute de frappe, un import manquant ou une balise non fermée.
Annexe C
Glossaire
- Composant
- Une fonction JavaScript avec une majuscule qui retourne du JSX. La brique de base réutilisable de React.
- JSX
- La syntaxe qui ressemble à du HTML dans les composants. Les accolades y insèrent du JavaScript.
- Props
- Des données passées à un composant comme des attributs HTML, pour le réutiliser avec des contenus différents.
- State
- La valeur changeante propre à un composant, créée avec
useState. La modifier réaffiche le composant. - App Router
- Le système de routing de Next.js où les dossiers de
app/définissent les URLs. - Layout
- Un cadre partagé autour des pages. Affiche chaque page là où il écrit
{children}. - Server Component
- Le défaut. Rendu en HTML à l'avance ; aucune interactivité propre.
- Client Component
- Un composant marqué
"use client"dont le JavaScript s'exécute dans le navigateur pour l'interactivité. - CSS Module
- Un fichier
.module.cssdont les classes sont privées au composant qui l'importe. - Hot reload
- Le serveur de dev qui met le navigateur à jour instantanément quand vous sauvegardez.
- Export statique
- La compilation du site entier en fichiers purs dans
out/, hébergeables sur n'importe quel hébergeur statique. - Build
- Le processus (
npm run build) qui transforme votre code source en fichiers de production optimisés. - localhost:3000
- Votre propre ordinateur qui sert le site pendant le développement. Visible par vous seul.
- npm
- Le gestionnaire de paquets qui installe les bibliothèques et lance les scripts du projet.