Initial commit

This commit is contained in:
decolua
2026-01-05 09:58:59 +07:00
commit 3857598de4
159 changed files with 14537 additions and 0 deletions
@@ -0,0 +1,57 @@
"use client";
export default function AnimatedBackground() {
return (
<>
{/* Animated Background */}
<div className="fixed inset-0 -z-10 overflow-hidden pointer-events-none">
{/* Grid pattern */}
<div
className="absolute inset-0 opacity-[0.08]"
style={{
backgroundImage: `linear-gradient(to right, #f97815 1px, transparent 1px), linear-gradient(to bottom, #f97815 1px, transparent 1px)`,
backgroundSize: '50px 50px'
}}
/>
{/* Animated gradient orbs */}
<div className="absolute -top-20 left-1/4 w-[600px] h-[600px] bg-[#f97815]/20 rounded-full blur-[120px] animate-blob" />
<div className="absolute top-1/3 -right-20 w-[500px] h-[500px] bg-purple-500/15 rounded-full blur-[120px] animate-blob-delayed-1" />
<div className="absolute -bottom-20 left-1/2 w-[550px] h-[550px] bg-blue-500/12 rounded-full blur-[120px] animate-blob-delayed-2" />
{/* Vignette effect */}
<div
className="absolute inset-0"
style={{
background: 'radial-gradient(circle at center, transparent 0%, rgba(24, 20, 17, 0.4) 100%)'
}}
/>
</div>
{/* CSS Animations */}
<style jsx global>{`
@keyframes blob {
0%, 100% {
transform: translate(0, 0) scale(1);
}
33% {
transform: translate(30px, -50px) scale(1.1);
}
66% {
transform: translate(-20px, 20px) scale(0.9);
}
}
.animate-blob {
animation: blob 20s ease-in-out infinite;
}
.animate-blob-delayed-1 {
animation: blob 22s ease-in-out 2s infinite;
}
.animate-blob-delayed-2 {
animation: blob 25s ease-in-out 4s infinite;
}
`}</style>
</>
);
}
+133
View File
@@ -0,0 +1,133 @@
"use client";
const FEATURES = [
{
icon: "link",
title: "Unified Endpoint",
desc: "Access all providers via a single standard API URL.",
colors: {
border: "hover:border-blue-500/50",
bg: "hover:bg-blue-500/5",
iconBg: "bg-blue-500/10",
iconText: "text-blue-500",
titleHover: "group-hover:text-blue-400"
}
},
{
icon: "bolt",
title: "Easy Setup",
desc: "Get up and running in minutes with npx command.",
colors: {
border: "hover:border-orange-500/50",
bg: "hover:bg-orange-500/5",
iconBg: "bg-orange-500/10",
iconText: "text-orange-500",
titleHover: "group-hover:text-orange-400"
}
},
{
icon: "shield_with_heart",
title: "Model Fallback",
desc: "Automatically switch providers on failure or high latency.",
colors: {
border: "hover:border-rose-500/50",
bg: "hover:bg-rose-500/5",
iconBg: "bg-rose-500/10",
iconText: "text-rose-500",
titleHover: "group-hover:text-rose-400"
}
},
{
icon: "monitoring",
title: "Usage Tracking",
desc: "Detailed analytics and cost monitoring across all models.",
colors: {
border: "hover:border-purple-500/50",
bg: "hover:bg-purple-500/5",
iconBg: "bg-purple-500/10",
iconText: "text-purple-500",
titleHover: "group-hover:text-purple-400"
}
},
{
icon: "key",
title: "OAuth & API Keys",
desc: "Securely manage credentials in one vault.",
colors: {
border: "hover:border-amber-500/50",
bg: "hover:bg-amber-500/5",
iconBg: "bg-amber-500/10",
iconText: "text-amber-500",
titleHover: "group-hover:text-amber-400"
}
},
{
icon: "cloud_sync",
title: "Cloud Sync",
desc: "Sync your configurations across devices instantly.",
colors: {
border: "hover:border-sky-500/50",
bg: "hover:bg-sky-500/5",
iconBg: "bg-sky-500/10",
iconText: "text-sky-500",
titleHover: "group-hover:text-sky-400"
}
},
{
icon: "terminal",
title: "CLI Support",
desc: "Works with Claude Code, Codex, Cline, Cursor, and more.",
colors: {
border: "hover:border-emerald-500/50",
bg: "hover:bg-emerald-500/5",
iconBg: "bg-emerald-500/10",
iconText: "text-emerald-500",
titleHover: "group-hover:text-emerald-400"
}
},
{
icon: "dashboard",
title: "Dashboard",
desc: "Visual dashboard for real-time traffic analysis.",
colors: {
border: "hover:border-fuchsia-500/50",
bg: "hover:bg-fuchsia-500/5",
iconBg: "bg-fuchsia-500/10",
iconText: "text-fuchsia-500",
titleHover: "group-hover:text-fuchsia-400"
}
},
];
export default function Features() {
return (
<section className="py-24 px-6" id="features">
<div className="max-w-7xl mx-auto">
<div className="mb-16">
<h2 className="text-3xl md:text-4xl font-bold mb-4">Powerful Features</h2>
<p className="text-gray-400 max-w-xl text-lg">
Everything you need to manage your AI infrastructure in one place, built for scale.
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{FEATURES.map((feature) => (
<div
key={feature.title}
className={`p-6 rounded-xl bg-[#23180f] border border-[#3a2f27] ${feature.colors.border} ${feature.colors.bg} transition-all duration-300 group`}
>
<div className={`w-10 h-10 rounded-lg ${feature.colors.iconBg} flex items-center justify-center mb-4 ${feature.colors.iconText} group-hover:scale-110 transition-transform duration-300`}>
<span className="material-symbols-outlined">{feature.icon}</span>
</div>
<h3 className={`text-lg font-bold mb-2 ${feature.colors.titleHover} transition-colors`}>
{feature.title}
</h3>
<p className="text-sm text-gray-400 leading-relaxed">{feature.desc}</p>
</div>
))}
</div>
</div>
</section>
);
}
+120
View File
@@ -0,0 +1,120 @@
"use client";
import { useEffect, useState } from "react";
import Image from "next/image";
const CLI_TOOLS = [
{ id: "claude", name: "Claude Code", image: "/providers/claude.png" },
{ id: "codex", name: "OpenAI Codex", image: "/providers/codex.png" },
{ id: "cline", name: "Cline", image: "/providers/cline.png" },
{ id: "cursor", name: "Cursor", image: "/providers/cursor.png" },
];
const PROVIDERS = [
{ id: "openai", name: "OpenAI", color: "bg-emerald-500", textColor: "text-white" },
{ id: "anthropic", name: "Anthropic", color: "bg-orange-400", textColor: "text-white" },
{ id: "gemini", name: "Gemini", color: "bg-blue-500", textColor: "text-white" },
{ id: "github", name: "GitHub Copilot", color: "bg-gray-700", textColor: "text-white" },
];
export default function FlowAnimation() {
const [activeFlow, setActiveFlow] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setActiveFlow((prev) => (prev + 1) % PROVIDERS.length);
}, 2000);
return () => clearInterval(interval);
}, []);
return (
<div className="mt-16 w-full max-w-4xl relative h-[360px] hidden md:flex items-center justify-center animate-[float_6s_ease-in-out_infinite]">
{/* 9Router Hub - Center */}
<div className="relative z-20 w-32 h-32 rounded-full bg-[#23180f] border-2 border-[#f97815] shadow-[0_0_40px_rgba(249,120,21,0.3)] flex flex-col items-center justify-center gap-1 group cursor-pointer hover:scale-105 transition-transform duration-500">
<span className="material-symbols-outlined text-4xl text-[#f97815]">hub</span>
<span className="text-xs font-bold text-white tracking-widest uppercase">9Router</span>
<div className="absolute inset-0 rounded-full border border-[#f97815]/30 animate-ping opacity-20"></div>
</div>
{/* CLI Tools - Left side */}
<div className="absolute left-0 top-1/2 -translate-y-1/2 flex flex-col gap-7">
{CLI_TOOLS.map((tool) => (
<div
key={tool.id}
className="flex items-center gap-3 opacity-70 hover:opacity-100 transition-opacity group"
>
<div className="w-16 h-16 rounded-2xl bg-[#23180f] border border-[#3a2f27] flex items-center justify-center overflow-hidden p-2 hover:border-[#f97815]/50 transition-all hover:scale-105">
<Image
src={tool.image}
alt={tool.name}
width={48}
height={48}
className="object-contain rounded-xl"
/>
</div>
</div>
))}
</div>
{/* SVG Lines from CLI to 9Router */}
<svg className="absolute inset-0 w-full h-full z-10 pointer-events-none stroke-yellow-700" xmlns="http://www.w3.org/2000/svg">
<path className="animate-[dash_2s_linear_infinite]" d="M 60 50 C 250 70, 250 180, 360 180" fill="none" strokeDasharray="5,5" strokeWidth="2"></path>
<path className="animate-[dash_2s_linear_infinite]" d="M 60 140 C 250 140, 250 180, 360 180" fill="none" strokeDasharray="5,5" strokeWidth="2"></path>
<path className="animate-[dash_2s_linear_infinite]" d="M 60 210 C 250 210, 250 180, 360 180" fill="none" strokeDasharray="5,5" strokeWidth="2"></path>
<path className="animate-[dash_2s_linear_infinite]" d="M 60 300 C 250 280, 250 180, 360 180" fill="none" strokeDasharray="5,5" strokeWidth="2"></path>
</svg>
{/* SVG Lines from 9Router to Providers */}
<svg className="absolute inset-0 w-full h-full z-10 pointer-events-none" xmlns="http://www.w3.org/2000/svg">
<path
d="M 440 180 C 550 180, 550 50, 740 50"
fill="none"
stroke={activeFlow === 0 ? "#f97815" : "rgb(75, 85, 99)"}
strokeWidth={activeFlow === 0 ? "3" : "2"}
className={activeFlow === 0 ? "animate-pulse" : ""}
></path>
<path
d="M 440 180 C 550 180, 550 130, 740 130"
fill="none"
stroke={activeFlow === 1 ? "#f97815" : "rgb(75, 85, 99)"}
strokeWidth={activeFlow === 1 ? "3" : "2"}
className={activeFlow === 1 ? "animate-pulse" : ""}
></path>
<path
d="M 440 180 C 550 180, 550 230, 740 230"
fill="none"
stroke={activeFlow === 2 ? "#f97815" : "rgb(75, 85, 99)"}
strokeWidth={activeFlow === 2 ? "3" : "2"}
className={activeFlow === 2 ? "animate-pulse" : ""}
></path>
<path
d="M 440 180 C 550 180, 550 310, 740 310"
fill="none"
stroke={activeFlow === 3 ? "#f97815" : "rgb(75, 85, 99)"}
strokeWidth={activeFlow === 3 ? "3" : "2"}
className={activeFlow === 3 ? "animate-pulse" : ""}
></path>
</svg>
{/* AI Providers - Right side */}
<div className="absolute right-0 top-0 bottom-0 flex flex-col justify-between py-6">
{PROVIDERS.map((provider, idx) => (
<div
key={provider.id}
className={`px-4 py-2 rounded-lg ${provider.color} ${provider.textColor} flex items-center justify-center font-bold text-xs shadow-lg hover:scale-110 transition-all cursor-help min-w-[140px] ${
activeFlow === idx ? "ring-4 ring-[#f97815]/50 scale-110" : ""
}`}
title={provider.name}
>
{provider.name}
</div>
))}
</div>
{/* Mobile fallback */}
<div className="md:hidden mt-8 w-full p-4 rounded-lg bg-[#23180f] border border-[#3a2f27]">
<p className="text-sm text-center text-gray-400">Interactive diagram visible on desktop</p>
</div>
</div>
);
}
+61
View File
@@ -0,0 +1,61 @@
"use client";
export default function Footer() {
return (
<footer className="border-t border-[#3a2f27] bg-[#120f0d] pt-16 pb-8 px-6">
<div className="max-w-7xl mx-auto">
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-8 mb-16">
{/* Brand */}
<div className="col-span-2 lg:col-span-2">
<div className="flex items-center gap-3 mb-6">
<div className="size-6 rounded bg-[#f97815] flex items-center justify-center text-white">
<span className="material-symbols-outlined text-[16px]">hub</span>
</div>
<h3 className="text-white text-lg font-bold">9Router</h3>
</div>
<p className="text-gray-500 text-sm max-w-xs mb-6">
The unified endpoint for AI generation. Connect, route, and manage your AI providers with ease.
</p>
<div className="flex gap-4">
<a className="text-gray-400 hover:text-white transition-colors" href="https://github.com/decolua/9router" target="_blank" rel="noopener noreferrer">
<span className="material-symbols-outlined">code</span>
</a>
</div>
</div>
{/* Product */}
<div className="flex flex-col gap-4">
<h4 className="font-bold text-white">Product</h4>
<a className="text-gray-400 hover:text-[#f97815] text-sm transition-colors" href="#features">Features</a>
<a className="text-gray-400 hover:text-[#f97815] text-sm transition-colors" href="/dashboard">Dashboard</a>
<a className="text-gray-400 hover:text-[#f97815] text-sm transition-colors" href="https://github.com/decolua/9router" target="_blank" rel="noopener noreferrer">Changelog</a>
</div>
{/* Resources */}
<div className="flex flex-col gap-4">
<h4 className="font-bold text-white">Resources</h4>
<a className="text-gray-400 hover:text-[#f97815] text-sm transition-colors" href="https://github.com/decolua/9router#readme" target="_blank" rel="noopener noreferrer">Documentation</a>
<a className="text-gray-400 hover:text-[#f97815] text-sm transition-colors" href="https://github.com/decolua/9router" target="_blank" rel="noopener noreferrer">GitHub</a>
<a className="text-gray-400 hover:text-[#f97815] text-sm transition-colors" href="https://www.npmjs.com/package/9router" target="_blank" rel="noopener noreferrer">NPM</a>
</div>
{/* Legal */}
<div className="flex flex-col gap-4">
<h4 className="font-bold text-white">Legal</h4>
<a className="text-gray-400 hover:text-[#f97815] text-sm transition-colors" href="https://github.com/decolua/9router/blob/main/LICENSE" target="_blank" rel="noopener noreferrer">MIT License</a>
</div>
</div>
{/* Bottom */}
<div className="border-t border-[#3a2f27] pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
<p className="text-gray-600 text-sm">© 2025 9Router. All rights reserved.</p>
<div className="flex gap-6">
<a className="text-gray-600 hover:text-white text-sm transition-colors" href="https://github.com/decolua/9router" target="_blank" rel="noopener noreferrer">GitHub</a>
<a className="text-gray-600 hover:text-white text-sm transition-colors" href="https://www.npmjs.com/package/9router" target="_blank" rel="noopener noreferrer">NPM</a>
</div>
</div>
</div>
</footer>
);
}
+99
View File
@@ -0,0 +1,99 @@
"use client";
import { useState } from "react";
export default function GetStarted() {
const [copied, setCopied] = useState(false);
const handleCopy = (text) => {
navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
return (
<section className="py-24 px-6 bg-[#120f0d]">
<div className="max-w-7xl mx-auto">
<div className="flex flex-col lg:flex-row gap-16 items-start">
{/* Left: Steps */}
<div className="flex-1">
<h2 className="text-3xl md:text-4xl font-bold mb-6">Get Started in 30 Seconds</h2>
<p className="text-gray-400 text-lg mb-8">
Install 9Router, configure your providers via web dashboard, and start routing AI requests.
</p>
<div className="flex flex-col gap-6">
<div className="flex gap-4">
<div className="flex-none w-8 h-8 rounded-full bg-[#f97815]/20 text-[#f97815] flex items-center justify-center font-bold">1</div>
<div>
<h4 className="font-bold text-lg">Install 9Router</h4>
<p className="text-sm text-gray-500 mt-1">Run npx command to start the server instantly</p>
</div>
</div>
<div className="flex gap-4">
<div className="flex-none w-8 h-8 rounded-full bg-[#f97815]/20 text-[#f97815] flex items-center justify-center font-bold">2</div>
<div>
<h4 className="font-bold text-lg">Open Dashboard</h4>
<p className="text-sm text-gray-500 mt-1">Configure providers and API keys via web interface</p>
</div>
</div>
<div className="flex gap-4">
<div className="flex-none w-8 h-8 rounded-full bg-[#f97815]/20 text-[#f97815] flex items-center justify-center font-bold">3</div>
<div>
<h4 className="font-bold text-lg">Route Requests</h4>
<p className="text-sm text-gray-500 mt-1">Point your CLI tools to http://localhost:20128</p>
</div>
</div>
</div>
</div>
{/* Right: Code block */}
<div className="flex-1 w-full">
<div className="rounded-xl overflow-hidden bg-[#1e1e1e] border border-[#3a2f27] shadow-2xl">
{/* Terminal header */}
<div className="flex items-center gap-2 px-4 py-3 bg-[#252526] border-b border-gray-700">
<div className="w-3 h-3 rounded-full bg-red-500"></div>
<div className="w-3 h-3 rounded-full bg-yellow-500"></div>
<div className="w-3 h-3 rounded-full bg-green-500"></div>
<div className="ml-2 text-xs text-gray-500 font-mono">terminal</div>
</div>
{/* Terminal content */}
<div className="p-6 font-mono text-sm leading-relaxed overflow-x-auto">
<div
className="flex items-center gap-2 mb-4 group cursor-pointer"
onClick={() => handleCopy("npx 9router")}
>
<span className="text-green-400">$</span>
<span className="text-white">npx 9router</span>
<span className="ml-auto text-gray-500 text-xs opacity-0 group-hover:opacity-100">
{copied ? "✓ Copied" : "Copy"}
</span>
</div>
<div className="text-gray-400 mb-6">
<span className="text-[#f97815]">&gt;</span> Starting 9Router...<br/>
<span className="text-[#f97815]">&gt;</span> Server running on <span className="text-blue-400">http://localhost:20128</span><br/>
<span className="text-[#f97815]">&gt;</span> Dashboard: <span className="text-blue-400">http://localhost:20128/dashboard</span><br/>
<span className="text-green-400">&gt;</span> Ready to route! ✓
</div>
<div className="text-xs text-gray-500 mb-2 border-t border-gray-700 pt-4">
📝 Configure providers in dashboard or use environment variables
</div>
<div className="text-gray-400 text-xs">
<span className="text-purple-400">Data Location:</span><br/>
<span className="text-gray-500"> macOS/Linux:</span> ~/.9router/db.json<br/>
<span className="text-gray-500"> Windows:</span> %APPDATA%/9router/db.json
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
}
+47
View File
@@ -0,0 +1,47 @@
"use client";
export default function HeroSection() {
return (
<section className="relative pt-32 pb-20 px-6 min-h-[90vh] flex flex-col items-center justify-center overflow-hidden">
{/* Glow effect */}
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[1000px] h-[500px] bg-[#f97815]/10 rounded-full blur-[120px] pointer-events-none"></div>
<div className="relative z-10 max-w-4xl w-full text-center flex flex-col items-center gap-8">
{/* Version badge */}
<div className="inline-flex items-center gap-2 rounded-full border border-[#3a2f27] bg-[#23180f]/50 px-3 py-1 text-xs font-medium text-[#f97815]">
<span className="flex h-2 w-2 rounded-full bg-[#f97815] animate-pulse"></span>
v1.0 is now live
</div>
{/* Main heading */}
<h1 className="text-5xl md:text-7xl font-black leading-[1.1] tracking-tight">
One Endpoint for <br/>
<span className="text-[#f97815]">All AI Providers</span>
</h1>
{/* Description */}
<p className="text-lg md:text-xl text-gray-400 max-w-2xl mx-auto font-light">
AI endpoint proxy with web dashboard - A JavaScript port of CLIProxyAPI. Works seamlessly with Claude Code, OpenAI Codex, Cline, RooCode, and other CLI tools.
</p>
{/* CTA Buttons */}
<div className="flex flex-wrap items-center justify-center gap-4 w-full">
<button className="h-12 px-8 rounded-lg bg-[#f97815] hover:bg-[#e0650a] text-[#181411] text-base font-bold transition-all shadow-[0_0_15px_rgba(249,120,21,0.4)] flex items-center gap-2">
<span className="material-symbols-outlined">rocket_launch</span>
Get Started
</button>
<a
href="https://github.com/decolua/9router"
target="_blank"
rel="noopener noreferrer"
className="h-12 px-8 rounded-lg border border-[#3a2f27] bg-[#23180f] hover:bg-[#3a2f27] text-white text-base font-bold transition-all flex items-center gap-2"
>
<span className="material-symbols-outlined">code</span>
View on GitHub
</a>
</div>
</div>
</section>
);
}
+66
View File
@@ -0,0 +1,66 @@
"use client";
export default function HowItWorks() {
return (
<section className="py-24 border-y border-[#3a2f27] bg-[#23180f]/30" id="how-it-works">
<div className="max-w-7xl mx-auto px-6">
<div className="mb-16">
<h2 className="text-3xl md:text-4xl font-bold mb-4">How 9Router Works</h2>
<p className="text-gray-400 max-w-xl text-lg">
Data flows seamlessly from your application through our intelligent routing layer to the best provider for the job.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 relative">
{/* Connection line */}
<div className="hidden md:block absolute top-12 left-[16%] right-[16%] h-[2px] bg-gradient-to-r from-gray-700 via-[#f97815] to-gray-700 -z-10"></div>
{/* Step 1: CLI & SDKs */}
<div className="flex flex-col gap-6 relative group">
<div className="w-24 h-24 rounded-2xl bg-[#181411] border border-[#3a2f27] flex items-center justify-center shadow-xl group-hover:border-gray-500 transition-colors z-10 mx-auto md:mx-0">
<span className="material-symbols-outlined text-4xl text-gray-300">terminal</span>
</div>
<div>
<h3 className="text-xl font-bold mb-2">1. CLI &amp; SDKs</h3>
<p className="text-sm text-gray-400">
Your requests start from your favorite tools or our unified SDK. Just change the base URL.
</p>
</div>
</div>
{/* Step 2: 9Router Hub */}
<div className="flex flex-col gap-6 relative group md:items-center md:text-center">
<div className="w-24 h-24 rounded-2xl bg-[#181411] border-2 border-[#f97815] flex items-center justify-center shadow-[0_0_30px_rgba(249,120,21,0.2)] z-10 mx-auto">
<span className="material-symbols-outlined text-4xl text-[#f97815] animate-pulse">hub</span>
</div>
<div>
<h3 className="text-xl font-bold mb-2 text-[#f97815]">2. 9Router Hub</h3>
<p className="text-sm text-gray-400">
Our engine analyzes the prompt, checks provider health, and routes for lowest latency or cost.
</p>
</div>
</div>
{/* Step 3: AI Providers */}
<div className="flex flex-col gap-6 relative group md:items-end md:text-right">
<div className="w-24 h-24 rounded-2xl bg-[#181411] border border-[#3a2f27] flex items-center justify-center shadow-xl group-hover:border-gray-500 transition-colors z-10 mx-auto md:mx-0">
<div className="grid grid-cols-2 gap-2">
<div className="w-6 h-6 rounded bg-white/10"></div>
<div className="w-6 h-6 rounded bg-white/10"></div>
<div className="w-6 h-6 rounded bg-white/10"></div>
<div className="w-6 h-6 rounded bg-white/10"></div>
</div>
</div>
<div>
<h3 className="text-xl font-bold mb-2">3. AI Providers</h3>
<p className="text-sm text-gray-400">
The request is fulfilled by OpenAI, Anthropic, Gemini, or others instantly.
</p>
</div>
</div>
</div>
</div>
</section>
);
}
+67
View File
@@ -0,0 +1,67 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
export default function Navigation() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const router = useRouter();
return (
<nav className="fixed top-0 z-50 w-full bg-[#181411]/80 backdrop-blur-md border-b border-[#3a2f27]">
<div className="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between">
{/* Logo */}
<div className="flex items-center gap-3 cursor-pointer" onClick={() => router.push("/")}>
<div className="size-8 rounded bg-gradient-to-br from-[#f97815] to-orange-700 flex items-center justify-center text-white">
<span className="material-symbols-outlined text-[20px]">hub</span>
</div>
<h2 className="text-white text-xl font-bold tracking-tight">9Router</h2>
</div>
{/* Desktop menu */}
<div className="hidden md:flex items-center gap-8">
<a className="text-gray-300 hover:text-white text-sm font-medium transition-colors" href="#features">Features</a>
<a className="text-gray-300 hover:text-white text-sm font-medium transition-colors" href="#how-it-works">How it Works</a>
<a className="text-gray-300 hover:text-white text-sm font-medium transition-colors" href="https://github.com/decolua/9router#readme" target="_blank" rel="noopener noreferrer">Docs</a>
<a className="text-gray-300 hover:text-white text-sm font-medium transition-colors flex items-center gap-1" href="https://github.com/decolua/9router" target="_blank" rel="noopener noreferrer">
GitHub <span className="material-symbols-outlined text-[14px]">open_in_new</span>
</a>
</div>
{/* CTA + Mobile menu */}
<div className="flex items-center gap-4">
<button
onClick={() => router.push("/dashboard")}
className="hidden sm:flex h-9 items-center justify-center rounded-lg px-4 bg-[#f97815] hover:bg-[#e0650a] transition-all text-[#181411] text-sm font-bold shadow-[0_0_15px_rgba(249,120,21,0.4)] hover:shadow-[0_0_20px_rgba(249,120,21,0.6)]"
>
Get Started
</button>
<button
className="md:hidden text-white"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
>
<span className="material-symbols-outlined">{mobileMenuOpen ? "close" : "menu"}</span>
</button>
</div>
</div>
{/* Mobile menu dropdown */}
{mobileMenuOpen && (
<div className="md:hidden border-t border-[#3a2f27] bg-[#181411]/95 backdrop-blur-md">
<div className="flex flex-col gap-4 p-6">
<a className="text-gray-300 hover:text-white text-sm font-medium transition-colors" href="#features" onClick={() => setMobileMenuOpen(false)}>Features</a>
<a className="text-gray-300 hover:text-white text-sm font-medium transition-colors" href="#how-it-works" onClick={() => setMobileMenuOpen(false)}>How it Works</a>
<a className="text-gray-300 hover:text-white text-sm font-medium transition-colors" href="https://github.com/decolua/9router#readme" target="_blank" rel="noopener noreferrer">Docs</a>
<a className="text-gray-300 hover:text-white text-sm font-medium transition-colors" href="https://github.com/decolua/9router" target="_blank" rel="noopener noreferrer">GitHub</a>
<button
onClick={() => router.push("/dashboard")}
className="h-9 rounded-lg bg-[#f97815] hover:bg-[#e0650a] text-[#181411] text-sm font-bold"
>
Get Started
</button>
</div>
</div>
)}
</nav>
);
}
+104
View File
@@ -0,0 +1,104 @@
"use client";
import Navigation from "./components/Navigation";
import HeroSection from "./components/HeroSection";
import FlowAnimation from "./components/FlowAnimation";
import HowItWorks from "./components/HowItWorks";
import Features from "./components/Features";
import GetStarted from "./components/GetStarted";
import Footer from "./components/Footer";
export default function LandingPage() {
return (
<div className="relative text-white font-sans overflow-x-hidden antialiased selection:bg-[#f97815] selection:text-white">
{/* Animated Background */}
<div className="fixed inset-0 z-0 overflow-hidden pointer-events-none bg-[#181411]">
{/* Grid pattern */}
<div className="absolute inset-0 opacity-[0.06]" style={{
backgroundImage: `linear-gradient(to right, #f97815 1px, transparent 1px), linear-gradient(to bottom, #f97815 1px, transparent 1px)`,
backgroundSize: '50px 50px'
}}></div>
{/* Animated gradient orbs */}
<div className="absolute top-0 left-1/4 w-[700px] h-[700px] bg-[#f97815]/12 rounded-full blur-[130px] animate-blob"></div>
<div className="absolute top-1/3 right-1/4 w-[600px] h-[600px] bg-purple-500/10 rounded-full blur-[130px] animate-blob" style={{ animationDelay: '2s', animationDuration: '22s' }}></div>
<div className="absolute bottom-0 left-1/2 w-[650px] h-[650px] bg-blue-500/8 rounded-full blur-[130px] animate-blob" style={{ animationDelay: '4s', animationDuration: '25s' }}></div>
{/* Vignette effect */}
<div className="absolute inset-0" style={{
background: 'radial-gradient(circle at center, transparent 0%, rgba(24, 20, 17, 0.4) 100%)'
}}></div>
</div>
<div className="relative z-10">
<Navigation />
<main>
{/* Hero with Flow Animation */}
<div className="relative">
<HeroSection />
<div className="flex justify-center pb-20">
<FlowAnimation />
</div>
</div>
<GetStarted />
<HowItWorks />
<Features />
{/* CTA Section */}
<section className="py-32 px-6 relative overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-t from-[#f97815]/5 to-transparent pointer-events-none"></div>
<div className="max-w-4xl mx-auto text-center relative z-10">
<h2 className="text-4xl md:text-5xl font-black mb-6">Ready to Simplify Your AI Infrastructure?</h2>
<p className="text-xl text-gray-400 mb-10 max-w-2xl mx-auto">
Join developers who are streamlining their AI integrations with 9Router. Open source and free to start.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
<button
onClick={() => window.location.href = "/dashboard"}
className="w-full sm:w-auto h-14 px-10 rounded-lg bg-[#f97815] hover:bg-[#e0650a] text-[#181411] text-lg font-bold transition-all shadow-[0_0_20px_rgba(249,120,21,0.5)]"
>
Start Free
</button>
<button
onClick={() => window.open("https://github.com/decolua/9router#readme", "_blank")}
className="w-full sm:w-auto h-14 px-10 rounded-lg border border-[#3a2f27] hover:bg-[#23180f] text-white text-lg font-bold transition-all"
>
Read Documentation
</button>
</div>
</div>
</section>
</main>
<Footer />
</div>
{/* Global styles for keyframes */}
<style jsx global>{`
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes dash {
to { stroke-dashoffset: -20; }
}
@keyframes blob {
0%, 100% {
transform: translate(0, 0) scale(1);
}
33% {
transform: translate(30px, -50px) scale(1.1);
}
66% {
transform: translate(-20px, 20px) scale(0.9);
}
}
.animate-blob {
animation: blob 20s ease-in-out infinite;
}
`}</style>
</div>
);
}