mirror of
https://github.com/DevVoxel/VectorDNS.git
synced 2026-02-27 09:57:39 +00:00
Add documentation pages with interactive architecture diagram
- /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
This commit is contained in:
311
app/docs/architecture/data-flow/page.tsx
Normal file
311
app/docs/architecture/data-flow/page.tsx
Normal file
@@ -0,0 +1,311 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user