Repository Public MIT
1import Link from "next/link";2import { t } from "@/lib/i18n";3import { SearchTrigger } from "./command-palette";4import { MobileMenu } from "./mobile-menu";5import { ThemeToggle } from "./theme-toggle";67const NAV = [8 { href: "/explore", label: t.nav.explore },9 { href: "/skills", label: t.nav.skills },10 { href: "/mcp-servers", label: t.nav.mcp },11 { href: "/collections", label: t.nav.collections },12 { href: "/docs", label: t.nav.docs },13];1415export function Logo() {16 return (17 <Link href="/" className="flex items-center gap-2.5">18 <svg width="22" height="22" viewBox="0 0 24 24" aria-hidden>19 <rect x="1" y="1" width="22" height="22" rx="6" style={{ fill: "var(--color-accent)" }} />20 <path d="M7.5 9.2c0-1.5 1.6-2.7 4.3-2.7 2.3 0 4 .9 4.5 2.4M16.5 14.8c0 1.5-1.6 2.7-4.3 2.7-2.3 0-4-.9-4.5-2.4M7.5 9.2c0 3.6 9 2 9 5.6" style={{ stroke: "var(--color-on-accent)" }} strokeWidth="2" fill="none" strokeLinecap="round" />21 </svg>22 <span className="text-[15px] font-semibold tracking-[0.08em] text-text">SKILLS</span>23 <span className="hidden border-l border-line-strong pl-2.5 font-mono text-[11px] text-faint md:inline">{t.brandSub}</span>24 </Link>25 );26}2728export function Header({ signedIn }: { signedIn: boolean }) {29 return (30 <header className="sticky top-0 z-40 border-b border-line bg-ink/85 backdrop-blur-md">31 <a href="#main" className="sr-only focus:not-sr-only focus:absolute focus:left-4 focus:top-3 focus:z-50 focus:rounded-md focus:bg-accent focus:px-3 focus:py-1.5 focus:text-sm focus:text-on-accent">32 Skip to content33 </a>34 <div className="container-page flex h-14 items-center gap-4">35 <Logo />36 <nav aria-label="Primary" className="ml-4 hidden items-center gap-1 md:flex">37 {NAV.map((n) => (38 <Link key={n.href} href={n.href} className="rounded-md px-2.5 py-1.5 text-sm text-muted transition-colors hover:text-text">39 {n.label}40 </Link>41 ))}42 </nav>43 <div className="ml-auto flex items-center gap-2">44 <SearchTrigger />45 <ThemeToggle />46 <Link href="/publish" className="hidden rounded-md px-2.5 py-1.5 text-sm text-muted hover:text-text sm:block">47 {t.nav.publish}48 </Link>49 <Link href={signedIn ? "/dashboard" : "/login"} className="btn hidden h-9 min-h-9 px-3 sm:inline-flex">50 {signedIn ? t.nav.dashboard : t.nav.signIn}51 </Link>52 <MobileMenu links={[...NAV, { href: "/publish", label: t.nav.publish }, { href: signedIn ? "/dashboard" : "/login", label: signedIn ? t.nav.dashboard : t.nav.signIn }]} />53 </div>54 </div>55 </header>56 );57}5859const FOOTER: { title: string; links: { href: string; label: string }[] }[] = [60 { title: "Registry", links: [{ href: "/explore", label: "Explore" }, { href: "/collections", label: "Collections" }, { href: "/publish", label: "Publish" }, { href: "/about", label: "About" }] },61 { title: "Documentation", links: [{ href: "/docs", label: "Getting started" }, { href: "/docs/cli", label: "CLI reference" }, { href: "/docs/api", label: "REST API" }, { href: "/docs/mcp", label: "MCP server" }] },62 { title: "Standards", links: [{ href: "https://agentskills.io/specification", label: "Agent Skills specification" }, { href: "https://modelcontextprotocol.io/specification/latest", label: "Model Context Protocol" }, { href: "/api/v1/openapi.json", label: "OpenAPI 3.1 document" }] },63 { title: "Trust", links: [{ href: "/docs/security", label: "Security & trust signals" }, { href: "/report", label: "Report a problem" }, { href: "/legal/acceptable-use", label: "Acceptable use" }, { href: "/legal/privacy", label: "Privacy" }, { href: "/legal/terms", label: "Terms" }, { href: "/contact", label: "Contact" }] },64];6566export function Footer() {67 return (68 <footer className="mt-24 border-t border-line">69 <div className="container-page grid gap-10 py-12 sm:grid-cols-2 lg:grid-cols-5">70 <div className="lg:col-span-1">71 <Logo />72 <p className="mt-4 max-w-xs text-sm text-muted">An open, research-friendly registry for reusable agent capabilities. Public read access is free and needs no account.</p>73 </div>74 {FOOTER.map((col) => (75 <nav key={col.title} aria-label={col.title}>76 <h2 className="eyebrow mb-3">{col.title}</h2>77 <ul className="space-y-2">78 {col.links.map((l) => (79 <li key={l.href}>80 {l.href.startsWith("http") ? (81 <a href={l.href} rel="noopener" className="text-sm text-muted hover:text-text">82 {l.label}83 </a>84 ) : (85 <Link href={l.href} prefetch={false} className="text-sm text-muted hover:text-text">86 {l.label}87 </Link>88 )}89 </li>90 ))}91 </ul>92 </nav>93 ))}94 </div>95 <div className="border-t border-line">96 <p className="container-page py-5 font-mono text-[11px] text-faint">97 Releases are immutable and checksummed. Scanner results are advisory. · skills.spboucher.ai98 </p>99 </div>100 </footer>101 );102}103