feat: add themed 404 page
Flatlined pulse trace mirrors the PulseNode brand mark - a route that isn't monitored here reads as "no pulse" rather than a generic error page. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpxhtQY3CExQdMs4j7MmJe
This commit is contained in:
@@ -133,8 +133,22 @@ body {
|
|||||||
animation: pulse-glow 2s ease-in-out infinite;
|
animation: pulse-glow 2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-glow-down {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 0 0 color-mix(in srgb, var(--pn-status-down) 55%, transparent);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 0 4px color-mix(in srgb, var(--pn-status-down) 0%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.status-pulse-down {
|
||||||
|
animation: pulse-glow-down 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.status-pulse,
|
.status-pulse,
|
||||||
|
.status-pulse-down,
|
||||||
.pn-toast,
|
.pn-toast,
|
||||||
.pn-spin-in {
|
.pn-spin-in {
|
||||||
animation: none;
|
animation: none;
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import Link from "next/link";
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Not Found",
|
||||||
|
description: "No pulse on this route.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function NotFound() {
|
||||||
|
return (
|
||||||
|
<main className="flex min-h-screen flex-col items-center justify-center gap-8 px-6 text-center">
|
||||||
|
<svg
|
||||||
|
width="320"
|
||||||
|
height="64"
|
||||||
|
viewBox="0 0 320 64"
|
||||||
|
fill="none"
|
||||||
|
aria-hidden="true"
|
||||||
|
className="w-full max-w-[320px]"
|
||||||
|
>
|
||||||
|
<polyline
|
||||||
|
points="0,32 30,32 40,10 50,54 60,24 72,32 140,32"
|
||||||
|
fill="none"
|
||||||
|
stroke="var(--pn-accent)"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="140"
|
||||||
|
y1="32"
|
||||||
|
x2="300"
|
||||||
|
y2="32"
|
||||||
|
stroke="var(--pn-status-down)"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
opacity="0.55"
|
||||||
|
/>
|
||||||
|
<circle cx="300" cy="32" r="4" fill="var(--pn-status-down)" className="status-pulse-down" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<p className="font-display text-7xl font-semibold tracking-tight text-fg">404</p>
|
||||||
|
<p className="text-base font-medium text-fg">No pulse on this route.</p>
|
||||||
|
<p className="text-sm text-fg-muted">Nothing here is being monitored.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="rounded-md border border-border px-4 py-2 text-sm font-medium text-fg transition-colors hover:border-accent hover:text-accent"
|
||||||
|
>
|
||||||
|
Back to dashboard
|
||||||
|
</Link>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user