feat: initial website implementation
React 18 + TypeScript + Vite + Tailwind CSS website for netOrk. Built by a parallel instance based on the product docs. Pages: Home (landing), Features, Drivers, Getting Started Components: Nav, Footer Assets: public/logo.png (1024x1024 RGBA) Docker: multi-stage Dockerfile (node:20 builder + nginx:alpine) Compose: netork-website service on proxy-net (Zoraxy integration) docs/DESIGN.md: Logo Assets section added (PNG only, SVG removed); wordmark pattern and <head> references documented. .gitignore: fixed (was literal \n, now proper newlines); excludes node_modules/, dist/, memory/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
00c483c2a2
commit
efa01b5f41
@@ -0,0 +1,47 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="bg-slate-900 border-t border-slate-800 mt-auto">
|
||||
<div className="max-w-7xl mx-auto px-6 py-12">
|
||||
<div className="flex flex-col md:flex-row gap-10 md:gap-16">
|
||||
<div className="shrink-0">
|
||||
<Link to="/" className="flex items-center gap-2.5 mb-3">
|
||||
<img src="/logo.png" alt="" className="h-6 w-6" aria-hidden="true" />
|
||||
<span className="font-semibold text-slate-100 tracking-tight">
|
||||
net<span className="text-sky-400">Ork</span>
|
||||
</span>
|
||||
</Link>
|
||||
<p className="text-sm text-slate-500">Self-hosted network orchestration</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-10 flex-1 text-sm">
|
||||
<div>
|
||||
<p className="font-medium text-slate-400 mb-3">Links</p>
|
||||
<ul className="space-y-2">
|
||||
<li><Link to="/features" className="text-slate-500 hover:text-slate-100 transition-colors">Features</Link></li>
|
||||
<li><Link to="/drivers" className="text-slate-500 hover:text-slate-100 transition-colors">Drivers</Link></li>
|
||||
<li><Link to="/plugins" className="text-slate-500 hover:text-slate-100 transition-colors">Plugins</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-medium text-slate-400 mb-3">Resources</p>
|
||||
<ul className="space-y-2">
|
||||
<li><Link to="/docs/getting-started" className="text-slate-500 hover:text-slate-100 transition-colors">Getting Started</Link></li>
|
||||
<li><Link to="/docs/architecture" className="text-slate-500 hover:text-slate-100 transition-colors">Architecture</Link></li>
|
||||
<li><span className="text-slate-600">Changelog</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-medium text-slate-400 mb-3">Legal</p>
|
||||
<ul className="space-y-2">
|
||||
<li><span className="text-slate-600">MIT License</span></li>
|
||||
<li><span className="text-slate-600">Privacy (none collected)</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import { useState, useRef, useEffect } from 'react'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
import { ChevronDownIcon } from '@heroicons/react/24/outline'
|
||||
|
||||
export default function Nav() {
|
||||
const [docsOpen, setDocsOpen] = useState(false)
|
||||
const location = useLocation()
|
||||
const dropdownRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
function handleClickOutside(e: MouseEvent) {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
|
||||
setDocsOpen(false)
|
||||
}
|
||||
}
|
||||
document.addEventListener('mousedown', handleClickOutside)
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setDocsOpen(false)
|
||||
}, [location.pathname])
|
||||
|
||||
const linkCls = (path: string) =>
|
||||
`text-sm transition-colors ${
|
||||
location.pathname === path
|
||||
? 'text-slate-100'
|
||||
: 'text-slate-400 hover:text-slate-100'
|
||||
}`
|
||||
|
||||
const isDocsActive = location.pathname.startsWith('/docs')
|
||||
|
||||
return (
|
||||
<nav className="sticky top-0 z-10 bg-slate-900/80 backdrop-blur border-b border-slate-800">
|
||||
<div className="max-w-7xl mx-auto px-6 h-14 flex items-center gap-8">
|
||||
<Link to="/" className="flex items-center gap-2.5 mr-2">
|
||||
<img src="/logo.png" alt="" className="h-7 w-7" aria-hidden="true" />
|
||||
<span className="font-semibold text-slate-100 tracking-tight">
|
||||
net<span className="text-sky-400">Ork</span>
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<Link to="/features" className={linkCls('/features')}>
|
||||
Features
|
||||
</Link>
|
||||
|
||||
<Link to="/drivers" className={linkCls('/drivers')}>
|
||||
Drivers
|
||||
</Link>
|
||||
|
||||
<div className="relative" ref={dropdownRef}>
|
||||
<button
|
||||
onClick={() => setDocsOpen((v) => !v)}
|
||||
className={`flex items-center gap-1 text-sm transition-colors ${
|
||||
isDocsActive ? 'text-slate-100' : 'text-slate-400 hover:text-slate-100'
|
||||
}`}
|
||||
>
|
||||
Docs
|
||||
<ChevronDownIcon
|
||||
className={`h-4 w-4 transition-transform ${docsOpen ? 'rotate-180' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
{docsOpen && (
|
||||
<div className="absolute top-full mt-2 left-0 w-48 rounded-lg border border-slate-800 bg-slate-900 py-1 shadow-xl">
|
||||
<Link
|
||||
to="/docs/getting-started"
|
||||
className="block px-4 py-2 text-sm text-slate-400 hover:text-slate-100 hover:bg-slate-800 transition-colors"
|
||||
>
|
||||
Getting Started
|
||||
</Link>
|
||||
<Link
|
||||
to="/docs/architecture"
|
||||
className="block px-4 py-2 text-sm text-slate-400 hover:text-slate-100 hover:bg-slate-800 transition-colors"
|
||||
>
|
||||
Architecture
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Link to="/plugins" className={linkCls('/plugins')}>
|
||||
Plugins
|
||||
</Link>
|
||||
|
||||
<div className="ml-auto">
|
||||
<Link
|
||||
to="/docs/getting-started"
|
||||
className="inline-flex items-center gap-2 px-4 py-1.5 text-sm rounded-lg bg-sky-600 hover:bg-sky-500 text-white font-medium transition-colors"
|
||||
>
|
||||
Get started
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user