portfolio_v2/app/global-error.tsx
franck ec005b1622 Refonte du portfolio : profil GitHub, CV, SEO, export statique
- Accueil façon profil GitHub (bio, homelab, projets épinglés, parcours)
  avec fond dégradé et panneaux liquid glass
- /cv : consultable en ligne (thème sombre), imprimable en PDF propre
  (thème clair, 1 page) ; numéro de téléphone non scrapable
- Pages d'erreur 404 / 500 / global-error animées (GSAP)
- Métadonnées : Open Graph, Twitter, JSON-LD Person, sitemap, robots
  (allowlist Google + bots d'aperçu, reste bloqué)
- Images OG et favicon en PNG statiques
- Contenu du CV : Saint-Paul, langues, expériences détaillées
- Export statique (output: export) + DEPLOY.md
- Retrait de l'indicateur de dev Next.js et des fichiers du starter

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3hzMzvei419MwkKFZkvMX
2026-09-08 19:33:47 +04:00

65 lines
1.7 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
import gsap from "gsap";
import "./globals.css";
export default function GlobalError({
error,
retry,
}: {
error: Error & { digest?: string };
retry: () => void;
}) {
const root = useRef<HTMLBodyElement>(null);
useEffect(() => {
console.error(error);
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (reduce) return;
const ctx = gsap.context(() => {
gsap.from("[data-fade]", {
autoAlpha: 0,
y: 16,
duration: 0.5,
ease: "power3.out",
stagger: 0.09,
});
}, root);
return () => ctx.revert();
}, [error]);
return (
<html lang="fr">
<title>Erreur — Franck Thiaw-Woaye-Lapierre</title>
<body ref={root} className="min-h-screen antialiased">
<main className="flex min-h-screen flex-col items-center justify-center gap-6 px-6 text-center">
<div
data-fade
className="leading-none font-bold text-danger [font-size:clamp(4rem,18vw,9rem)]"
>
500
</div>
<div data-fade className="space-y-2">
<h1 className="text-2xl font-semibold">Erreur critique</h1>
<p className="max-w-[46ch] text-muted">
L&apos;application n&apos;a pas pu se charger. Réessaie dans un
instant.
</p>
</div>
<button
data-fade
type="button"
onClick={() => retry()}
className="rounded-md border border-line bg-surface px-4 py-2 text-sm font-semibold hover:border-muted"
>
Recharger
</button>
</main>
</body>
</html>
);
}