'use client' import { useEffect, useState } from 'react' import { Globe, ChevronRight, ChevronDown, RefreshCw, ExternalLink, Shield, AlertCircle } from 'lucide-react' interface Zone { id: string; name: string; status: string; nameservers: string[]; plan: string; recordCount: number | null } interface DnsRecord { id: string; type: string; name: string; content: string; ttl: number; proxied: boolean } const TYPE_COLORS: Record = { A: '#22c55e', AAAA: '#2979FF', CNAME: '#F5A623', MX: '#9C27B0', TXT: '#06b6d4', NS: '#aaa', SRV: '#FF1D6C', CAA: '#f97316', } export default function DnsPage() { const [zones, setZones] = useState([]) const [loading, setLoading] = useState(true) const [expanded, setExpanded] = useState(null) const [records, setRecords] = useState>({}) const [loadingZone, setLoadingZone] = useState(null) const [live, setLive] = useState(false) const [search, setSearch] = useState('') useEffect(() => { fetch('/api/dns').then(r => r.json()).then(d => { setZones(d.zones || []) setLive(d.live ?? false) setLoading(false) }).catch(() => setLoading(false)) }, []) const toggleZone = async (zone: Zone) => { if (expanded === zone.id) { setExpanded(null); return } setExpanded(zone.id) if (!records[zone.id] && live && zone.id !== `zone-${zones.indexOf(zone)}`) { setLoadingZone(zone.id) try { const r = await fetch(`/api/dns?zone=${zone.id}`) const d = await r.json() setRecords(prev => ({ ...prev, [zone.id]: d.records || [] })) } finally { setLoadingZone(null) } } } const filtered = zones.filter(z => !search || z.name.includes(search.toLowerCase())) return (

DNS Zones

{zones.length} zones · Cloudflare {live ? '● live' : '○ cached'}

{!live && (
Set CLOUDFLARE_API_TOKEN for live data
)}
setSearch(e.target.value)} placeholder="Search zones…" style={{ width: '100%', background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 8, padding: '10px 14px', color: '#fff', fontSize: 13, outline: 'none', marginBottom: 16, boxSizing: 'border-box' }} /> {loading ? (
Loading zones…
) : (
{filtered.map(zone => (
toggleZone(zone)} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 18px', cursor: 'pointer' }}> {expanded === zone.id ? : } {expanded === zone.id && (
{/* Nameservers */}
Nameservers
{zone.nameservers.map(ns => ( {ns} ))}
{/* DNS Records */} {loadingZone === zone.id ? (
Loading records…
) : records[zone.id]?.length ? (
DNS Records ({records[zone.id].length})
{records[zone.id].map(rec => (
{rec.type} {rec.name} {rec.content} {rec.proxied && ☁ proxied}
))}
) : (
{live ? 'No records found' : 'Add CLOUDFLARE_API_TOKEN to Vercel env to view DNS records'}
)}
)}
))}
)}
) }