mirror of
https://github.com/R0m1k3/PleinR.git
synced 2026-10-23 15:18:04 +02:00
Référencement : métadonnées complètes, données structurées, sitemap et robots
- Layout : metadataBase, gabarit de titre « %s · Plein R », description, mots-clés, Open Graph / Twitter, robots, icônes, manifeste, viewport et couleur de thème ; JSON-LD Organization + WebSite (recherche annuaire). - Chaque page publique pose titre, description (≤ 160 caractères) et canonique via pageMetadata() ; l'annuaire ignore ainsi ?q=. Fiche adhérent : titre « Nom · Catégorie à Ville », description dérivée, LocalBusiness avec adresse, contacts et horaires (OpeningHoursSpecification), BreadcrumbList. Annuaire : ItemList des adhérents. Association : BusinessEvent par rencontre à venir. Rencontres passées : fil d'Ariane. - Nouvelles routes : robots.txt, sitemap.xml (pages statiques + adhérents actifs), manifest.webmanifest, image de partage 1200×630 générée avec le logo, page 404 dédiée (noindex). - /backend, /login, /inscription/* et les fiches inactives en noindex. - Landmarks <main> sur toutes les pages publiques, fil d'Ariane en <nav>. - serializeJsonLd() échappe <, > et & : les saisies des adhérents ne peuvent pas fermer le bloc <script>. Tests unitaires dans tests/seo.test.ts. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDbKbJrPWweXXYSxA8MXW7
This commit is contained in:
21 files changed
+1113
-36
No files matched your search
@@ -0,0 +1,48 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { SiteFooter } from "@/components/SiteFooter";
|
||||
import { SiteHeader } from "@/components/SiteHeader";
|
||||
import { NOINDEX } from "@/lib/seo";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Page introuvable",
|
||||
robots: NOINDEX,
|
||||
};
|
||||
|
||||
/** 404 publique : renvoie vers l'annuaire plutôt que vers une page blanche. */
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<div style={{ background: "#F6F2E8", minHeight: "100vh", fontFamily: "'Public Sans',sans-serif", color: "#33291D" }}>
|
||||
<SiteHeader logo />
|
||||
<main className="container" style={{ paddingTop: 48, paddingBottom: 72, maxWidth: 720 }}>
|
||||
<div style={{ color: "#9a6638", fontSize: 12, letterSpacing: "0.14em", textTransform: "uppercase", fontWeight: 800, marginBottom: 12 }}>
|
||||
Erreur 404
|
||||
</div>
|
||||
<h1 className="font-display" style={{ margin: "0 0 14px", color: "#26201a", fontSize: "clamp(30px, 6vw, 48px)", lineHeight: 1.05, letterSpacing: "-0.02em" }}>
|
||||
Cette page n'existe pas ou plus
|
||||
</h1>
|
||||
<p style={{ fontSize: 17, lineHeight: 1.6, color: "#6c6150", margin: "0 0 26px" }}>
|
||||
La fiche ou la page demandée a peut-être été retirée. Retrouvez tous les commerçants et
|
||||
entreprises du Bassin de Pompey dans l'annuaire.
|
||||
</p>
|
||||
<div style={{ display: "flex", gap: 12, flexWrap: "wrap" }}>
|
||||
<Link
|
||||
href="/annuaire"
|
||||
className="font-display"
|
||||
style={{ textDecoration: "none", background: "#E0A63C", color: "#33291D", fontWeight: 700, fontSize: 15.5, padding: "13px 24px", borderRadius: 12 }}
|
||||
>
|
||||
Voir l'annuaire
|
||||
</Link>
|
||||
<Link
|
||||
href="/"
|
||||
className="font-display"
|
||||
style={{ textDecoration: "none", background: "#fff", border: "1px solid #e6dcc6", color: "#33291D", fontWeight: 700, fontSize: 15.5, padding: "13px 24px", borderRadius: 12 }}
|
||||
>
|
||||
Retour à l'accueil
|
||||
</Link>
|
||||
</div>
|
||||
</main>
|
||||
<SiteFooter />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user