Error 500
Original · free500 server error page
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/error-500.json"use client";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { motion, useReducedMotion } from "motion/react";
type RetryState = "idle" | "retrying";
type ServiceStatus = "operational" | "degraded" | "down";
interface ServiceRow {
name: string;
region: string;
status: ServiceStatus;
detail: string;
}
const RETRY_SECONDS = 15;
const SERVICES: ServiceRow[] = [
{ name: "API Gateway", region: "us-east-1", status: "operational", detail: "204 ms · healthy" },
{ name: "Application Server", region: "us-east-1", status: "down", detail: "worker pool exhausted" },
{ name: "PostgreSQL Primary", region: "us-east-1", status: "degraded", detail: "connection saturation 98%" },
{ name: "Redis Cache", region: "us-east-1", status: "operational", detail: "11 ms · healthy" },
{ name: "Edge CDN", region: "global", status: "operational", detail: "cache hit 96%" },
];
const STATUS_META: Record<
ServiceStatus,
{ label: string; dot: string; ring: string; text: string }
> = {
operational: {
label: "Operational",
dot: "bg-emerald-500",
ring: "ring-emerald-500/30",
text: "text-emerald-600 dark:text-emerald-400",
},
degraded: {
label: "Degraded",
dot: "bg-amber-500",
ring: "ring-amber-500/30",
text: "text-amber-600 dark:text-amber-400",
},
down: {
label: "Down",
dot: "bg-rose-500",
ring: "ring-rose-500/30",
text: "text-rose-600 dark:text-rose-400",
},
};
export default function Error500() {
const reduce = useReducedMotion();
const [retryState, setRetryState] = useState<RetryState>("idle");
const [attempts, setAttempts] = useState<number>(0);
const [autoRetry, setAutoRetry] = useState<boolean>(false);
const [countdown, setCountdown] = useState<number>(RETRY_SECONDS);
const [copied, setCopied] = useState<boolean>(false);
const [detectedAt, setDetectedAt] = useState<string>("moments ago");
const [announce, setAnnounce] = useState<string>("");
const retryTimer = useRef<number | null>(null);
const copyTimer = useRef<number | null>(null);
const incidentId = "INC-5F3A-90C2-7E11";
useEffect(() => {
setDetectedAt(
new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" }),
);
return () => {
if (retryTimer.current !== null) window.clearTimeout(retryTimer.current);
if (copyTimer.current !== null) window.clearTimeout(copyTimer.current);
};
}, []);
const handleRetry = useCallback(() => {
setRetryState((prev) => {
if (prev === "retrying") return prev;
setAnnounce("Reconnecting to the application server.");
if (retryTimer.current !== null) window.clearTimeout(retryTimer.current);
retryTimer.current = window.setTimeout(() => {
setAttempts((a) => {
const next = a + 1;
setAnnounce(`Attempt ${next} failed. The server is still returning 500 errors.`);
return next;
});
setCountdown(RETRY_SECONDS);
setRetryState("idle");
}, 1900);
return "retrying";
});
}, []);
useEffect(() => {
if (!autoRetry || retryState !== "idle") return;
if (countdown <= 0) {
handleRetry();
return;
}
const t = window.setTimeout(() => setCountdown((c) => c - 1), 1000);
return () => window.clearTimeout(t);
}, [autoRetry, retryState, countdown, handleRetry]);
const toggleAutoRetry = useCallback(() => {
setAutoRetry((prev) => {
const next = !prev;
if (next) {
setCountdown(RETRY_SECONDS);
setAnnounce("Automatic retry enabled.");
} else {
setAnnounce("Automatic retry disabled.");
}
return next;
});
}, []);
const handleCopy = useCallback(async () => {
try {
await navigator.clipboard.writeText(incidentId);
setCopied(true);
setAnnounce("Incident ID copied to clipboard.");
if (copyTimer.current !== null) window.clearTimeout(copyTimer.current);
copyTimer.current = window.setTimeout(() => setCopied(false), 2200);
} catch {
setCopied(false);
setAnnounce("Copy failed. Please select the incident ID manually.");
}
}, []);
const rise = useMemo(() => {
if (reduce) return {};
return {
initial: { opacity: 0, y: 18 },
animate: { opacity: 1, y: 0 },
transition: { duration: 0.55, ease: "easeOut" as const },
};
}, [reduce]);
const focusRing =
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-white dark:focus-visible:ring-offset-slate-950";
const retrying = retryState === "retrying";
return (
<section className="relative w-full overflow-hidden bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-slate-100">
<style>{`
@keyframes err500-drift {
0% { transform: translate3d(0,0,0); }
100% { transform: translate3d(-56px,-56px,0); }
}
@keyframes err500-pulse {
0%,100% { opacity: .5; transform: scale(1); }
50% { opacity: 1; transform: scale(1.05); }
}
@keyframes err500-scan {
0% { transform: translateY(-120%); }
100% { transform: translateY(720%); }
}
@keyframes err500-spin { to { transform: rotate(360deg); } }
@keyframes err500-blink { 0%,100% { opacity: 1; } 50% { opacity: .15; } }
@keyframes err500-dash { to { stroke-dashoffset: 0; } }
@keyframes err500-ping {
0% { transform: scale(1); opacity: .7; }
80%,100% { transform: scale(2.4); opacity: 0; }
}
.err500-grid { animation: err500-drift 22s linear infinite; }
.err500-badge { animation: err500-pulse 2.6s ease-in-out infinite; }
.err500-scanline { animation: err500-scan 3.4s linear infinite; }
.err500-spinner { animation: err500-spin .8s linear infinite; }
.err500-cursor { animation: err500-blink 1.1s step-end infinite; }
.err500-spark {
stroke-dasharray: 640;
stroke-dashoffset: 640;
animation: err500-dash 2.4s ease-out forwards;
}
.err500-ping { animation: err500-ping 1.9s cubic-bezier(0,0,.2,1) infinite; }
@media (prefers-reduced-motion: reduce) {
.err500-grid, .err500-badge, .err500-scanline, .err500-spinner,
.err500-cursor, .err500-spark, .err500-ping { animation: none !important; }
.err500-spark { stroke-dashoffset: 0; }
}
`}</style>
{/* Atmospheric background */}
<div aria-hidden className="pointer-events-none absolute inset-0">
<div
className="err500-grid absolute -inset-24 opacity-[0.5] dark:opacity-[0.35]"
style={{
backgroundImage:
"linear-gradient(to right, rgba(100,116,139,0.16) 1px, transparent 1px), linear-gradient(to bottom, rgba(100,116,139,0.16) 1px, transparent 1px)",
backgroundSize: "44px 44px",
}}
/>
<div className="absolute -top-40 left-1/2 h-[32rem] w-[32rem] -translate-x-1/2 rounded-full bg-rose-400/20 blur-[120px] dark:bg-rose-500/15" />
<div className="absolute -bottom-40 -right-24 h-[28rem] w-[28rem] rounded-full bg-indigo-400/20 blur-[120px] dark:bg-indigo-500/15" />
<div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-rose-500/40 to-transparent" />
</div>
<div className="relative mx-auto w-full max-w-6xl px-6 py-20 sm:px-8 sm:py-24 lg:py-28">
<motion.div {...rise} className="grid gap-10 lg:grid-cols-[1.05fr_0.95fr] lg:gap-14">
{/* Left column: headline + actions */}
<div className="flex flex-col">
<div className="flex items-center gap-3">
<span className="relative flex h-2.5 w-2.5">
<span className="err500-ping absolute inline-flex h-full w-full rounded-full bg-rose-500/60" />
<span className="relative inline-flex h-2.5 w-2.5 rounded-full bg-rose-500" />
</span>
<span className="text-xs font-semibold uppercase tracking-[0.24em] text-rose-600 dark:text-rose-400">
Major incident · production down
</span>
</div>
{/* The 500 numerals */}
<div className="relative mt-8 select-none">
<div
aria-hidden
className="err500-badge absolute -inset-6 -z-10 rounded-[2.5rem] bg-gradient-to-br from-rose-500/10 via-transparent to-indigo-500/10 blur-2xl"
/>
<h1 className="flex items-baseline font-mono text-[5.5rem] font-black leading-none tracking-tighter sm:text-[8rem]">
<span className="bg-gradient-to-br from-slate-900 to-slate-500 bg-clip-text text-transparent dark:from-white dark:to-slate-500">
5
</span>
<span className="bg-gradient-to-br from-rose-500 to-rose-700 bg-clip-text text-transparent">
0
</span>
<span className="bg-gradient-to-br from-slate-900 to-slate-500 bg-clip-text text-transparent dark:from-white dark:to-slate-500">
0
</span>
<span aria-hidden className="err500-cursor ml-2 inline-block h-[0.62em] w-[0.11em] translate-y-[-0.06em] bg-rose-500" />
</h1>
</div>
<h2 className="mt-6 text-2xl font-bold tracking-tight sm:text-3xl">
Our server hit an unexpected error.
</h2>
<p className="mt-4 max-w-lg text-[0.975rem] leading-relaxed text-slate-600 dark:text-slate-400">
The request never made it back. An application worker crashed while processing your
call, so nothing was saved or charged. Our on-call engineer has been paged
automatically, and the fix is already underway.
</p>
{/* Primary controls */}
<div className="mt-8 flex flex-wrap items-center gap-3">
<button
type="button"
onClick={handleRetry}
disabled={retrying}
aria-live="off"
className={`group inline-flex items-center gap-2.5 rounded-xl bg-slate-900 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-slate-900/20 transition-colors hover:bg-slate-800 disabled:cursor-not-allowed disabled:opacity-70 dark:bg-white dark:text-slate-900 dark:shadow-black/40 dark:hover:bg-slate-200 ${focusRing}`}
>
{retrying ? (
<svg viewBox="0 0 24 24" className="err500-spinner h-4 w-4" aria-hidden fill="none">
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2.5" opacity="0.25" />
<path d="M21 12a9 9 0 0 0-9-9" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" />
</svg>
) : (
<svg viewBox="0 0 24 24" className="h-4 w-4" aria-hidden fill="none">
<path
d="M20 12a8 8 0 1 1-2.34-5.66M20 4v4h-4"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)}
{retrying ? "Reconnecting…" : "Try again"}
</button>
<a
href="/"
className={`inline-flex items-center gap-2 rounded-xl border border-slate-300 bg-white px-5 py-3 text-sm font-semibold text-slate-700 transition-colors hover:border-slate-400 hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-200 dark:hover:border-slate-600 dark:hover:bg-slate-800 ${focusRing}`}
>
<svg viewBox="0 0 24 24" className="h-4 w-4" aria-hidden fill="none">
<path
d="M3 10.5 12 3l9 7.5M5 9.5V20a1 1 0 0 0 1 1h4v-6h4v6h4a1 1 0 0 0 1-1V9.5"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
Back to homepage
</a>
<a
href="mailto:support@webinnoventix.com?subject=Incident%20INC-5F3A-90C2-7E11"
className={`inline-flex items-center gap-2 rounded-xl px-4 py-3 text-sm font-semibold text-slate-600 underline-offset-4 transition-colors hover:text-slate-900 hover:underline dark:text-slate-400 dark:hover:text-white ${focusRing}`}
>
Contact support
</a>
</div>
{/* Auto-retry switch */}
<div className="mt-6 flex items-center gap-3 rounded-xl border border-slate-200 bg-white/70 px-4 py-3 backdrop-blur dark:border-slate-800 dark:bg-slate-900/60">
<button
type="button"
role="switch"
aria-checked={autoRetry}
aria-labelledby="err500-auto-label"
onClick={toggleAutoRetry}
className={`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors ${
autoRetry ? "bg-indigo-600" : "bg-slate-300 dark:bg-slate-700"
} ${focusRing}`}
>
<span
className={`inline-block transform rounded-full bg-white shadow transition-transform ${
autoRetry ? "translate-x-6" : "translate-x-1"
}`}
style={{ height: "1.125rem", width: "1.125rem" }}
/>
</button>
<div className="min-w-0">
<p id="err500-auto-label" className="text-sm font-medium text-slate-800 dark:text-slate-200">
Retry automatically
</p>
<p className="text-xs text-slate-500 dark:text-slate-500">
{autoRetry && !retrying
? `Next attempt in ${countdown}s`
: retrying
? "Attempting to reconnect…"
: "Ping the server on a 15-second loop"}
</p>
</div>
{attempts > 0 && (
<span className="ml-auto rounded-md bg-rose-100 px-2 py-1 font-mono text-xs font-semibold text-rose-700 dark:bg-rose-500/15 dark:text-rose-300">
{attempts} failed
</span>
)}
</div>
</div>
{/* Right column: incident console */}
<div className="relative overflow-hidden rounded-2xl border border-slate-200 bg-white/80 shadow-xl shadow-slate-900/5 backdrop-blur-sm dark:border-slate-800 dark:bg-slate-900/70 dark:shadow-black/30">
<div aria-hidden className="err500-scanline pointer-events-none absolute inset-x-0 top-0 h-16 bg-gradient-to-b from-rose-500/10 to-transparent" />
{/* Console header */}
<div className="flex items-center justify-between border-b border-slate-200 px-5 py-3.5 dark:border-slate-800">
<div className="flex items-center gap-1.5">
<span className="h-3 w-3 rounded-full bg-rose-400" />
<span className="h-3 w-3 rounded-full bg-amber-400" />
<span className="h-3 w-3 rounded-full bg-emerald-400" />
</div>
<span className="font-mono text-xs text-slate-500 dark:text-slate-500">
status.webinnoventix.com
</span>
</div>
{/* Incident meta */}
<div className="grid grid-cols-2 gap-px bg-slate-200 dark:bg-slate-800">
<div className="bg-white px-5 py-4 dark:bg-slate-900">
<p className="text-[0.68rem] font-semibold uppercase tracking-wider text-slate-400 dark:text-slate-500">
Incident ID
</p>
<div className="mt-1.5 flex items-center gap-2">
<code className="font-mono text-sm font-semibold text-slate-800 dark:text-slate-200">
{incidentId}
</code>
<button
type="button"
onClick={handleCopy}
aria-label={copied ? "Incident ID copied" : "Copy incident ID"}
className={`inline-flex h-6 w-6 items-center justify-center rounded-md text-slate-400 transition-colors hover:bg-slate-100 hover:text-slate-700 dark:hover:bg-slate-800 dark:hover:text-slate-200 ${focusRing}`}
>
{copied ? (
<svg viewBox="0 0 24 24" className="h-3.5 w-3.5 text-emerald-500" aria-hidden fill="none">
<path d="m5 12 5 5 9-11" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
) : (
<svg viewBox="0 0 24 24" className="h-3.5 w-3.5" aria-hidden fill="none">
<rect x="9" y="9" width="11" height="11" rx="2" stroke="currentColor" strokeWidth="2" />
<path d="M5 15V6a2 2 0 0 1 2-2h9" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
)}
</button>
</div>
</div>
<div className="bg-white px-5 py-4 dark:bg-slate-900">
<p className="text-[0.68rem] font-semibold uppercase tracking-wider text-slate-400 dark:text-slate-500">
Detected at
</p>
<p className="mt-1.5 font-mono text-sm font-semibold text-slate-800 dark:text-slate-200">
{detectedAt}
</p>
</div>
</div>
{/* Hand-drawn request-rate chart */}
<div className="border-t border-slate-200 px-5 py-4 dark:border-slate-800">
<div className="flex items-center justify-between">
<p className="text-[0.68rem] font-semibold uppercase tracking-wider text-slate-400 dark:text-slate-500">
Requests / min · last 3h
</p>
<span className="font-mono text-xs font-semibold text-rose-600 dark:text-rose-400">
↓ 100% · flatline
</span>
</div>
<svg
viewBox="0 0 320 92"
className="mt-3 h-24 w-full"
role="img"
aria-label="Request rate chart showing traffic climbing then collapsing to zero when the server went down."
preserveAspectRatio="none"
>
<defs>
<linearGradient id="err500-fill" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="rgb(244,63,94)" stopOpacity="0.28" />
<stop offset="100%" stopColor="rgb(244,63,94)" stopOpacity="0" />
</linearGradient>
</defs>
{[23, 46, 69].map((y) => (
<line
key={y}
x1="0"
y1={y}
x2="320"
y2={y}
stroke="currentColor"
strokeWidth="1"
className="text-slate-200 dark:text-slate-800"
/>
))}
<path
d="M0,74 L34,66 L60,70 L92,50 L120,58 L150,30 L172,14 L184,84 L320,84 L320,92 L0,92 Z"
fill="url(#err500-fill)"
/>
<path
d="M0,74 L34,66 L60,70 L92,50 L120,58 L150,30 L172,14 L184,84 L320,84"
fill="none"
stroke="rgb(244,63,94)"
strokeWidth="2.25"
strokeLinejoin="round"
strokeLinecap="round"
className="err500-spark"
/>
<line x1="184" y1="14" x2="184" y2="84" stroke="rgb(244,63,94)" strokeWidth="1" strokeDasharray="3 3" opacity="0.55" />
<circle cx="172" cy="14" r="3.5" fill="rgb(244,63,94)" />
</svg>
</div>
{/* System status list */}
<div className="border-t border-slate-200 dark:border-slate-800">
<ul className="divide-y divide-slate-100 dark:divide-slate-800/70">
{SERVICES.map((svc) => {
const meta = STATUS_META[svc.status];
return (
<li key={svc.name} className="flex items-center gap-3 px-5 py-3">
<span
className={`relative flex h-2.5 w-2.5 shrink-0 rounded-full ring-4 ${meta.ring}`}
>
<span className={`h-2.5 w-2.5 rounded-full ${meta.dot}`} />
</span>
<div className="min-w-0 flex-1">
<div className="flex items-baseline gap-2">
<p className="truncate text-sm font-semibold text-slate-800 dark:text-slate-200">
{svc.name}
</p>
<span className="font-mono text-[0.68rem] text-slate-400 dark:text-slate-500">
{svc.region}
</span>
</div>
<p className="truncate font-mono text-xs text-slate-500 dark:text-slate-500">
{svc.detail}
</p>
</div>
<span className={`shrink-0 text-xs font-semibold ${meta.text}`}>
{meta.label}
</span>
</li>
);
})}
</ul>
</div>
<div className="border-t border-slate-200 px-5 py-3.5 dark:border-slate-800">
<a
href="/status"
className={`inline-flex items-center gap-1.5 rounded-md text-xs font-semibold text-indigo-600 underline-offset-4 hover:underline dark:text-indigo-400 ${focusRing}`}
>
View full status page
<svg viewBox="0 0 24 24" className="h-3.5 w-3.5" aria-hidden fill="none">
<path d="M7 17 17 7M9 7h8v8" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</a>
</div>
</div>
</motion.div>
<p className="mt-10 text-center font-mono text-xs text-slate-400 dark:text-slate-600">
If this keeps happening, quote incident {incidentId} to our team — it maps straight to the trace.
</p>
</div>
{/* Accessible live region for control feedback */}
<div aria-live="polite" className="sr-only">
{announce}
</div>
</section>
);
}Dependencies
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Error 404
Originalfriendly 404 page with illustration and CTA

Error 403
Original403 access denied page

Error Offline
Originaloffline / no-connection state

Error Maintenance
Originalscheduled maintenance page

Error Coming Soon
Originalcoming soon page with countdown and email

Error Under Construction
Originalunder construction page

Error Search Empty
Originalno search results page

Error Expired
Originallink/session expired page

Error Generic
Originalgeneric error page with retry

Spotlight Hero
OriginalA centred hero with a soft radial spotlight, badge and dual call-to-action.

Split Hero
OriginalA two-column hero pairing a headline and CTAs with a product mock and social proof.

Gradient Spotlight Hero
OriginalA minimal centred hero with a soft gradient-mesh backdrop, announcement pill and dual call-to-action buttons.

