From 2ae7dc385dfff677cf5cab23b825ce91dc08e3c2 Mon Sep 17 00:00:00 2001 From: SamRepository25 Date: Sat, 10 Oct 2026 14:19:20 +0530 Subject: [PATCH] Add HTTP 500 and 503 error pages --- src/components/MaintenanceGate.tsx | 4 +- src/lib/error-page.ts | 60 +++++++++++++++++++++--------- src/routes/__root.tsx | 2 +- src/start.ts | 45 +++++++++++++++++++++- 4 files changed, 89 insertions(+), 22 deletions(-) diff --git a/src/components/MaintenanceGate.tsx b/src/components/MaintenanceGate.tsx index 6306a60..a0db7ab 100644 --- a/src/components/MaintenanceGate.tsx +++ b/src/components/MaintenanceGate.tsx @@ -7,7 +7,9 @@ import { supabase } from "@/integrations/supabase/client"; const MAINTENANCE_SETTING_KEY = "site.maintenance_mode"; function isAdminOrAuthPath(pathname: string) { - return /^\/(?:auth|mfa-verify|dashboard|admin)(?:\/|$)/.test(pathname); + return /^\/(?:auth|mfa-setup|mfa-verify|forgot-password|reset-password|dashboard|admin)(?:\/|$)/.test( + pathname, + ); } export function MaintenanceGate({ children }: { children: ReactNode }) { diff --git a/src/lib/error-page.ts b/src/lib/error-page.ts index 725235c..5a7e325 100644 --- a/src/lib/error-page.ts +++ b/src/lib/error-page.ts @@ -1,30 +1,54 @@ -export function renderErrorPage(): string { +function renderStatusPage({ + title, + heading, + message, +}: { + title: string; + heading: string; + message: string; +}) { return ` - This page didn't load + ${title} -
-

This page didn't load

-

Something went wrong on our end. You can try refreshing or head back home.

-
- - Go home -
-
+
+
CodeForge
+

${heading}

+

${message}

+ Go to homepage +
`; } + +export function renderErrorPage() { + return renderStatusPage({ + title: "500 — Something went wrong | CodeForge", + heading: "500 — Something went wrong", + message: "An unexpected error occurred on our end. Please try again in a little while.", + }); +} + +export function renderMaintenancePage() { + return renderStatusPage({ + title: "503 — Maintenance in progress | CodeForge", + heading: "We’ll be back soon", + message: + "CodeForge is temporarily unavailable while maintenance is in progress. Please check back shortly.", + }); +} diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 54cb428..08582a5 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -41,7 +41,7 @@ function ErrorComponent({ error, reset }: { error: Error; reset: () => void }) { return (
-

Something went wrong

+

500 — Something went wrong

An unexpected error occurred. Please try again.

diff --git a/src/start.ts b/src/start.ts index 2086427..e3564cc 100644 --- a/src/start.ts +++ b/src/start.ts @@ -1,8 +1,49 @@ import { createStart, createMiddleware } from "@tanstack/react-start"; -import { renderErrorPage } from "./lib/error-page"; +import { renderErrorPage, renderMaintenancePage } from "./lib/error-page"; import { attachSupabaseAuth } from "@/integrations/supabase/auth-attacher"; +const maintenanceSettingKey = "site.maintenance_mode"; + +function isAdminOrAuthPath(pathname: string) { + return /^\/(?:auth|mfa-setup|mfa-verify|forgot-password|reset-password|dashboard|admin)(?:\/|$)/.test( + pathname, + ); +} + +const maintenanceMiddleware = createMiddleware().server(async ({ next, request }) => { + if (request.method !== "GET" || !request.headers.get("accept")?.includes("text/html")) { + return next(); + } + + const pathname = new URL(request.url).pathname; + if (isAdminOrAuthPath(pathname)) return next(); + + try { + const { supabaseAdmin } = await import("@/integrations/supabase/client.server"); + const { data, error } = await supabaseAdmin + .from("site_settings") + .select("value") + .eq("key", maintenanceSettingKey) + .maybeSingle(); + if (error) throw error; + if (data?.value === "true") { + return new Response(renderMaintenancePage(), { + status: 503, + headers: { + "content-type": "text/html; charset=utf-8", + "cache-control": "no-store", + "retry-after": "300", + }, + }); + } + } catch (error) { + console.error("Unable to check CodeForge maintenance mode", error); + } + + return next(); +}); + const errorMiddleware = createMiddleware().server(async ({ next }) => { try { return await next(); @@ -20,5 +61,5 @@ const errorMiddleware = createMiddleware().server(async ({ next }) => { export const startInstance = createStart(() => ({ functionMiddleware: [attachSupabaseAuth], - requestMiddleware: [errorMiddleware], + requestMiddleware: [maintenanceMiddleware, errorMiddleware], }));