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:
398
app/docs/configuration/page.tsx
Normal file
398
app/docs/configuration/page.tsx
Normal file
@@ -0,0 +1,398 @@
|
||||
import type { Metadata } from "next";
|
||||
import {
|
||||
Settings,
|
||||
ArrowRight,
|
||||
Shield,
|
||||
Globe,
|
||||
Gauge,
|
||||
Database,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Configuration",
|
||||
};
|
||||
|
||||
function CodeBlock({ code }: { code: string }) {
|
||||
return (
|
||||
<pre className="overflow-x-auto rounded-md border bg-muted/50 p-4 font-mono text-sm leading-relaxed">
|
||||
<code>{code.trim()}</code>
|
||||
</pre>
|
||||
);
|
||||
}
|
||||
|
||||
function EnvVar({
|
||||
name,
|
||||
defaultVal,
|
||||
required,
|
||||
description,
|
||||
}: {
|
||||
name: string;
|
||||
defaultVal: string;
|
||||
required?: boolean;
|
||||
description: string;
|
||||
}) {
|
||||
return (
|
||||
<tr className="border-b last:border-b-0">
|
||||
<td className="py-3 pr-4 align-top">
|
||||
<code className="font-mono text-xs">{name}</code>
|
||||
</td>
|
||||
<td className="py-3 pr-4 align-top">
|
||||
{defaultVal ? (
|
||||
<code className="font-mono text-xs text-muted-foreground">
|
||||
{defaultVal}
|
||||
</code>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">—</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-3 pr-4 align-top">
|
||||
{required ? (
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
required
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge variant="outline" className="text-xs">
|
||||
optional
|
||||
</Badge>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-3 align-top text-sm text-muted-foreground">
|
||||
{description}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ConfigurationPage() {
|
||||
return (
|
||||
<div className="space-y-10">
|
||||
{/* Header */}
|
||||
<div>
|
||||
<div className="mb-3 flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Settings className="size-4" />
|
||||
<span>Go Server</span>
|
||||
<ArrowRight className="size-3" />
|
||||
<span>Configuration</span>
|
||||
</div>
|
||||
<h1 className="text-3xl font-bold tracking-tight">Configuration</h1>
|
||||
<p className="mt-2 text-muted-foreground">
|
||||
All server configuration is done via environment variables or a{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">.env</span>{" "}
|
||||
file in the project root.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* .env example */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Example .env</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock
|
||||
code={`PORT=8080
|
||||
API_KEY=your-secret-api-key
|
||||
CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
|
||||
LOG_FORMAT=json`}
|
||||
/>
|
||||
<p className="mt-3 text-sm text-muted-foreground">
|
||||
Copy{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
.env.example
|
||||
</span>{" "}
|
||||
to{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
.env
|
||||
</span>{" "}
|
||||
to get started:{" "}
|
||||
<code className="font-mono text-xs bg-muted px-1 rounded">
|
||||
cp .env.example .env
|
||||
</code>
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Environment Variables reference */}
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-xl font-semibold tracking-tight">
|
||||
Environment Variables
|
||||
</h2>
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="border-b text-left text-muted-foreground">
|
||||
<th className="pb-2 pr-4 font-medium">Variable</th>
|
||||
<th className="pb-2 pr-4 font-medium">Default</th>
|
||||
<th className="pb-2 pr-4 font-medium"></th>
|
||||
<th className="pb-2 font-medium">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<EnvVar
|
||||
name="PORT"
|
||||
defaultVal="8080"
|
||||
description="Port the HTTP server listens on."
|
||||
/>
|
||||
<EnvVar
|
||||
name="API_KEY"
|
||||
defaultVal=""
|
||||
description="Shared secret for API key authentication. Auth is disabled when empty — do not leave empty in production."
|
||||
/>
|
||||
<EnvVar
|
||||
name="CORS_ORIGINS"
|
||||
defaultVal="http://localhost:3000"
|
||||
description="Comma-separated list of allowed CORS origins. Set to your frontend domain in production."
|
||||
/>
|
||||
<EnvVar
|
||||
name="LOG_FORMAT"
|
||||
defaultVal="text"
|
||||
description='Log output format. "text" for human-readable, "json" for structured logging (recommended for production).'
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* API Key Auth */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Shield className="size-5 text-primary" />
|
||||
<h2 className="text-xl font-semibold tracking-tight">
|
||||
API Key Authentication
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
The Go server uses a shared API key for authentication. This is
|
||||
intentional: the server is designed to be an internal service called
|
||||
only by your Next.js backend — not directly by end users.
|
||||
</p>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm">How it works</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
When{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
API_KEY
|
||||
</span>{" "}
|
||||
is set, every request (except{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
GET /health
|
||||
</span>
|
||||
) must include the header:
|
||||
</p>
|
||||
<CodeBlock code="X-API-Key: your-secret-api-key" />
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Requests missing or sending an incorrect key receive a{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
401 UNAUTHORIZED
|
||||
</span>{" "}
|
||||
response.
|
||||
</p>
|
||||
<CodeBlock
|
||||
code={`{
|
||||
"error": "missing or invalid API key",
|
||||
"code": "UNAUTHORIZED"
|
||||
}`}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm">Calling from Next.js</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock
|
||||
code={`// In your Next.js server action or API route
|
||||
const res = await fetch(\`\${process.env.DNS_SERVER_URL}/api/v1/dns/lookup\`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-API-Key": process.env.DNS_API_KEY!,
|
||||
},
|
||||
body: JSON.stringify({ domain, types }),
|
||||
});`}
|
||||
/>
|
||||
<p className="mt-3 text-sm text-muted-foreground">
|
||||
Store{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
DNS_API_KEY
|
||||
</span>{" "}
|
||||
as a secret environment variable in your Next.js deployment. Never
|
||||
expose it client-side.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* CORS */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Globe className="size-5 text-primary" />
|
||||
<h2 className="text-xl font-semibold tracking-tight">CORS</h2>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
CORS is handled by{" "}
|
||||
<a
|
||||
href="https://github.com/go-chi/cors"
|
||||
className="text-primary underline-offset-4 hover:underline"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
go-chi/cors
|
||||
</a>
|
||||
. Configure allowed origins via the{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
CORS_ORIGINS
|
||||
</span>{" "}
|
||||
variable.
|
||||
</p>
|
||||
<Card>
|
||||
<CardContent className="space-y-3 pt-6">
|
||||
<p className="text-sm font-medium">Development</p>
|
||||
<CodeBlock code="CORS_ORIGINS=http://localhost:3000" />
|
||||
<p className="text-sm font-medium">Production (single domain)</p>
|
||||
<CodeBlock code="CORS_ORIGINS=https://app.yourdomain.com" />
|
||||
<p className="text-sm font-medium">Production (multiple domains)</p>
|
||||
<CodeBlock code="CORS_ORIGINS=https://app.yourdomain.com,https://yourdomain.com" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Since the Go server is an internal API called server-side by Next.js,
|
||||
CORS is mostly relevant for development. In production, only your
|
||||
Next.js server IP/domain needs access.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Rate Limiting */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Gauge className="size-5 text-primary" />
|
||||
<h2 className="text-xl font-semibold tracking-tight">
|
||||
Rate Limiting
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Rate limiting is provided by{" "}
|
||||
<a
|
||||
href="https://github.com/go-chi/httprate"
|
||||
className="text-primary underline-offset-4 hover:underline"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
go-chi/httprate
|
||||
</a>{" "}
|
||||
and is enabled by default.
|
||||
</p>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm">Current defaults</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
||||
<li>• Rate limiting is applied per IP address.</li>
|
||||
<li>• Limits are enforced at the router middleware level.</li>
|
||||
<li>
|
||||
• Requests exceeding the limit receive{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
429 Too Many Requests
|
||||
</span>
|
||||
.
|
||||
</li>
|
||||
</ul>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="border-dashed">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<CardTitle className="text-sm">
|
||||
Per-API-key rate limiting
|
||||
</CardTitle>
|
||||
<Badge variant="outline" className="text-xs">
|
||||
Planned
|
||||
</Badge>
|
||||
</div>
|
||||
<CardDescription>
|
||||
When billing tiers are added, rate limits will be enforced per API
|
||||
key to match the user`'`s plan (free vs. pro).
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ul className="space-y-1.5 text-sm text-muted-foreground">
|
||||
<li>• Free tier: limited requests per day</li>
|
||||
<li>• Pro tier: higher limits, hourly checks</li>
|
||||
<li>• Team tier: highest limits, shared across org</li>
|
||||
</ul>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Redis Caching */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Database className="size-5 text-primary" />
|
||||
<h2 className="text-xl font-semibold tracking-tight">
|
||||
Redis Caching
|
||||
</h2>
|
||||
<Badge variant="outline" className="text-xs">
|
||||
Planned
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
DNS result caching via Redis is on the roadmap. When available, the
|
||||
server will check Redis before querying upstream DNS, storing results
|
||||
with TTL-based expiry.
|
||||
</p>
|
||||
<Card className="border-dashed">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm">
|
||||
Planned Redis configuration
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<CodeBlock
|
||||
code={`# Planned env vars (not yet available)
|
||||
REDIS_URL=redis://localhost:6379
|
||||
REDIS_TTL=300 # seconds`}
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
The cache layer will use{" "}
|
||||
<a
|
||||
href="https://github.com/redis/go-redis"
|
||||
className="text-primary underline-offset-4 hover:underline"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
go-redis
|
||||
</a>{" "}
|
||||
and sit as middleware before DNS resolution. A{" "}
|
||||
<span className="font-mono text-xs bg-muted px-1 rounded">
|
||||
docker-compose.yml
|
||||
</span>{" "}
|
||||
bundling the Go server with Redis will be provided.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user