Ajout page détail produit avec SEO sur React Router 7

Crée une fiche produit avec Markdown, meta SEO, JSON-LD et breadcrumb sous React Router 7. Améliore l’indexation et l’UX de ton appli.

4 min read
Déverrouillez votre potentiel

avec React Router 7

Vous en avez marre de...

❌ perdre du temps à chercher des informations éparpillées
❌ ne pas avoir de retour sur votre progression
Assistant IA spécialisé

Posez vos questions 24/7 à notre IA experte en React Router 7

Quiz interactifs

Validez vos acquis avec des quiz personnalisés et un feedback instantané

9 modules
72 leçons
Accès à vie
299.49
-35%

Objectif de la leçon

Nous transformons la liste de robots humanoïdes en véritables fiches produit :

  1. migration Prisma pour ajouter content (Markdown) au modèle Product;
  2. seed refactorisé avec des robots plus fun ;
  3. route dynamique /products/:slug ;
  4. affichage SEO : balises meta + JSON-LD Product et breadcrumb;
  5. rendu Markdown SSR avec Tailwind Typography.

Tu suis ? On code ! 🚀


1 Migration : champ content dans Product

prisma/schema.prisma
1
model Product {
2
id String @id @default(uuid())
3
name String
4
slug String @unique
5
description String?
6
content String? // ^? contenu Markdown pour le SEO
7
priceCents Int
8
stock Int @default(0)
9
isActive Boolean @default(true)
10
/* … */
11
}
Terminal
1
npx prisma migrate dev --name add-product-content

Explication : le champ content stocke un texte Markdown riche (titres, tableaux, listes). Le SEO adore : un seul H1 (le name), et le reste en H2/H3.


2 Nouveau seed plein d’humour

prisma/seed.ts
1
/* … */
2
await prisma.product.create({
3
data: {
4
name: "Chef Gordon 2",
5
slug: "chef-gordon-2",
6
description: "Le robot cuistot étoilé !",
7
content: md`
8
### Fonctionnalités principales
9
| Tâche | Temps moyen |
10
| ----- | ----------- |
11
| Émincer un oignon | 2 s |
12
| Nettoyer le plan de travail | 5 s |
13
14
> *Parce que « C’est trop cuit ! » n’existe plus.*
15
`,
16
priceCents: 799000,
17
stock: 12,
18
},
19
});
Terminal
1
npx prisma db seed

Pourquoi ? • descriptions longues → longue traîne SEO ; • Markdown = mise en page simple côté rédacteur.


3 Route dynamique products.$productSlug.tsx

Loader serveur

app/routes/products.$productSlug.tsx
1
import { getProduct } from "~/server/products.server";
2
3
export async function loader({ params }) {
4
const { product, productImages } = await getProduct({
5
productSlug: params.productSlug,
6
});
7
if (!product)
8
throw new Response("Produit introuvable", { status: 404 });
9
return { product, productImages };
10
}

Rappel : getProduct renvoie { product, productImages } – si aucune image en base, on génère trois placeholders Picsum.

Balises meta + JSON-LD

app/routes/products.$productSlug.tsx
1
import { generateMeta } from "@forge42/seo-tools/remix/metadata";
2
import { product as productLD } from "@forge42/seo-tools/structured-data/product";
3
import { breadcrumbs } from "@forge42/seo-tools/structured-data/breadcrumb";
4
5
export const meta = ({ loaderData, location }) =>
6
generateMeta(
7
{
8
title: loaderData.product.name,
9
description: loaderData.product.description ?? "",
10
image: loaderData.productImages[0].url,
11
url: `https://localhost:5173${location.pathname}`,
12
},
13
[
14
{ "script:ld+json": productLD(/* …données produit… */) },
15
{ "script:ld+json": breadcrumbs(location.pathname, ["Accueil", "Collection", loaderData.product.name]) },
16
],
17
);

Explication : generateMeta écrit <title>, <meta> et injecte deux scripts JSON-LD : Product (prix, stock) + breadcrumb (meilleure navigation pour Google).

Page React

app/routes/products.$productSlug.tsx {75,91}
1
<div className="prose">
2
<Markdown remarkPlugins={[remarkGfm]}>
3
{product.content}
4
</Markdown>
5
</div>

Pourquoi react-markdown ? • SSR immédiat : le contenu est déjà HTML dans la réponse ; • remark-gfm ajoute tableaux + todo-list GitHub style.

Tailwind Typography

Terminal
1
npm i @tailwindcss/typography
app.css
1
@plugin "@tailwindcss/typography";

Ensuite la classe prose gère couleurs, tailles et espacements.


4 Breadcrumb + design responsive

Cardinalité :

  • Desktop : image 4/3, H1 + price + bouton.
  • Mobile : images avant le titre, burger menu reste utilisable.
app/routes/products.$productSlug.tsx {26-36}
1
<nav aria-label="Breadcrumb" className="mb-8 text-sm">
2
<Link to="/" className="text-gray-500 hover:text-black">Accueil</Link>
3
<ChevronRight className="inline h-4 w-4 mx-1 text-gray-400" />
4
<Link to="/products" className="text-gray-500 hover:text-black">Collection</Link>
5
<ChevronRight className="inline h-4 w-4 mx-1 text-gray-400" />
6
<span className="text-gray-900">{product.name}</span>
7
</nav>

5 Tester : extension Meta SEO Inspector

  1. F12 → Onglet Elements : <title>Chef Gordon 2…</title> + meta OK.
  2. Meta SEO Inspector : image OG, JSON-LD Product, breadcrumb valides.
  3. Schema Markup Validator : 0 erreur, 0 warning.

6 Commit & pull-request

Terminal
1
git add .
2
git commit -m "feat(product): page détail avec markdown & SEO"
3
git push -u origin 7-5-ajout-de-la-page-detail-du-produit

Merge ; la CI rebuild → staging → prod. Ton robot est en ligne, optimisé et indexable 🔥


À retenir

  • Slug unique = URL lisible + clé pour findUnique.
  • Champ content Markdown + react-markdown = rédaction libre, rendu SSR.
  • generateMeta + JSON-LD = SEO complet sans duplicate code.
  • Breadcrumb améliore UX et rich snippet.
  • Tailwind Typography → typographie propre en une classe.

Prochaine étape : dashboard admin pour gérer ces robots. À tout de suite !

Premium
Quiz interactif
Testez vos connaissances et validez votre compréhension du module avec notre quiz interactif.
1

Comprendre les concepts fondamentaux

Quelle est la principale différence entre les composants client et serveur dans React ?

Les composants client s'exécutent uniquement dans le navigateur
Les composants serveur peuvent utiliser useState
Les composants client sont plus rapides
Il n'y a aucune différence significative
2

Optimisation des performances

Quelle technique est recommandée pour éviter les rendus inutiles dans React ?

Utiliser React.memo pour les composants fonctionnels
Ajouter plus d'états locaux
Éviter d'utiliser les props
Toujours utiliser les class components
3

Architecture des données

Quel hook permet de gérer les effets de bord dans un composant React ?

useEffect
useState
useMemo
useContext
4

Gestion des erreurs

Comment implémenter la gestion des erreurs pour les requêtes API dans React ?

Utiliser try/catch avec async/await
Ignorer les erreurs
Toujours afficher un message d'erreur
Rediriger l'utilisateur
5

Déploiement et CI/CD

Quelle est la meilleure pratique pour déployer une application React en production ?

Utiliser un service CI/CD comme GitHub Actions
Copier les fichiers manuellement via FTP
Envoyer le code source complet
Ne jamais mettre à jour l'application

Débloquez ce quiz et tous les autres contenus premium en achetant ce cours