argobox/src/components/404.astro.astro

372 lines
9.6 KiB
Plaintext

---
// 404.astro - Custom 404 error page
import BaseLayout from '../layouts/BaseLayout.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import Terminal from '../components/Terminal.astro';
// Terminal commands for the 404 page
const terminalCommands = [
{
prompt: "[system@argobox]$ ",
command: "find /var/www/ArgoBox -name \"requested-page\"",
output: ["find: No matches found"]
},
{
prompt: "[system@argobox]$ ",
command: "grep -r \"requested-page\" /var/www/ArgoBox",
output: ["No matches found in site content"]
},
{
prompt: "[system@argobox]$ ",
command: "echo $?",
output: ["1"]
},
{
prompt: "[system@argobox]$ ",
command: "suggest_pages",
output: [
"Running site diagnostics...",
"Suggested pages:",
" - <a href='/'>Home</a>",
" - <a href='/blog'>Blog</a>",
" - <a href='/resources'>Resources</a>",
" - <a href='/projects'>Projects</a>"
]
},
{
prompt: "[system@argobox]$ ",
command: "return --code=404",
}
];
// Random tech error messages
const errorMessages = [
"Connection terminated unexpectedly.",
"Resource allocation failed: Page not found.",
"Route resolution error: Destination unreachable.",
"404: The requested URL does not exist on this server.",
"Network path not found: Check your request and try again."
];
// Get a random error message
const randomError = errorMessages[Math.floor(Math.random() * errorMessages.length)];
---
<BaseLayout title="404 - Page Not Found | ArgoBox" description="The requested page was not found on the ArgoBox tech blog.">
<Header slot="header" />
<main class="error-container">
<div class="error-content">
<div class="error-code">
<span class="error-digit">4</span>
<div class="error-digit-middle">
<div class="error-spinner"></div>
<span>0</span>
</div>
<span class="error-digit">4</span>
</div>
<h1 class="error-title">Page Not Found</h1>
<p class="error-message">{randomError}</p>
<div class="error-actions">
<a href="/" class="primary-button">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
<span>Return Home</span>
</a>
<a href="/blog" class="secondary-button">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</svg>
<span>Browse Articles</span>
</a>
</div>
</div>
<div class="error-terminal">
<Terminal commands={terminalCommands} title="system-error-trace" />
</div>
<div class="error-bg"></div>
<div class="glitch-effect"></div>
</main>
<Footer slot="footer" />
</BaseLayout>
<style>
.error-container {
min-height: 70vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem;
position: relative;
overflow: hidden;
}
.error-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(circle at 20% 35%, rgba(239, 68, 68, 0.05) 0%, transparent 50%),
radial-gradient(circle at 75% 15%, rgba(6, 182, 212, 0.05) 0%, transparent 45%),
radial-gradient(circle at 85% 70%, rgba(139, 92, 246, 0.05) 0%, transparent 40%);
z-index: -1;
}
.error-bg::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
linear-gradient(rgba(226, 232, 240, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(226, 232, 240, 0.03) 1px, transparent 1px);
background-size: 30px 30px;
}
.error-content {
max-width: 600px;
text-align: center;
margin-bottom: 3rem;
position: relative;
z-index: 1;
}
.error-code {
display: flex;
align-items: center;
justify-content: center;
font-size: 8rem;
font-weight: 800;
margin-bottom: 2rem;
line-height: 1;
gap: 1rem;
}
.error-digit {
background: linear-gradient(135deg, var(--accent-primary), var(--accent-tertiary));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: 0 5px 15px rgba(6, 182, 212, 0.3);
}
.error-digit-middle {
position: relative;
width: 100px;
height: 130px;
display: flex;
align-items: center;
justify-content: center;
color: var(--accent-secondary);
}
.error-spinner {
position: absolute;
width: 100%;
height: 100%;
border: 4px solid rgba(59, 130, 246, 0.2);
border-top: 4px solid var(--accent-secondary);
border-radius: 50%;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error-title {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.error-message {
color: var(--text-secondary);
font-size: 1.1rem;
margin-bottom: 2rem;
font-family: var(--font-mono);
}
.error-actions {
display: flex;
gap: 1rem;
justify-content: center;
margin-top: 2rem;
}
.primary-button {
padding: 0.8rem 1.5rem;
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
color: var(--bg-primary);
font-weight: 600;
border-radius: 8px;
border: none;
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(6, 182, 212, 0.3);
}
.primary-button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(6, 182, 212, 0.4);
}
.secondary-button {
padding: 0.8rem 1.5rem;
background: rgba(226, 232, 240, 0.1);
color: var(--text-primary);
font-weight: 600;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
transition: all 0.3s ease;
}
.secondary-button:hover {
background: rgba(226, 232, 240, 0.2);
border-color: rgba(255, 255, 255, 0.2);
}
.error-terminal {
width: 100%;
max-width: 700px;
margin: 0 auto;
}
.glitch-effect {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(45deg,
rgba(255, 0, 0, 0) 45%,
rgba(255, 0, 0, 0.03) 50%,
rgba(255, 0, 0, 0) 55%
);
background-size: 200% 200%;
pointer-events: none;
animation: glitch-scan 4s ease-in-out infinite;
z-index: 2;
mix-blend-mode: overlay;
}
@keyframes glitch-scan {
0%, 100% {
background-position: 0% 0%;
opacity: 0;
}
25%, 75% {
opacity: 0;
}
50% {
background-position: 100% 100%;
opacity: 1;
}
}
@media (max-width: 768px) {
.error-code {
font-size: 5rem;
}
.error-title {
font-size: 2rem;
}
.error-digit-middle {
width: 70px;
height: 90px;
}
.error-actions {
flex-direction: column;
}
}
</style>
<script>
// Add some randomized glitch effects to the 404 page
document.addEventListener('DOMContentLoaded', () => {
const errorContainer = document.querySelector('.error-container');
const errorDigit = document.querySelectorAll('.error-digit');
// Random glitch effect for the error digits
function glitchEffect() {
const randomDigit = errorDigit[Math.floor(Math.random() * errorDigit.length)];
randomDigit.style.opacity = '0.8';
randomDigit.style.transform = `translateX(${Math.random() * 5 - 2.5}px)`;
setTimeout(() => {
randomDigit.style.opacity = '1';
randomDigit.style.transform = 'translateX(0)';
}, 100);
}
// Create data corruption effect in background
function createCorruptionEffect() {
const corruptionLine = document.createElement('div');
corruptionLine.classList.add('corruption-line');
// Random positioning and styling
const top = Math.random() * 100;
const width = Math.random() * 100;
const duration = Math.random() * 2 + 0.5;
corruptionLine.style.cssText = `
position: absolute;
top: ${top}%;
left: 0;
height: 1px;
width: ${width}%;
background: rgba(6, 182, 212, 0.4);
z-index: 0;
transform: translateX(-100%);
animation: slideRight ${duration}s forwards ease-out;
`;
errorContainer.appendChild(corruptionLine);
// Remove after animation is complete
setTimeout(() => {
corruptionLine.remove();
}, duration * 1000);
}
// Set intervals for effects
setInterval(glitchEffect, 3000);
setInterval(createCorruptionEffect, 2000);
// Add keyframe animation dynamically
const style = document.createElement('style');
style.innerHTML = `
@keyframes slideRight {
0% { transform: translateX(-100%); }
100% { transform: translateX(100vw); }
}
`;
document.head.appendChild(style);
});
</script>