mirror of
https://github.com/DevVoxel/VectorDNS.git
synced 2026-02-27 05:47:38 +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:
193
components/docs/architecture-diagram.tsx
Normal file
193
components/docs/architecture-diagram.tsx
Normal file
@@ -0,0 +1,193 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ReactFlow,
|
||||
Background,
|
||||
type Node,
|
||||
type Edge,
|
||||
type NodeProps,
|
||||
Handle,
|
||||
Position,
|
||||
} from "@xyflow/react";
|
||||
import "@xyflow/react/dist/style.css";
|
||||
import { Globe, Server, Database, Wifi } from "lucide-react";
|
||||
|
||||
type ServiceNodeData = {
|
||||
label: string;
|
||||
subtitle: string;
|
||||
icon: React.ElementType;
|
||||
color: string;
|
||||
items?: string[];
|
||||
};
|
||||
|
||||
function ServiceNode({ data }: NodeProps<Node<ServiceNodeData>>) {
|
||||
const Icon = data.icon;
|
||||
return (
|
||||
<div
|
||||
className="rounded-lg border bg-card px-5 py-4 shadow-sm"
|
||||
style={{ minWidth: 200 }}
|
||||
>
|
||||
<Handle type="target" position={Position.Top} className="opacity-0" />
|
||||
<Handle type="source" position={Position.Bottom} className="opacity-0" />
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
id="right"
|
||||
className="opacity-0"
|
||||
/>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
id="left"
|
||||
className="opacity-0"
|
||||
/>
|
||||
<div className="flex items-center gap-2.5">
|
||||
<div
|
||||
className="flex size-8 items-center justify-center rounded-md"
|
||||
style={{ backgroundColor: data.color }}
|
||||
>
|
||||
<Icon className="size-4 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-semibold text-foreground">
|
||||
{data.label}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">{data.subtitle}</div>
|
||||
</div>
|
||||
</div>
|
||||
{data.items && (
|
||||
<ul className="mt-3 space-y-1 border-t pt-3">
|
||||
{data.items.map((item) => (
|
||||
<li
|
||||
key={item}
|
||||
className="flex items-center gap-1.5 text-[11px] text-muted-foreground"
|
||||
>
|
||||
<span
|
||||
className="size-1 shrink-0 rounded-full"
|
||||
style={{ backgroundColor: data.color }}
|
||||
/>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const nodeTypes = { service: ServiceNode };
|
||||
|
||||
const nodes: Node<ServiceNodeData>[] = [
|
||||
{
|
||||
id: "nextjs",
|
||||
type: "service",
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
label: "Next.js",
|
||||
subtitle: "Vercel (Frontend)",
|
||||
icon: Globe,
|
||||
color: "#3b82f6",
|
||||
items: ["UI / SSR", "Auth (Supabase)", "WHOIS lookups", "Static pages"],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "go",
|
||||
type: "service",
|
||||
position: { x: 350, y: 0 },
|
||||
data: {
|
||||
label: "Go DNS API",
|
||||
subtitle: "VPS (Microservice)",
|
||||
icon: Server,
|
||||
color: "#10b981",
|
||||
items: [
|
||||
"DNS resolution (miekg/dns)",
|
||||
"DNSSEC validation",
|
||||
"Propagation checks",
|
||||
"Monitoring cron",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "supabase",
|
||||
type: "service",
|
||||
position: { x: 0, y: 230 },
|
||||
data: {
|
||||
label: "Supabase",
|
||||
subtitle: "Database & Auth",
|
||||
icon: Database,
|
||||
color: "#8b5cf6",
|
||||
items: ["Postgres DB", "Auth (OAuth + email)", "Row Level Security"],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "dns",
|
||||
type: "service",
|
||||
position: { x: 350, y: 230 },
|
||||
data: {
|
||||
label: "DNS Resolvers",
|
||||
subtitle: "Authoritative NS",
|
||||
icon: Wifi,
|
||||
color: "#f59e0b",
|
||||
items: ["Google (8.8.8.8)", "Cloudflare (1.1.1.1)", "Authoritative NS"],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const edges: Edge[] = [
|
||||
{
|
||||
id: "nextjs-go",
|
||||
source: "nextjs",
|
||||
target: "go",
|
||||
sourceHandle: "right",
|
||||
targetHandle: "left",
|
||||
label: "HTTPS",
|
||||
animated: true,
|
||||
style: { stroke: "#3b82f6" },
|
||||
labelStyle: { fontSize: 15, fill: "#94a3b8", fontWeight: "bold" },
|
||||
labelBgStyle: { fill: "transparent" },
|
||||
},
|
||||
{
|
||||
id: "nextjs-supabase",
|
||||
source: "nextjs",
|
||||
target: "supabase",
|
||||
label: "SDK",
|
||||
style: { stroke: "#8b5cf6" },
|
||||
labelStyle: { fontSize: 15, fill: "#94a3b8", fontWeight: "bold" },
|
||||
labelBgStyle: { fill: "transparent" },
|
||||
},
|
||||
{
|
||||
id: "go-dns",
|
||||
source: "go",
|
||||
target: "dns",
|
||||
label: "UDP/TCP",
|
||||
animated: true,
|
||||
style: { stroke: "#10b981" },
|
||||
labelStyle: { fontSize: 15, fill: "#94a3b8", fontWeight: "bold" },
|
||||
labelBgStyle: { fill: "transparent" },
|
||||
},
|
||||
];
|
||||
|
||||
export function ArchitectureDiagram() {
|
||||
return (
|
||||
<div className="h-105 w-full rounded-lg border bg-background">
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
nodeTypes={nodeTypes}
|
||||
fitView
|
||||
fitViewOptions={{ padding: 0.3 }}
|
||||
proOptions={{ hideAttribution: true }}
|
||||
nodesDraggable={false}
|
||||
nodesConnectable={false}
|
||||
elementsSelectable={false}
|
||||
panOnDrag={false}
|
||||
zoomOnScroll={false}
|
||||
zoomOnPinch={false}
|
||||
zoomOnDoubleClick={false}
|
||||
preventScrolling={false}
|
||||
>
|
||||
<Background gap={20} size={1} className="opacity-30" />
|
||||
</ReactFlow>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
85
components/docs/sidebar.tsx
Normal file
85
components/docs/sidebar.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import {
|
||||
BookOpen,
|
||||
Layers,
|
||||
ArrowRightLeft,
|
||||
Database,
|
||||
FileCode,
|
||||
Settings,
|
||||
Server,
|
||||
} from "lucide-react";
|
||||
|
||||
const sections = [
|
||||
{
|
||||
title: "Getting Started",
|
||||
items: [{ title: "Overview", href: "/docs", icon: BookOpen }],
|
||||
},
|
||||
{
|
||||
title: "Architecture",
|
||||
items: [
|
||||
{ title: "System Overview", href: "/docs/architecture", icon: Layers },
|
||||
{
|
||||
title: "Data Flow",
|
||||
href: "/docs/architecture/data-flow",
|
||||
icon: ArrowRightLeft,
|
||||
},
|
||||
{
|
||||
title: "Database Schema",
|
||||
href: "/docs/architecture/database",
|
||||
icon: Database,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "API",
|
||||
items: [
|
||||
{ title: "API Reference", href: "/docs/api", icon: FileCode },
|
||||
{ title: "Configuration", href: "/docs/configuration", icon: Settings },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Deployment",
|
||||
items: [
|
||||
{ title: "Self-Hosting", href: "/docs/self-hosting", icon: Server },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export function DocsSidebar() {
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
<nav className="space-y-6">
|
||||
{sections.map((section) => (
|
||||
<div key={section.title}>
|
||||
<h4 className="mb-2 text-sm font-semibold tracking-tight text-muted-foreground">
|
||||
{section.title}
|
||||
</h4>
|
||||
<ul className="space-y-1">
|
||||
{section.items.map((item) => {
|
||||
const isActive = pathname === item.href;
|
||||
return (
|
||||
<li key={item.href}>
|
||||
<Link
|
||||
href={item.href}
|
||||
className={`flex items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors hover:bg-muted ${
|
||||
isActive
|
||||
? "bg-muted font-medium text-foreground"
|
||||
: "text-muted-foreground"
|
||||
}`}
|
||||
>
|
||||
<item.icon className="size-4" />
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user