import Link from "next/link"; import { UPTIME_REPORT_URL } from "@/lib/env-config"; type UptimeStatus = "up" | "down"; interface LocationStat { uptime_status: UptimeStatus; response_time: number | null; last_check: number; } interface UptimeMonitor { id: string; name: string; type: string; target: string; last_check: number; uptime_status: UptimeStatus; monitor_status: string; uptime: number; locations?: Record; } interface UptimeMonitorsApiResponse { monitors?: unknown[]; } const HETRIXTOOLS_API_BASE = "https://api.hetrixtools.com/v3"; function formatTimestamp(timestamp: number) { if (!Number.isFinite(timestamp) || timestamp <= 0) return "n/a"; return new Date(timestamp * 1000).toLocaleString(); } function formatLocationName(location: string) { return location .replaceAll("_", " ") .split(" ") .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) .join(" "); } function toNumber(value: unknown, fallback = 0) { if (typeof value === "number" && Number.isFinite(value)) return value; if (typeof value === "string") { const parsed = Number.parseFloat(value); if (Number.isFinite(parsed)) return parsed; } return fallback; } function normalizeUptimeStatus(value: unknown): UptimeStatus { return value === "down" ? "down" : "up"; } function normalizeMonitor(rawMonitor: unknown): UptimeMonitor | null { if (!rawMonitor || typeof rawMonitor !== "object") return null; const monitor = rawMonitor as Record; const rawLocations = monitor.locations && typeof monitor.locations === "object" ? (monitor.locations as Record) : {}; const locations: Record = {}; for (const [locationName, rawLocation] of Object.entries(rawLocations)) { if (!rawLocation || typeof rawLocation !== "object") continue; const location = rawLocation as Record; locations[locationName] = { uptime_status: normalizeUptimeStatus(location.uptime_status), response_time: location.response_time === null ? null : toNumber(location.response_time, 0), last_check: toNumber(location.last_check, 0), }; } return { id: String(monitor.id ?? ""), name: String(monitor.name ?? "Unnamed monitor"), type: String(monitor.type ?? ""), target: String(monitor.target ?? ""), last_check: toNumber(monitor.last_check, 0), uptime_status: normalizeUptimeStatus(monitor.uptime_status), monitor_status: String(monitor.monitor_status ?? "unknown"), uptime: toNumber(monitor.uptime, 0), locations, }; } async function fetchUptimeMonitors(): Promise<{ monitors: UptimeMonitor[]; error?: string; }> { const apiKey = process.env.HETRIXTOOLS_API_KEY; const monitorId = process.env.HETRIXTOOLS_MONITOR_ID; if (!apiKey) { return { monitors: [], error: "Missing HETRIXTOOLS_API_KEY. Add it to your server environment to enable custom uptime UI.", }; } const query = monitorId ? `id=${encodeURIComponent(monitorId)}` : "per_page=20&page=1&order_by=last_check&order=desc"; try { const response = await fetch(`${HETRIXTOOLS_API_BASE}/uptime-monitors?${query}`, { method: "GET", headers: { Authorization: `Bearer ${apiKey}`, }, next: { revalidate: 60 }, }); if (!response.ok) { return { monitors: [], error: `HetrixTools API request failed (${response.status}).`, }; } const data = (await response.json()) as UptimeMonitorsApiResponse; const monitors = (data.monitors ?? []) .map((monitor) => normalizeMonitor(monitor)) .filter((monitor): monitor is UptimeMonitor => monitor !== null); return { monitors }; } catch { return { monitors: [], error: "Could not reach HetrixTools API from the server.", }; } } export default async function UptimePage() { const { monitors, error } = await fetchUptimeMonitors(); return (

System Status

SurfSense uptime dashboard

Open original report Source: HetrixTools v3 API (`/uptime-monitors`).
{error ? (

Unable to load custom uptime data

{error}

) : monitors.length === 0 ? (
No uptime monitors returned by HetrixTools API.
) : (
{monitors.map((monitor) => { const locations = Object.entries(monitor.locations ?? {}); const isUp = monitor.uptime_status === "up"; return (

{monitor.name}

{monitor.target || "No target shown"}

{isUp ? "Operational" : "Outage"}

Uptime

{monitor.uptime.toFixed(4)}%

Last check

{formatTimestamp(monitor.last_check)}

Monitor status

{monitor.monitor_status.replaceAll("_", " ")}

{locations.length > 0 && (

Locations

{locations.map(([locationName, locationData]) => (

{formatLocationName(locationName)}

{locationData.uptime_status === "up" ? "Up" : "Down"} ยท{" "} {locationData.response_time ?? "n/a"} ms

))}
)}
); })}
)}
); }