feat: add branded 404 page

This commit is contained in:
2026-08-30 13:49:35 -03:00
parent 48f05bcf8a
commit a3859f1efc
7 changed files with 256 additions and 2 deletions
+70
View File
@@ -0,0 +1,70 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>__SEO_TITLE__</title>
<meta name="description" content="__SEO_DESCRIPTION__">
<meta name="robots" content="noindex,nofollow,noarchive">
<meta name="application-name" content="The Meme Protocol">
<meta name="theme-color" content="#00ff41">
<link rel="manifest" href="/site.webmanifest?v=20260814">
<link rel="service-desc" type="application/openapi+json" href="/openapi.json">
<link rel="help" type="text/markdown" href="/meme-api.skill.md">
<meta property="og:type" content="website">
<meta property="og:site_name" content="The Meme Protocol">
<meta property="og:title" content="__SEO_TITLE__">
<meta property="og:description" content="__SEO_DESCRIPTION__">
<meta property="og:url" content="__SEO_URL__">
<meta property="og:image" content="__SEO_IMAGE__">
<meta property="og:image:type" content="image/png">
<meta property="og:image:width" content="1266">
<meta property="og:image:height" content="1242">
<meta property="og:image:alt" content="__SEO_IMAGE_ALT__">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="__SEO_TITLE__">
<meta name="twitter:description" content="__SEO_DESCRIPTION__">
<meta name="twitter:image" content="__SEO_IMAGE__">
<meta name="twitter:image:alt" content="__SEO_IMAGE_ALT__">
<link rel="icon" type="image/svg+xml" href="/assets/favicon/favicon.svg?v=20260814">
<link rel="icon" type="image/png" sizes="96x96" href="/assets/favicon/favicon-96x96.png?v=20260814">
<link rel="shortcut icon" href="/favicon.ico?v=20260814">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/favicon/apple-touch-icon.png?v=20260814">
<meta name="apple-mobile-web-app-title" content="Meme Protocol">
<link rel="stylesheet" href="/assets/styles.css">
</head>
<body class="not-found-page">
<header class="topbar">
<a class="brand brand-link" href="/" aria-label="The Meme Protocol home">THE_MEME_PROTOCOL</a>
<a class="primary-action not-found-action" href="/">RETURN_TO_LIVE_FEED</a>
</header>
<main class="shell not-found-shell">
<div class="status-line">
<nav class="protocol-menu" aria-label="Protocol menu">
<a href="/?open=pet">DOWNLOAD PET</a>
<a href="/lore">READ LORE</a>
</nav>
<span class="live"><span class="pulse" aria-hidden="true"></span>ERROR_404 // NODE_UNREACHABLE</span>
</div>
<section class="not-found-content" aria-label="Page not found">
<div class="not-found-visual">
<img
src="/assets/homo-reseticus-404.png"
width="1266"
height="1242"
alt="Homo Reseticus surrounded by an unreachable node pattern"
>
</div>
</section>
</main>
<footer class="repo-footer">
<a href="https://git.yoonect.com/Nautilus/bitsforfree" rel="noopener noreferrer" target="_blank">
<img src="/assets/yoonect-logo.png" alt="" aria-hidden="true">
<span>SOURCE</span>
</a>
</footer>
</body>
</html>
+7
View File
@@ -253,6 +253,13 @@ function renderMemes(memes, options = {}) {
}
async function openSharedContentFromUrl() {
const requestedDialog = new URLSearchParams(window.location.search).get('open');
if (window.location.pathname === '/' && requestedDialog === 'pet') {
petModal.showModal();
window.history.replaceState({}, '', '/');
return;
}
if (window.location.pathname === '/lore' || window.location.pathname === '/lore/') {
await openLoreDialog();
return;
Binary file not shown.

After

Width:  |  Height:  |  Size: 653 KiB

+84
View File
@@ -91,6 +91,15 @@ a {
letter-spacing: 0.2em;
}
.brand-link {
text-decoration: none;
}
.brand-link:hover,
.brand-link:focus-visible {
color: var(--text);
}
.primary-action,
.secondary-action,
.icon-action {
@@ -925,6 +934,75 @@ dialog::backdrop {
text-align: center;
}
.not-found-page {
min-height: 100svh;
overflow-x: hidden;
}
.not-found-shell {
display: grid;
grid-template-rows: auto 1fr;
min-height: 100svh;
}
.not-found-content {
display: grid;
width: min(100%, 760px);
justify-items: center;
place-self: center;
padding: 24px 0 48px;
text-align: center;
}
.not-found-visual {
position: relative;
isolation: isolate;
width: clamp(190px, 39vmin, 414px);
max-width: 100%;
}
.not-found-page .pulse {
background: #ff453a;
box-shadow: 0 0 8px rgb(255 69 58 / 55%);
}
.not-found-visual::before {
position: absolute;
z-index: -1;
inset: 7% 5% 6%;
border-radius: 50%;
background:
radial-gradient(
ellipse at 50% 47%,
rgb(255 255 255 / 58%) 0%,
rgb(244 248 244 / 36%) 36%,
rgb(211 224 213 / 16%) 58%,
transparent 76%
),
radial-gradient(
ellipse at 50% 48%,
rgb(192 216 198 / 12%) 0%,
transparent 72%
);
content: "";
filter: blur(36px);
transform: scale(1.24);
}
.not-found-visual img {
display: block;
width: 100%;
height: auto;
filter: contrast(1.06) drop-shadow(0 0 18px rgb(229 226 225 / 14%));
}
.not-found-action {
display: inline-flex;
min-height: 40px;
align-items: center;
justify-content: center;
}
[hidden] {
display: none !important;
}
@@ -1048,3 +1126,9 @@ dialog::backdrop {
justify-content: space-between;
}
}
@media (prefers-reduced-motion: reduce) {
.not-found-page .pulse {
animation: none;
}
}