${heading}
+${message}
+ Go to homepage +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 `
-Something went wrong on our end. You can try refreshing or head back home.
-${message}
+ Go to homepage +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], }));