'use client'; import { useEffect, useState } from 'react'; import Link from 'next/link'; import { apiFetch } from '@/lib/api'; import { StatusPill } from '@/components/status-pill'; interface Overview { totals: { users: number; orgs: number; servers: number; liveServers: number; builds: number; failedBuilds: number; toolCalls: number; }; trends: { newUsersLast7d: number; newServersLast7d: number }; statusBreakdown: { status: string; c: number }[]; recentBuilds24h: { status: string; c: number }[]; recentActivity: { id: string; action: string; resourceType: string | null; resourceId: string | null; metadata: Record | null; ipAddress: string | null; createdAt: string; }[]; } export default function AdminOverview() { const [data, setData] = useState(null); useEffect(() => { apiFetch('/v1/admin/overview').then(setData); const t = setInterval(() => apiFetch('/v1/admin/overview').then(setData), 8000); return () => clearInterval(t); }, []); if (!data) { return
Loading…
; } return (

Admin overview

Live system metrics — refreshes every 8 seconds.

{data.statusBreakdown.length === 0 ? ( ) : (
    {data.statusBreakdown.map((row) => (
  • {row.c}
  • ))}
)}
{data.recentBuilds24h.length === 0 ? ( ) : (
    {data.recentBuilds24h.map((row) => (
  • {row.c}
  • ))}
)}

Recent activity

Full audit log →
{data.recentActivity.length === 0 ? ( ) : ( {data.recentActivity.map((e) => ( ))}
When Action Resource IP
{new Date(e.createdAt).toLocaleString()} {e.action} {e.resourceType ? `${e.resourceType}/${e.resourceId?.slice(0, 8) ?? '—'}` : '—'} {e.ipAddress ?? '—'}
)}
); } function Card({ label, value, sub, subRender, }: { label: string; value: number; sub?: string; subRender?: string; }) { return (
{label}
{value.toLocaleString()}
{sub && (
{subRender ?? sub}
)}
); } function Panel({ title, children }: { title: string; children: React.ReactNode }) { return (
{title}
{children}
); } function Empty({ text }: { text: string }) { return

{text}

; }