From 01227f14fdecdb85323b9f5642decc60d8bff508 Mon Sep 17 00:00:00 2001
From: Rito Rhymes <83614463+ritorhymes@users.noreply.github.com>
Date: Wed, 25 Feb 2026 07:38:03 -0500
Subject: [PATCH] 404: add custom page with scoped path handling
404s are served at unknown, often nested URLs, where relative asset
paths can resolve against missing paths instead of site root.
This keeps 404 assets and navigation resolving from the homepage
context without changing URL behavior on normal pages.
The default banner is omitted on 404 so the error state and recovery
action are immediately clear.
---
assets/sass/main.scss | 33 ++++++++++++++++++++++++++++
layouts/404.html | 9 ++++++++
layouts/_default/baseof.html | 11 ++++++++--
static/images/gitgitgadget-logo.png | Bin 0 -> 11266 bytes
4 files changed, 51 insertions(+), 2 deletions(-)
create mode 100644 layouts/404.html
create mode 100644 static/images/gitgitgadget-logo.png
diff --git a/assets/sass/main.scss b/assets/sass/main.scss
index 78a8d21..1e89f60 100644
--- a/assets/sass/main.scss
+++ b/assets/sass/main.scss
@@ -123,3 +123,36 @@ footer nav ul li a {
margin: auto 0px;
}
}
+.not-found {
+ text-align: center;
+ margin: 3rem auto;
+}
+
+.not-found-logo {
+ width: 200px;
+ margin: 0 auto 1.5rem;
+ display: block;
+}
+
+.not-found h1 {
+ margin: 0 0 1rem;
+ font-size: 3rem;
+ font-weight: 700;
+}
+
+.not-found p {
+ margin: 0 0 1rem;
+}
+
+body.page-404 {
+ min-height: 90vh;
+ display: flex;
+ flex-direction: column;
+}
+
+body.page-404 .not-found {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
diff --git a/layouts/404.html b/layouts/404.html
new file mode 100644
index 0000000..252138b
--- /dev/null
+++ b/layouts/404.html
@@ -0,0 +1,9 @@
+{{ define "main" }}
+
+

+
404 Not Found
+
The page you are looking for doesn't exist
+
Return home
+
+{{ partial "footer.html" . }}
+{{ end }}
diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html
index 51254a2..2842872 100644
--- a/layouts/_default/baseof.html
+++ b/layouts/_default/baseof.html
@@ -6,13 +6,20 @@
{{ .Title }}
{{- $canonical := .Permalink | replaceRE "\\.html$" "" -}}
-
+ {{- if eq .Kind "404" }}
+
+ {{- end }}
{{- $style := resources.Get "sass/main.scss" | resources.ExecuteAsTemplate "main.scss" . | css.Sass }}
+
{{- partial "breadcrumbs.html" . -}}
-
+
+ {{- if ne .Kind "404" }}
{{ partial "banner.html" . -}}
+ {{- end }}
{{ block "main" . }}
{{ .Content }}
diff --git a/static/images/gitgitgadget-logo.png b/static/images/gitgitgadget-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..7d7983df4f9dc518a751c1688d2790731dcd58eb
GIT binary patch
literal 11266
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
literal 0
HcmV?d00001