Fil d'Ariane accessible avec Claude Code
Implémentez un fil d'Ariane avec Claude Code, JSON-LD, aria-current, CSS mobile et tests.
Le fil d’Ariane semble être une petite ligne au-dessus du titre, mais il touche en réalité à la structure du site, aux liens internes, à l’accessibilité, aux données structurées et à l’affichage mobile. Une version fragile peut paraître correcte tout en oubliant la page courante pour les lecteurs d’écran, en envoyant un JSON-LD incomplet à Google ou en cassant la mise en page sur mobile.
Dans les modèles ClaudeCodeLab, un premier prompt Claude Code a bien généré Home > Blog > Title, mais sans aria-current, avec des URL relatives dans le JSON-LD, des retours à la ligne en mobile et des slugs bruts. Claude Code est utile si on lui donne le contrat complet dès le départ.
Ce guide montre comment demander à Claude Code de générer et de relire un fil d’Ariane accessible pour React, Next.js-like et Astro. À lire avec l’optimisation SEO, l’accessibilité, Astro et React.
Contrat de conception
Un fil d’Ariane n’est pas un bouton retour. Il indique la hiérarchie, aide à revenir aux pages parentes et clarifie la relation entre pages. Le Breadcrumb Pattern du WAI-ARIA APG recommande une région de navigation libellée et aria-current="page" pour la page courante.
Les données structurées doivent suivre schema.org BreadcrumbList. Chaque élément doit avoir une position. Pour Google, vérifiez aussi la page officielle breadcrumb structured data.
| Décision | À définir | Erreur fréquente |
|---|---|---|
| Libellés | Titres, catégories ou dictionnaire | Slugs affichés tels quels |
| URL | Liens HTML et URL absolues JSON-LD | Chemins relatifs en données structurées |
| Page courante | Lien ou texte final | État montré seulement par la couleur |
| Mobile | Tout afficher ou réduire le milieu | Plusieurs lignes avant le contenu |
| Langues | Préfixe et libellés localisés | Mélange de langues |
Prompt pour Claude Code
Implémente un fil d'Ariane pour un site React/Next.js ou Astro.
Exigences:
- Recevoir items comme { label: string; href: string }[].
- Ajouter aria-current="page" au dernier item.
- Utiliser nav aria-label="Fil d'Ariane".
- Marquer les séparateurs avec aria-hidden="true".
- Générer JSON-LD BreadcrumbList depuis le même tableau items.
- Convertir les URL JSON-LD en URL absolues avec siteUrl.
- Ajouter un helper qui construit items depuis pathname.
- Transformer les slugs en texte lisible et permettre un dictionnaire de labels.
- Sur mobile, masquer les items intermédiaires en gardant la page courante lisible.
- Ajouter des tests Vitest pour root, chemins profonds, labels localisés et query strings.
- Lister ensuite les vérifications accessibilité et données structurées.
Pour une modification plus large, lancez une deuxième passe avec la checklist de revue Claude Code.
Composant React
import type { ReactNode } from "react";
export type BreadcrumbItem = {
label: string;
href: string;
};
type BreadcrumbProps = {
items: BreadcrumbItem[];
siteUrl: string;
ariaLabel?: string;
};
function toAbsoluteUrl(siteUrl: string, href: string) {
return new URL(href, siteUrl).toString();
}
function Separator(): ReactNode {
return (
<span className="breadcrumb__separator" aria-hidden="true">
/
</span>
);
}
export function Breadcrumb({
items,
siteUrl,
ariaLabel = "Breadcrumb",
}: BreadcrumbProps) {
if (items.length <= 1) return null;
const jsonLd = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: items.map((item, index) => ({
"@type": "ListItem",
position: index + 1,
item: {
"@id": toAbsoluteUrl(siteUrl, item.href),
name: item.label,
},
})),
};
return (
<>
<nav className="breadcrumb" aria-label={ariaLabel}>
<ol className="breadcrumb__list">
{items.map((item, index) => {
const isCurrent = index === items.length - 1;
return (
<li className="breadcrumb__item" key={item.href}>
{index > 0 ? <Separator /> : null}
{isCurrent ? (
<span className="breadcrumb__current" aria-current="page">
{item.label}
</span>
) : (
<a className="breadcrumb__link" href={item.href}>
{item.label}
</a>
)}
</li>
);
})}
</ol>
</nav>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
</>
);
}
Helper de routes
import type { BreadcrumbItem } from "@/components/Breadcrumb";
export type BreadcrumbLabels = Record<string, string>;
function titleize(segment: string) {
return decodeURIComponent(segment)
.replace(/[-_]+/g, " ")
.replace(/\b\w/g, (char) => char.toUpperCase());
}
export function buildBreadcrumbs(
pathname: string,
labels: BreadcrumbLabels = {},
): BreadcrumbItem[] {
const cleanPath = pathname.split(/[?#]/)[0].replace(/\/+$/, "") || "/";
const segments = cleanPath.split("/").filter(Boolean);
const items: BreadcrumbItem[] = [
{ label: labels["/"] ?? "Home", href: "/" },
];
let href = "";
for (const segment of segments) {
href += `/${segment}`;
items.push({
label: labels[href] ?? labels[segment] ?? titleize(segment),
href,
});
}
return items;
}
import { Breadcrumb } from "@/components/Breadcrumb";
import { buildBreadcrumbs } from "@/lib/breadcrumbs";
const siteUrl = "https://claudecodelab.com";
export default async function ArticlePage() {
const pathname = "/fr/blog/claude-code-breadcrumb-navigation";
const labels = {
"/": "Accueil",
"/fr": "Français",
"/fr/blog": "Articles",
"/fr/blog/claude-code-breadcrumb-navigation":
"Fil d'Ariane accessible avec Claude Code",
};
const items = buildBreadcrumbs(pathname, labels);
return (
<main>
<Breadcrumb items={items} siteUrl={siteUrl} ariaLabel="Fil d'Ariane" />
<h1>Fil d'Ariane accessible avec Claude Code</h1>
</main>
);
}
Dans Astro, utilisez la même structure avec Astro.url.pathname et set:html={JSON.stringify(jsonLd)} dans un composant .astro.
CSS mobile
.breadcrumb { margin-block: 0 1rem; font-size: 0.875rem; color: #4b5563; }
.breadcrumb__list { display: flex; flex-wrap: wrap; gap: 0.25rem; list-style: none; margin: 0; padding: 0; }
.breadcrumb__item { align-items: center; display: inline-flex; min-width: 0; }
.breadcrumb__link { color: #2563eb; text-decoration: underline; text-underline-offset: 0.15em; }
.breadcrumb__current { color: #111827; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.breadcrumb__separator { color: #9ca3af; margin-inline: 0.35rem; }
@media (max-width: 640px) {
.breadcrumb__list { flex-wrap: nowrap; }
.breadcrumb__item:not(:first-child):not(:nth-last-child(-n + 2)) { display: none; }
.breadcrumb__item:nth-last-child(2)::after { color: #9ca3af; content: "..."; margin-inline: 0.35rem; }
.breadcrumb__current { max-width: 58vw; }
}
Tests
import { describe, expect, it } from "vitest";
import { buildBreadcrumbs } from "./breadcrumbs";
describe("buildBreadcrumbs", () => {
it("returns only Home for the root path", () => {
expect(buildBreadcrumbs("/")).toEqual([{ label: "Home", href: "/" }]);
});
it("builds nested breadcrumbs and ignores query strings", () => {
expect(buildBreadcrumbs("/blog/claude-code?page=2")).toEqual([
{ label: "Home", href: "/" },
{ label: "Blog", href: "/blog" },
{ label: "Claude Code", href: "/blog/claude-code" },
]);
});
it("uses localized labels when provided", () => {
expect(
buildBreadcrumbs("/fr/blog/claude-code-breadcrumb-navigation", {
"/": "Accueil",
"/fr": "Français",
"/fr/blog": "Articles",
"/fr/blog/claude-code-breadcrumb-navigation": "Fil d'Ariane",
}),
).toEqual([
{ label: "Accueil", href: "/" },
{ label: "Français", href: "/fr" },
{ label: "Articles", href: "/fr/blog" },
{ label: "Fil d'Ariane", href: "/fr/blog/claude-code-breadcrumb-navigation" },
]);
});
});
En E2E, vérifiez nav[aria-label], un seul aria-current="page", un JSON-LD valide, des URL absolues et l’absence de chevauchement mobile. Voir aussi Playwright.
Cas d’usage, pièges et CTA
Les cas les plus utiles sont les blogs/documentations, les pages de formation ou ecommerce, les écrans SaaS profonds et les sites multilingues. Dans chaque cas, le fil d’Ariane améliore la compréhension du contexte et les liens internes.
Les pièges récurrents sont l’état courant indiqué seulement par couleur, les URL relatives dans JSON-LD, les slugs bruts, le mobile qui se casse et deux sources de données séparées pour l’UI et le JSON-LD. Avant publication, contrôlez aria-label, aria-current, séparateurs masqués, BreadcrumbList, position, URL absolues, cohérence visuelle/JSON-LD, mobile, langue et validation Search Console.
Sur ClaudeCodeLab, ce composant aide à guider les lecteurs vers la fiche gratuite, les produits et la formation/consulting Claude Code. J’ai vérifié le code en séparant composant React, helper et tests Vitest; la meilleure décision a été de générer l’UI et JSON-LD depuis le même items.
Résumé
Un bon fil d’Ariane n’est pas une décoration. Donnez à Claude Code les libellés, routes, aria-current, JSON-LD, URL absolues, comportement mobile et tests, puis relisez le résultat avec les sources officielles.
PDF gratuit: cheatsheet Claude Code
Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.
Nous protégeons vos données et n'envoyons pas de spam.
À propos de l'auteur
Masa
Ingénieur spécialisé dans les workflows pratiques avec Claude Code.
Articles liés
Échelle de sécurité des permissions Claude Code
Passer du read-only aux éditions limitées, preuves et checks de déploiement sans perdre le contrôle.
Claude Code Small PR Proof Pack : rendre les petits changements reviewables
Un pack de preuve pour PR Claude Code : diff, vérifications, URL publique, CTA et rollback.
Gate de review avant commit avec Claude Code
Review avant commit avec Claude Code : diff, build, URL publique, liens Gumroad, CTA consultation, tests manquants et fichiers hors scope.