+ {/* Name */}
+
+
+ setFormData({ ...formData, name: e.target.value })}
+ placeholder="e.g. API, Website, CDN"
+ className="w-full px-3 py-2 rounded-lg border border-neutral-300 dark:border-neutral-600 bg-white dark:bg-neutral-800 text-neutral-900 dark:text-white placeholder-neutral-400 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:border-transparent text-sm"
+ />
+
+
+ {/* URL */}
+
+
+
setFormData({ ...formData, url: e.target.value })}
+ placeholder={`https://${siteDomain}`}
+ className="w-full px-3 py-2 rounded-lg border border-neutral-300 dark:border-neutral-600 bg-white dark:bg-neutral-800 text-neutral-900 dark:text-white placeholder-neutral-400 focus:outline-none focus:ring-2 focus:ring-brand-orange focus:border-transparent text-sm"
+ />
+
+ Must be on {siteDomain} or a subdomain (e.g. api.{siteDomain})
+
+
+
+ {/* Check interval */}
+
+
+
+
+
+ {/* Expected status code */}
+
+
+ setFormData({ ...formData, expected_status_code: parseInt(e.target.value) || 200 })}
+ min={100}
+ max={599}
+ className="w-full px-3 py-2 rounded-lg border border-neutral-300 dark:border-neutral-600 bg-white dark:bg-neutral-800 text-neutral-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-brand-orange focus:border-transparent text-sm"
+ />
+
+
+ {/* Timeout */}
+
+
+ setFormData({ ...formData, timeout_seconds: parseInt(e.target.value) || 30 })}
+ min={5}
+ max={60}
+ className="w-full px-3 py-2 rounded-lg border border-neutral-300 dark:border-neutral-600 bg-white dark:bg-neutral-800 text-neutral-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-brand-orange focus:border-transparent text-sm"
+ />
+
+
+ {/* Actions */}
+
+
+
+
+
+ )
+}
diff --git a/lib/api/uptime.ts b/lib/api/uptime.ts
new file mode 100644
index 0000000..5f4ec6f
--- /dev/null
+++ b/lib/api/uptime.ts
@@ -0,0 +1,128 @@
+import apiRequest from './client'
+
+// * Types for uptime monitoring
+
+export interface UptimeMonitor {
+ id: string
+ site_id: string
+ name: string
+ url: string
+ check_interval_seconds: number
+ expected_status_code: number
+ timeout_seconds: number
+ enabled: boolean
+ last_checked_at: string | null
+ last_status: 'up' | 'down' | 'degraded' | 'unknown'
+ last_response_time_ms: number | null
+ created_at: string
+ updated_at: string
+}
+
+export interface UptimeCheck {
+ id: string
+ monitor_id: string
+ status: 'up' | 'down' | 'degraded'
+ response_time_ms: number | null
+ status_code: number | null
+ error_message: string | null
+ checked_at: string
+}
+
+export interface UptimeDailyStat {
+ monitor_id: string
+ date: string
+ total_checks: number
+ successful_checks: number
+ failed_checks: number
+ degraded_checks: number
+ avg_response_time_ms: number
+ min_response_time_ms: number | null
+ max_response_time_ms: number | null
+ uptime_percentage: number
+}
+
+export interface MonitorStatus {
+ monitor: UptimeMonitor
+ daily_stats: UptimeDailyStat[] | null
+ overall_uptime: number
+}
+
+export interface UptimeStatusResponse {
+ monitors: MonitorStatus[] | null
+ overall_uptime: number
+ status: 'operational' | 'degraded' | 'down'
+ total_monitors: number
+}
+
+export interface CreateMonitorRequest {
+ name: string
+ url: string
+ check_interval_seconds?: number
+ expected_status_code?: number
+ timeout_seconds?: number
+}
+
+export interface UpdateMonitorRequest {
+ name: string
+ url: string
+ check_interval_seconds?: number
+ expected_status_code?: number
+ timeout_seconds?: number
+ enabled?: boolean
+}
+
+/**
+ * Fetches the uptime status overview for all monitors of a site
+ */
+export async function getUptimeStatus(siteId: string, startDate?: string, endDate?: string): Promise