From 16ddc55e6b11d503f91e799ac87dea6f3750c892 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Tue, 6 Oct 2026 18:44:22 +0000 Subject: [PATCH 1/2] feat(sh1pt.com): public /api/health with a database check GET /api/health answers 200 {"status":"ok","db":"ok"} after one HEAD select against profiles (3s cap), or 503 {"status":"error","db":"down"}. Cache-Control: no-store. The middleware lets the path straight through the crawl gateway and the www redirect. For status.profullstack.com, which today only checks the home page. Co-Authored-By: Claude Opus 5.5 --- sites/sh1pt.com/app/api/health/route.ts | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 sites/sh1pt.com/app/api/health/route.ts diff --git a/sites/sh1pt.com/app/api/health/route.ts b/sites/sh1pt.com/app/api/health/route.ts new file mode 100644 index 00000000..46653376 --- /dev/null +++ b/sites/sh1pt.com/app/api/health/route.ts @@ -0,0 +1,27 @@ +// Public health check for status.profullstack.com: one HEAD select against +// profiles, capped at 3s. Never returns error details. + +import { NextResponse } from 'next/server'; +import { getSupabaseServiceClient } from '@/lib/supabase/service'; + +export const runtime = 'nodejs'; +export const dynamic = 'force-dynamic'; + +const HEADERS = { 'Cache-Control': 'no-store' }; + +export async function GET() { + try { + const { error } = await getSupabaseServiceClient() + .from('profiles') + .select('id', { head: true }) + .limit(1) + .abortSignal(AbortSignal.timeout(3000)); + if (error) throw error; + return NextResponse.json({ status: 'ok', db: 'ok' }, { headers: HEADERS }); + } catch { + return NextResponse.json( + { status: 'error', db: 'down' }, + { status: 503, headers: HEADERS }, + ); + } +} From 4ff38fb8a7f98b30baab22ff26f95a7367c44de8 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Tue, 6 Oct 2026 18:44:38 +0000 Subject: [PATCH 2/2] fix(sh1pt.com): let /api/health through the middleware Co-Authored-By: Claude Opus 5.5 --- sites/sh1pt.com/middleware.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sites/sh1pt.com/middleware.ts b/sites/sh1pt.com/middleware.ts index 7d95a3ae..5823a9c7 100644 --- a/sites/sh1pt.com/middleware.ts +++ b/sites/sh1pt.com/middleware.ts @@ -2,6 +2,9 @@ import { gate } from "@/lib/crawl-gateway"; import { NextResponse, type NextRequest } from 'next/server'; export async function middleware(request: NextRequest) { + // The status page's health check is never gated or redirected. + if (request.nextUrl.pathname === '/api/health') return NextResponse.next(); + // Crawl gateway first: AI training crawlers get 402 Payment Required (or the // sales page at /crawl) unless they present a paid pass. People, Googlebot // and retrieval crawlers fall through to everything below.