A browser navigation (Sec-Fetch-Mode navigate, or GET/HEAD without it; no X-Requested-With; Accept naming text/html above every JSON type; not /api, /_<name> or the admin prefix) that hits a framework-generated 404, 405 or 500 gets a self-contained SummerCMS page: unmatched routes and wrong methods at the ServeMux, failed Where/WhereIn constraints, overlap-family misses, the unpublished uploads route and recovered panics. Every other request keeps the exact stdlib text, wire's opaque JSON 500 or the bare raw-group 500. Details (method, path, X-Request-Id) only with app.debug or outside production. Applications replace the page with a published surf.ErrorPageRenderer; http.error_pages.enabled false turns it off.
122 lines
3.4 KiB
HTML
122 lines
3.4 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="robots" content="noindex">
|
|
<title>{{.Status}} · {{.Title}} · SummerCMS</title>
|
|
<link rel="icon" type="image/webp" href="{{.Logo}}">
|
|
<style>
|
|
*, *::before, *::after { box-sizing: border-box; }
|
|
html, body { margin: 0; padding: 0; }
|
|
body {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 24px;
|
|
background-color: #233148;
|
|
background-image: radial-gradient(ellipse 80% 50% at 50% 0%, rgba(245, 197, 90, 0.10), rgba(245, 197, 90, 0) 70%);
|
|
color: #e9edf3;
|
|
font-family: Roboto, system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
font-size: 16px;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
.card {
|
|
width: 100%;
|
|
max-width: 480px;
|
|
padding: 40px 32px;
|
|
background: #29344a;
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
border-radius: 16px;
|
|
box-shadow: 0 24px 48px rgba(0, 0, 0, 0.28), 0 2px 6px rgba(0, 0, 0, 0.18);
|
|
text-align: center;
|
|
}
|
|
.brand {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 24px;
|
|
}
|
|
.brand img { width: 60px; height: 60px; display: block; }
|
|
.wordmark { font-size: 18px; font-weight: 700; letter-spacing: 0.01em; color: #e9edf3; }
|
|
.gold { color: #fbd77e; }
|
|
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
|
|
.gold {
|
|
background-image: linear-gradient(135deg, #fde9b4 0%, #f5c55a 100%);
|
|
-webkit-background-clip: text;
|
|
background-clip: text;
|
|
color: transparent;
|
|
}
|
|
}
|
|
.status {
|
|
display: inline-block;
|
|
margin: 0;
|
|
font-size: 72px;
|
|
font-weight: 700;
|
|
line-height: 1;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
h1 { margin: 16px 0 8px; font-size: 22px; font-weight: 600; line-height: 1.3; color: #e9edf3; }
|
|
.message { margin: 0 0 28px; color: #a3adbd; line-height: 1.6; }
|
|
.home {
|
|
display: inline-block;
|
|
padding: 10px 24px;
|
|
background: #f5c55a;
|
|
color: #1d2940;
|
|
border-radius: 999px;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
transition: background-color 0.15s ease;
|
|
}
|
|
.home:hover { background: #fbd77e; }
|
|
.home:focus-visible { outline: 2px solid #fbe3a6; outline-offset: 3px; }
|
|
.details {
|
|
margin: 28px 0 0;
|
|
padding: 14px 16px;
|
|
background: #18223a;
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
border-radius: 6px;
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 6px 14px;
|
|
text-align: left;
|
|
font-family: "Roboto Mono", ui-monospace, monospace;
|
|
font-size: 13px;
|
|
}
|
|
.details dt { color: #8a94a3; }
|
|
.details dd { margin: 0; color: #c5ccd6; word-break: break-all; }
|
|
.caption { margin: 28px 0 0; font-size: 12px; color: #8a94a3; }
|
|
@media (max-width: 520px) {
|
|
body { padding: 16px; }
|
|
.card { padding: 28px 20px; }
|
|
.status { font-size: 56px; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<main class="card">
|
|
<div class="brand">
|
|
<img src="{{.Logo}}" width="60" height="60" alt="SummerCMS">
|
|
<span class="wordmark">Summer<span class="gold">CMS</span></span>
|
|
</div>
|
|
<p class="status gold">{{.Status}}</p>
|
|
<h1>{{.Title}}</h1>
|
|
<p class="message">{{.Message}}</p>
|
|
<a class="home" href="{{.Home}}">Go to the home page</a>
|
|
{{- if .ShowDetails}}
|
|
<dl class="details">
|
|
<dt>Status</dt><dd>{{.Status}}</dd>
|
|
<dt>Method</dt><dd>{{.Method}}</dd>
|
|
<dt>Path</dt><dd>{{.Path}}</dd>
|
|
{{- if .RequestID}}
|
|
<dt>Request ID</dt><dd>{{.RequestID}}</dd>
|
|
{{- end}}
|
|
</dl>
|
|
{{- end}}
|
|
<p class="caption">Powered by SummerCMS</p>
|
|
</main>
|
|
</body>
|
|
</html>
|