Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions error-404.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{{!< default}}

{{!--
404 page. Inherits the default layout so visitors keep the theme's
navigation, footer, and overall look while they figure out where to go.
--}}

<main class="gh-main">

<article class="gh-article gh-canvas">

<header class="gh-article-header">
<h1 class="gh-article-title is-title">{{statusCode}}</h1>
<p class="gh-article-excerpt is-body">{{t "Page not found"}}</p>
</header>

<section class="gh-content is-body">
<p>
<a href="{{@site.url}}" class="gh-button">{{t "Go to the front page →"}}</a>
</p>
</section>

</article>

</main>

{{!-- Visitors landing here didn't find what they were looking for.
Suggest a few recent posts to help them re-engage. --}}
{{#get "posts" include="authors" limit="3" as |suggested|}}
{{#if suggested}}
<section class="gh-container is-grid gh-outer">
<div class="gh-container-inner gh-inner">
<h2 class="gh-container-title">{{t "Recent posts"}}</h2>
<main class="gh-main">
<div class="gh-feed">
{{#foreach suggested}}
{{> "post-card" lazyLoad=true}}
{{/foreach}}
</div>
</main>
Comment on lines +34 to +40
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify how many main landmarks are present in the template
FILE="$(fd '^error-404\.hbs$' | head -n1)"
rg -n '<main\b|</main>' "$FILE"

Repository: TryGhost/Source

Length of output: 164


🏁 Script executed:

#!/bin/bash
FILE="$(fd '^error-404\.hbs$' | head -n1)"
echo "FILE=$FILE"
nl -ba "$FILE" | sed -n '1,80p'

Repository: TryGhost/Source

Length of output: 137


🏁 Script executed:

#!/bin/bash
FILE="$(fd '^error-404\.hbs$' | head -n1)"
echo "FILE=$FILE"

echo "---- all <main> / </main> occurrences ----"
rg -n '<main\b|</main>' "$FILE"

echo "---- lines 1-80 with numbers (awk) ----"
awk '{printf "%d:%s\n", NR, $0}' "$FILE" | sed -n '1,80p'

Repository: TryGhost/Source

Length of output: 1786


🏁 Script executed:

#!/bin/bash
# Verify how many main landmarks are present in the template
FILE="$(fd '^error-404\.hbs$' | head -n1)"
rg -n '<main\b|</main>' "$FILE"

Repository: TryGhost/Source

Length of output: 164


Avoid a second <main> landmark in error-404.hbs

error-404.hbs already has a <main class="gh-main"> at the top, and lines 34-40 add another <main class="gh-main"> around the “Recent posts” feed, creating landmark ambiguity for screen readers. Switch the inner wrapper to a non-landmark element while keeping the styling class.

♻️ Proposed fix
-                <main class="gh-main">
+                <div class="gh-main">
                     <div class="gh-feed">
                         {{`#foreach` suggested}}
                             {{> "post-card" lazyLoad=true}}
                         {{/foreach}}
                     </div>
-                </main>
+                </div>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@error-404.hbs` around lines 34 - 40, The template introduces a second main
landmark by wrapping the suggested posts in <main class="gh-main">; replace that
inner <main> with a non-landmark element (e.g., <div> or <section>) while
preserving class="gh-main" and the existing {{`#foreach` suggested}} ... {{>
"post-card" lazyLoad=true}} block so styling and behavior remain unchanged;
update the element surrounding the suggested feed in error-404.hbs where the
inner main is declared.

</div>
</section>
{{/if}}
{{/get}}
66 changes: 66 additions & 0 deletions error.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{{!--
Generic error template — handles all non-404 errors (500, etc.).
Standalone (doesn't extend default.hbs) and kept lightweight on
purpose: minimal dependencies, no partials, no API calls.

The reasoning mirrors Casper's: 500 errors usually happen when
something on the server is struggling, so we don't want the error
page itself to compound the issue. Keep this template as
self-contained as possible.
--}}

<!DOCTYPE html>
<html lang="{{@site.locale}}">
<head>
<title>{{meta_title}}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}">
<style>
:root {
--background-color: {{@custom.site_background_color}}
}
</style>
{{ghost_head}}
</head>
<body class="{{body_class}}">

Comment on lines +19 to +27
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Missing contrast-class handling can make error text unreadable on custom backgrounds.

error.hbs sets --background-color but doesn’t apply the has-dark-text/has-light-text class behavior used by default.hbs, so foreground contrast can break on some custom colors.

Suggested fix
 <body class="{{body_class}}">
+<script>
+    var accentColor = getComputedStyle(document.documentElement).getPropertyValue('--background-color').trim().slice(1);
+    if (accentColor.length === 3) {
+        accentColor = accentColor[0] + accentColor[0] + accentColor[1] + accentColor[1] + accentColor[2] + accentColor[2];
+    }
+    var r = parseInt(accentColor.substr(0, 2), 16);
+    var g = parseInt(accentColor.substr(2, 2), 16);
+    var b = parseInt(accentColor.substr(4, 2), 16);
+    var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
+    document.documentElement.className = `has-${yiq >= 128 ? 'dark' : 'light'}-text`;
+</script>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<style>
:root {
--background-color: {{@custom.site_background_color}}
}
</style>
{{ghost_head}}
</head>
<body class="{{body_class}}">
<style>
:root {
--background-color: {{`@custom.site_background_color`}}
}
</style>
{{ghost_head}}
</head>
<body class="{{body_class}}">
<script>
var accentColor = getComputedStyle(document.documentElement).getPropertyValue('--background-color').trim().slice(1);
if (accentColor.length === 3) {
accentColor = accentColor[0] + accentColor[0] + accentColor[1] + accentColor[1] + accentColor[2] + accentColor[2];
}
var r = parseInt(accentColor.substr(0, 2), 16);
var g = parseInt(accentColor.substr(2, 2), 16);
var b = parseInt(accentColor.substr(4, 2), 16);
var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
document.documentElement.className = `has-${yiq >= 128 ? 'dark' : 'light'}-text`;
</script>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@error.hbs` around lines 19 - 27, error.hbs sets --background-color
({{`@custom.site_background_color`}}) but never applies the contrast class used in
default.hbs, so add the same contrast-class logic: determine whether the
provided {{`@custom.site_background_color`}} is light or dark (reusing the
helper/logic from default.hbs or the theme's color-to-contrast utility) and add
either "has-dark-text" or "has-light-text" to the <body class="{{body_class}}">
element so foreground styles follow the correct contrast; locate the
contrast-detection used in default.hbs (or its helper) and call it here, or
insert a minimal inline script that computes luminance from
{{`@custom.site_background_color`}} and sets the body class accordingly.

<main class="gh-main">

<article class="gh-article gh-canvas">

<header class="gh-article-header">
<h1 class="gh-article-title is-title">{{statusCode}}</h1>
<p class="gh-article-excerpt is-body">{{message}}</p>
</header>

<section class="gh-content is-body">
<p>
<a href="{{@site.url}}" class="gh-button">{{t "Go to the front page →"}}</a>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove theme helpers from generic error template

In error.hbs, using {{t}} makes the generic error page depend on a theme helper even though Ghost’s error-template contract expects error.hbs to avoid theme helpers (except asset) to reduce cascading failures and misleading diagnostics during 5xx handling. If the original failure is related to helper/theme rendering, this can cause the error template itself to fail or mask the root cause. Replace translated helper output here with static text (or move helper-dependent UX to error-404.hbs, where helpers are allowed).

Useful? React with 👍 / 👎.

</p>
</section>

{{#if errorDetails}}
<section class="gh-content is-body">
<h3>{{t "Theme errors"}}</h3>
<ul>
{{#foreach errorDetails}}
<li>
<strong>{{rule}}</strong>
{{#foreach failures}}
<p>{{ref}}: {{message}}</p>
{{/foreach}}
</li>
{{/foreach}}
</ul>
</section>
{{/if}}

</article>

</main>

{{ghost_foot}}

</body>
</html>
1 change: 1 addition & 0 deletions locales/context.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "solo/post.hbs",
"Older Posts": "ghost-tpl/pagination.hbs",
"Page {page} of {totalPages}": "alto/partials/pagination.hbs, ghost-tpl/pagination.hbs",
"Page not found": "Friendly message shown on 404 pages",
"Paid": "solo/partials/loop.hbs",
"Paid-members only": "casper/partials/post-card.hbs",
"Please enter a valid email address": "ghost-private/private.hbs",
Expand Down
1 change: 1 addition & 0 deletions locales/de-CH.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "Weiter →",
"Older Posts": "Ältere Beiträge",
"Page {page} of {totalPages}": "Seite {page} von {totalPages}",
"Page not found": "",
"Paid": "Kostenpflichtig",
"Paid-members only": "Nur für zahlende Mitglieder",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "Suivant →",
"Older Posts": "Publications plus anciennes",
"Page {page} of {totalPages}": "Page {page} sur {totalPages}",
"Page not found": "Page introuvable",
"Paid": "Payant",
"Paid-members only": "Réservé aux abonnés payants",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/ga.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/gd.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/sv.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "Sonraki →",
"Older Posts": "Daha Eski Yazılar",
"Page {page} of {totalPages}": "Sayfa {page} / {totalPages}",
"Page not found": "",
"Paid": "Ücretli",
"Paid-members only": "Ücretli üyelere özel",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "Далі →",
"Older Posts": "Старіші дописи",
"Page {page} of {totalPages}": "Сторінка {page} з {totalPages}",
"Page not found": "",
"Paid": "Платний",
"Paid-members only": "Тільки за платною підпискою",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/zh-Hant.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "付費會員限定",
"Please enter a valid email address": "",
Expand Down
1 change: 1 addition & 0 deletions locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"Next →": "",
"Older Posts": "",
"Page {page} of {totalPages}": "",
"Page not found": "",
"Paid": "",
"Paid-members only": "",
"Please enter a valid email address": "",
Expand Down