import { useState } from 'react' import { Network, ShieldAlert } from 'lucide-react' import { useAuth } from '../lib/AuthContext' import { api, ApiError } from '../lib/api' const cardBase: React.CSSProperties = { backgroundColor: 'rgba(10, 10, 12, 0.92)', border: '1px solid rgba(200, 164, 52, 0.12)', borderRadius: '14px', padding: '32px', } const fieldLabel: React.CSSProperties = { fontSize: '11px', color: '#7A7D85', marginBottom: '6px', display: 'block', } const fieldInput: React.CSSProperties = { width: '100%', height: '36px', borderRadius: '8px', border: '1px solid rgba(200,164,52,0.12)', backgroundColor: 'rgba(255,255,255,0.03)', color: '#E8E6E0', fontSize: '13px', padding: '0 12px', outline: 'none', } const goldButton: React.CSSProperties = { height: '38px', borderRadius: '8px', border: 'none', fontSize: '13px', fontWeight: 600, color: '#0A0B0D', backgroundColor: '#C8A434', boxShadow: '0 0 14px rgba(200,164,52,0.2)', padding: '0 20px', } export default function MeshGate() { const { refreshMeshStatus } = useAuth() const [cidr, setCidr] = useState('') const [testIp, setTestIp] = useState('') const [error, setError] = useState(null) const [testResult, setTestResult] = useState<{ ok: boolean; message: string; hostMeshIp: string | null } | null>(null) const [submitting, setSubmitting] = useState(false) const [overriding, setOverriding] = useState(false) async function handleVerify(e: React.FormEvent) { e.preventDefault() setError(null) setTestResult(null) setSubmitting(true) try { const result = await api.verifyMesh(cidr, testIp || undefined) setTestResult(result) if (result.ok) await refreshMeshStatus() } catch (err) { setError(err instanceof ApiError ? err.message : 'Failed to verify mesh') } finally { setSubmitting(false) } } async function handleOverride() { setOverriding(true) try { await api.overrideMesh() await refreshMeshStatus() } catch (err) { setError(err instanceof ApiError ? err.message : 'Failed to skip mesh setup') } finally { setOverriding(false) } } return (

Mesh Setup Required

ArchNest expects this host to be on a private mesh network before the rest of the app can be configured. Works with any mesh — NetBird, WireGuard, ZeroTier, Tailscale, etc. Enter the mesh's IP range below; we verify by checking this host has an address in it.

setCidr(e.target.value)} placeholder="e.g. 100.64.0.0/10 (NetBird/Tailscale CGNAT range)" required /> setTestIp(e.target.value)} placeholder="e.g. 100.64.0.1 — only needed if this host's own IP isn't in the mesh range" />

If this host reaches the mesh through routing instead of holding a local mesh IP (e.g. a VPC peered into the mesh), give us an address on the mesh we can ping to confirm reachability.

{error &&

{error}

} {testResult && (

{testResult.message} {testResult.hostMeshIp && ` — this host's mesh IP: ${testResult.hostMeshIp}`}

)}

Mesh provider down, or setting this up later? You can skip this check for now — it stays skipped until you re-enable it from Settings.

) }