Skip to Content
BootstrapPartie 14 — Projets guidésProjet 5 — App Next.js (Niv. 5)

Projet 5 — App Next.js (Niv. ⭐⭐⭐⭐⭐)

⏱️ TL;DR — Le capstone : une petite app Next.js (App Router) avec react-bootstrap, votre thème Sass du projet 4, un dark mode via next-themes, une navbar, une liste de données en cartes, une modale de détail et un formulaire contrôlé validé. Objectif : intégrer proprement Bootstrap dans un vrai projet React moderne.

🎯 Cahier des charges

  1. Setup : Next.js App Router + bootstrap + react-bootstrap + sass + next-themes.
  2. Thème : importer votre bootstrap-custom.scss (projet 4) dans app/layout.js.
  3. Dark mode : ThemeProvider de next-themes avec attribute="data-bs-theme" + un toggle.
  4. Navbar : composant client react-bootstrap.
  5. Liste : des données affichées en cartes (grille responsive), chargées côté serveur.
  6. Détail : une modale react-bootstrap ouverte au clic sur une carte.
  7. Formulaire : un formulaire contrôlé avec validation (état + is-invalid).

🔍 Endroits à visiter

BesoinChapitre
Pourquoi pas le JS natif11.1
react-bootstrap11.2
Intégration App Router11.3
Choix Bootstrap vs autre11.4
Thème SassProjet 4
Validation en React6.5

Jalons

  • Le CSS/Sass est importé dans le layout serveur (pas d’erreur window).
  • Le dark mode persiste et ne « flashe » pas au chargement.
  • La navbar est un composant 'use client'.
  • La modale de détail s’ouvre via une prop show (aucun data-bs-*).
  • Le formulaire affiche les erreurs par l’état, pas par le DOM.

💡 Indice d’arborescence

app/ ├── layout.js // import du scss + <Providers> ├── providers.jsx // 'use client' : ThemeProvider next-themes ├── page.jsx // liste (server) qui rend <ProductGrid data={…} /> └── components/ ├── SiteNav.jsx // 'use client' : react-bootstrap Navbar ├── ThemeToggle.jsx // 'use client' : useTheme() ├── ProductGrid.jsx // 'use client' : cartes + Modal détail └── ContactForm.jsx // 'use client' : formulaire contrôlé
// layout.js (extrait) import './bootstrap-custom.scss' import { Providers } from './providers' export default function RootLayout({ children }) { return ( <html lang="fr" suppressHydrationWarning> <body><Providers>{children}</Providers></body> </html> ) }

Pour aller plus loin

  • Ajoutez une route dynamique /produits/[id] avec un vrai fetch.
  • Déployez sur Vercel et vérifiez le poids (purge + tree-shaking, 13.1).
  • Comparez l’effort avec une version Tailwind + shadcn/ui (11.4).

🎉 Bravo ! Vous avez terminé les projets. Testez maintenant vos connaissances : Partie 15 — Quiz (1000 questions).