Web InnoventixFreeCode

Error 500

Original · free

500 server error page

byWeb InnoventixReact + Tailwind
error500pages
Open

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
error-500.tsx
"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

motion

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 quote

Similar components

Browse all →