- 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
65 lines
1.7 KiB
TypeScript
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'application n'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>
|
|
);
|
|
}
|