mirror of
https://github.com/DevVoxel/VectorDNS.git
synced 2026-02-27 09:57:39 +00:00
- /docs route with sidebar navigation and index page - Architecture section: system overview with React Flow diagram, data flow, database schema - API reference, configuration guide, and self-hosting docs for Go DNS server - Feature planning document for future development - Added docs link to landing page nav
312 lines
9.6 KiB
TypeScript
312 lines
9.6 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { ArrowRightLeft, ArrowDown } from "lucide-react";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardHeader,
|
|
CardTitle,
|
|
CardDescription,
|
|
} from "@/components/ui/card";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Separator } from "@/components/ui/separator";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Data Flow",
|
|
};
|
|
|
|
const dnsQuerySteps = [
|
|
{
|
|
step: "1",
|
|
actor: "User",
|
|
action: "Submits a domain name in the VectorDNS UI",
|
|
detail: "Browser sends a request to a Next.js API route on Vercel.",
|
|
},
|
|
{
|
|
step: "2",
|
|
actor: "Next.js API Route",
|
|
action: "Proxies the request to the Go DNS service",
|
|
detail:
|
|
"Adds the shared API key header and forwards to the Go server over HTTPS.",
|
|
},
|
|
{
|
|
step: "3",
|
|
actor: "Go Microservice",
|
|
action: "Resolves DNS records via UDP/TCP",
|
|
detail:
|
|
"Uses miekg/dns to query resolvers (Google 8.8.8.8, Cloudflare 1.1.1.1) or authoritative nameservers directly.",
|
|
},
|
|
{
|
|
step: "4",
|
|
actor: "DNS Resolvers",
|
|
action: "Return DNS records",
|
|
detail:
|
|
"Authoritative nameservers or recursive resolvers respond with the requested record types.",
|
|
},
|
|
{
|
|
step: "5",
|
|
actor: "Go Microservice",
|
|
action: "Returns structured JSON to Next.js",
|
|
detail: "Parsed and normalized DNS records are sent back over HTTPS.",
|
|
},
|
|
{
|
|
step: "6",
|
|
actor: "Next.js",
|
|
action: "Stores results in Supabase & returns to client",
|
|
detail:
|
|
"DNS history is written to Supabase for authenticated users. The response is returned to the browser.",
|
|
},
|
|
];
|
|
|
|
const monitoringSteps = [
|
|
{
|
|
step: "1",
|
|
actor: "Go Cron Job",
|
|
action: "Triggers on a schedule (daily by default)",
|
|
detail:
|
|
"A native Go cron scheduler runs inside the VPS process — no serverless timeouts.",
|
|
},
|
|
{
|
|
step: "2",
|
|
actor: "Go Microservice",
|
|
action: "Fetches monitored domains from Supabase",
|
|
detail:
|
|
"Reads the saved_domains table to get the list of domains and their last-known DNS snapshot.",
|
|
},
|
|
{
|
|
step: "3",
|
|
actor: "Go Microservice",
|
|
action: "Re-queries DNS for each domain",
|
|
detail:
|
|
"Performs fresh DNS lookups and diffs the result against the stored snapshot.",
|
|
},
|
|
{
|
|
step: "4",
|
|
actor: "Go Microservice",
|
|
action: "Detects changes",
|
|
detail:
|
|
"If records changed, writes a new entry to dns_history and availability_history.",
|
|
},
|
|
{
|
|
step: "5",
|
|
actor: "Go Microservice",
|
|
action: "Triggers notifications",
|
|
detail:
|
|
"Writes to the notifications table. Next.js picks these up for in-app display; Resend handles email delivery.",
|
|
},
|
|
];
|
|
|
|
const whoIsSteps = [
|
|
{
|
|
step: "1",
|
|
actor: "User",
|
|
action: "Requests WHOIS data for a domain",
|
|
detail: "Next.js handles this entirely — no Go service involved.",
|
|
},
|
|
{
|
|
step: "2",
|
|
actor: "Next.js API Route",
|
|
action: "Calls the whoiser library",
|
|
detail:
|
|
"whoiser queries the appropriate WHOIS server directly from Vercel.",
|
|
},
|
|
{
|
|
step: "3",
|
|
actor: "Next.js",
|
|
action: "Returns parsed WHOIS data to the client",
|
|
detail: "Registrar, expiry, nameservers, and registration details.",
|
|
},
|
|
];
|
|
|
|
type FlowStep = {
|
|
step: string;
|
|
actor: string;
|
|
action: string;
|
|
detail: string;
|
|
};
|
|
|
|
function FlowSteps({ steps }: { steps: FlowStep[] }) {
|
|
return (
|
|
<div className="space-y-2">
|
|
{steps.map((s, i) => (
|
|
<div key={s.step}>
|
|
<div className="flex gap-4">
|
|
<div className="flex flex-col items-center">
|
|
<div className="flex size-7 shrink-0 items-center justify-center rounded-full bg-primary text-xs font-bold text-primary-foreground">
|
|
{s.step}
|
|
</div>
|
|
{i < steps.length - 1 && (
|
|
<div className="mt-1 flex flex-1 flex-col items-center">
|
|
<div className="w-px flex-1 bg-border" />
|
|
<ArrowDown className="size-3 text-muted-foreground" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="pb-4">
|
|
<div className="flex flex-wrap items-center gap-2">
|
|
<Badge variant="outline" className="text-xs">
|
|
{s.actor}
|
|
</Badge>
|
|
<span className="text-sm font-medium">{s.action}</span>
|
|
</div>
|
|
<p className="mt-1 text-sm text-muted-foreground">{s.detail}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function DataFlowPage() {
|
|
return (
|
|
<div className="space-y-10">
|
|
{/* Page header */}
|
|
<div className="space-y-3">
|
|
<div className="flex items-center gap-2">
|
|
<ArrowRightLeft className="size-6 text-primary" />
|
|
<h1 className="text-3xl font-bold tracking-tight">Data Flow</h1>
|
|
</div>
|
|
<p className="text-lg text-muted-foreground">
|
|
How requests travel through VectorDNS — from the browser through
|
|
Next.js and the Go DNS service to resolvers, and how results are
|
|
stored.
|
|
</p>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
{/* DNS query flow */}
|
|
<div className="space-y-4">
|
|
<div className="space-y-1">
|
|
<h2 className="text-xl font-semibold tracking-tight">
|
|
DNS Record Lookup
|
|
</h2>
|
|
<p className="text-sm text-muted-foreground">
|
|
User-initiated DNS query flow.
|
|
</p>
|
|
</div>
|
|
<Card className="overflow-hidden">
|
|
<CardContent className="p-0">
|
|
<pre className="overflow-x-auto bg-muted/50 p-4 font-mono text-xs text-foreground">
|
|
User → Next.js API Route → Go DNS API → DNS Resolvers
|
|
</pre>
|
|
</CardContent>
|
|
</Card>
|
|
<Card>
|
|
<CardContent className="pt-6">
|
|
<FlowSteps steps={dnsQuerySteps} />
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
{/* Monitoring flow */}
|
|
<div className="space-y-4">
|
|
<div className="space-y-1">
|
|
<h2 className="text-xl font-semibold tracking-tight">
|
|
Domain Monitoring
|
|
</h2>
|
|
<p className="text-sm text-muted-foreground">
|
|
Scheduled background job — runs on the VPS, no user trigger
|
|
required.
|
|
</p>
|
|
</div>
|
|
<Card className="overflow-hidden">
|
|
<CardContent className="p-0">
|
|
<pre className="overflow-x-auto bg-muted/50 p-4 font-mono text-xs text-foreground">
|
|
Go Cron → Supabase (read) → DNS Resolvers → Supabase (write) →
|
|
Notifications
|
|
</pre>
|
|
</CardContent>
|
|
</Card>
|
|
<Card>
|
|
<CardContent className="pt-6">
|
|
<FlowSteps steps={monitoringSteps} />
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
{/* WHOIS flow */}
|
|
<div className="space-y-4">
|
|
<div className="space-y-1">
|
|
<h2 className="text-xl font-semibold tracking-tight">
|
|
WHOIS Lookups
|
|
</h2>
|
|
<p className="text-sm text-muted-foreground">
|
|
Handled entirely by Next.js — the Go service is not involved.
|
|
</p>
|
|
</div>
|
|
<Card className="overflow-hidden">
|
|
<CardContent className="p-0">
|
|
<pre className="overflow-x-auto bg-muted/50 p-4 font-mono text-xs text-foreground">
|
|
User → Next.js API Route (whoiser) → WHOIS Servers
|
|
</pre>
|
|
</CardContent>
|
|
</Card>
|
|
<Card>
|
|
<CardContent className="pt-6">
|
|
<FlowSteps steps={whoIsSteps} />
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
{/* Key design notes */}
|
|
<div className="space-y-4">
|
|
<h2 className="text-xl font-semibold tracking-tight">
|
|
Key Design Notes
|
|
</h2>
|
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-sm">No direct client → Go</CardTitle>
|
|
<CardDescription className="text-sm">
|
|
The browser never calls the Go service directly. All requests go
|
|
through Next.js API routes, which validate the session and add
|
|
the API key.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-sm">
|
|
Persistent process on VPS
|
|
</CardTitle>
|
|
<CardDescription className="text-sm">
|
|
Unlike serverless functions, the Go service runs continuously —
|
|
enabling native cron jobs and long-running monitoring without
|
|
timeout constraints.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-sm">UDP/TCP, not DoH</CardTitle>
|
|
<CardDescription className="text-sm">
|
|
DNS queries use direct UDP/TCP to resolvers or authoritative
|
|
nameservers via miekg/dns — faster and more capable than
|
|
DNS-over-HTTPS.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-sm">
|
|
Supabase as source of truth
|
|
</CardTitle>
|
|
<CardDescription className="text-sm">
|
|
Both Next.js and the Go service read/write Supabase. Row Level
|
|
Security ensures users only access their own data.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|