/** * Single source of truth for the backend URL used by Next.js server * components. Defaults to localhost in development; throws at *request time* * in production if BACKEND_URL isn't set so a misdeployed container fails * with a clear message instead of silently pointing at localhost. The check * is lazy so Next.js build-time page-data collection doesn't trip it. */ let warned = false; export function getBackendUrl(): string { const explicit = process.env.BACKEND_URL; if (explicit) return explicit; if (process.env.NODE_ENV === "production") { throw new Error( "BACKEND_URL env var is required in production. " + "Set it to the backend service URL (e.g. http://backend:3001).", ); } if (!warned) { warned = true; console.warn("[lib/api] BACKEND_URL unset — defaulting to http://localhost:3001 (dev only)"); } return "http://localhost:3001"; } /** * Fetch JSON from the backend with a default revalidate window. Returns * `null` on network failure or non-2xx status — callers handle the null * to render a graceful fallback instead of crashing the server render. */ export async function apiFetch( path: string, options: { revalidate?: number; noStore?: boolean } = {}, ): Promise { const { revalidate = 60, noStore = false } = options; try { const res = await fetch( `${getBackendUrl()}${path}`, noStore ? { cache: "no-store" } : { next: { revalidate } }, ); if (!res.ok) return null; return (await res.json()) as T; } catch { return null; } }