Files
leadchat/public/404.html
Sojan Jose b2cb3717e5 fix: Replace default Rails error pages with custom designs (#13514)
## Summary

- Replace generic Rails 404, 422, and 500 error pages with
custom-designed pages
- Each page features a prominent gradient error code, clean typography,
and a "Back to home" CTA
- Full dark mode support via `prefers-color-scheme` media query  
- Mobile responsive design  
- No external dependencies (self-contained static HTML, works even when
Rails is down)
- No logo/branding to ensure compatibility with custom-branded
self-hosted instances

---

## Before (default Rails 404)

<img width="2400" height="1998" alt="old-404"
src="https://github.com/user-attachments/assets/c5f044c4-aab6-40e9-aa11-6096ed9d2b42"
/>

---

## After

### Light mode

| 404 | 422 | 500 |
|-----|-----|-----|
| <img width="600" alt="new-404-light"
src="https://github.com/user-attachments/assets/1826c812-0eb9-4219-bdd2-026c54b53123"
/> | <img width="600" alt="new-422-light"
src="https://github.com/user-attachments/assets/d72ffdbf-b61e-4f53-a16b-4ee81103124f"
/> | <img width="600" alt="new-500-light"
src="https://github.com/user-attachments/assets/81bbdb24-bfe7-43a1-b584-f37f71e3bded"
/> |

---

### Dark mode

| 404 | 422 | 500 |
|-----|-----|-----|
| <img width="600" alt="new-404-dark"
src="https://github.com/user-attachments/assets/bd323915-bfb9-48c1-885d-96ff263b4ae0"
/> | <img width="600" alt="new-422-dark"
src="https://github.com/user-attachments/assets/dcb08eca-aee5-4e36-9690-f44da13e8d88"
/> | <img width="600" alt="new-500-dark"
src="https://github.com/user-attachments/assets/538c3c2c-b9dc-406c-9932-ff8897b64790"
/> |

---

## Test plan

Easier way to verify:

- [ ] Visit `/404.html` directly to verify the 404 page  
- [ ] Visit `/422.html` directly to verify the 422 page  
- [ ] Visit `/500.html` directly to verify the 500 page  

Full verification:

- [ ] Visit a non-existent route in production mode to verify the 404
page
- [ ] Trigger a 422 error (e.g., invalid CSRF token) to verify the 422
page
- [ ] Trigger a 500 error to verify the 500 page  
- [ ] Toggle system dark mode and verify all pages render correctly  
- [ ] Test on mobile viewport widths
2026-02-11 07:57:00 -08:00

109 lines
3.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Page not found</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Tahoma, Arial, sans-serif;
background: rgba(39, 129, 246, 0.05);
color: rgb(28, 32, 36);
padding: 2rem 1.5rem;
-webkit-font-smoothing: antialiased;
}
.page {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
max-width: 28rem;
}
.error-number {
font-size: 8rem;
font-weight: 700;
line-height: 1;
letter-spacing: -0.04em;
background: linear-gradient(180deg, rgb(39, 129, 246) 0%, rgb(155, 195, 252) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 1.5rem;
}
h1 {
font-size: 1.5rem;
font-weight: 600;
line-height: 1.3;
text-align: center;
margin-bottom: 0.5rem;
}
.description {
font-size: 0.9375rem;
color: rgb(96, 100, 108);
line-height: 1.6;
text-align: center;
margin-bottom: 2.5rem;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
background: rgb(39, 129, 246);
color: #fff;
font-size: 0.9375rem;
font-weight: 500;
padding: 0.75rem 2rem;
border-radius: 0.625rem;
text-decoration: none;
transition: background 0.15s ease;
}
.btn:hover { background: rgb(16, 115, 233); }
.btn svg { width: 1.125rem; height: 1.125rem; }
.divider {
width: 3rem;
height: 2px;
background: rgb(224, 225, 230);
border-radius: 1px;
margin: 2.5rem 0;
}
.help {
font-size: 0.8125rem;
color: rgb(139, 141, 152);
text-align: center;
line-height: 1.5;
}
@media (prefers-color-scheme: dark) {
body { background: rgb(17, 17, 19); color: rgb(237, 238, 240); }
.error-number { background: linear-gradient(180deg, rgb(126, 182, 255) 0%, rgb(40, 89, 156) 100%); -webkit-background-clip: text; background-clip: text; }
.description { color: rgb(176, 180, 186); }
.divider { background: rgb(46, 49, 53); }
.help { color: rgb(105, 110, 119); }
}
@media (max-width: 480px) {
.error-number { font-size: 5rem; }
h1 { font-size: 1.25rem; }
}
</style>
</head>
<body>
<div class="page">
<div class="error-number">404</div>
<h1>Page not found</h1>
<p class="description">The page you're looking for doesn't exist or has been moved.</p>
<a href="/" class="btn">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18" /></svg>
Back to home
</a>
<div class="divider"></div>
<p class="help">If you think this is a mistake, please reach out to support.</p>
</div>
</body>
</html>