mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-07-27 04:31:57 +00:00
merge: unify docs.hanzo.ai header/footer on @hanzogui/shell chrome
# Conflicts: # apps/docs/scripts/gen-services-nav.ts
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { HomeLayout } from '@hanzo/docs-base-ui/layouts/home';
|
||||
import { baseOptions, linkItems } from '@/components/layouts/shared';
|
||||
import { TryHanzoDropdown } from '@/components/try-hanzo-dropdown';
|
||||
import { MeetHanzo } from '@/components/meet-hanzo';
|
||||
import { HanzoAppLauncher, HanzoPreFooterCTA } from '@hanzogui/shell';
|
||||
import { Footer } from '@/components/footer';
|
||||
|
||||
export default function Layout({ children }: LayoutProps<'/'>) {
|
||||
@@ -15,13 +16,26 @@ export default function Layout({ children }: LayoutProps<'/'>) {
|
||||
type: 'custom',
|
||||
secondary: true,
|
||||
on: 'nav',
|
||||
children: <TryHanzoDropdown />,
|
||||
children: <MeetHanzo />,
|
||||
},
|
||||
{
|
||||
type: 'custom',
|
||||
secondary: true,
|
||||
on: 'nav',
|
||||
children: (
|
||||
<HanzoAppLauncher
|
||||
currentApp="docs"
|
||||
quickSwitchKey={false}
|
||||
label="Meet Hanzo apps"
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
className="dark:bg-neutral-950 dark:[--color-fd-background:var(--color-neutral-950)]"
|
||||
>
|
||||
{children}
|
||||
</HomeLayout>
|
||||
<HanzoPreFooterCTA surface="hanzo.ai" />
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -8,7 +8,8 @@ import { cn } from '@/lib/cn';
|
||||
import { buttonVariants } from '@hanzo/docs-base-ui/components/ui/button';
|
||||
import { ProjectSwitcher } from '@/components/projects/project-switcher';
|
||||
import { AuthButtons } from '@/components/auth-buttons';
|
||||
import { TryHanzoDropdown } from '@/components/try-hanzo-dropdown';
|
||||
import { MeetHanzo } from '@/components/meet-hanzo';
|
||||
import { HanzoAppLauncher } from '@hanzogui/shell';
|
||||
import { Footer } from '@/components/footer';
|
||||
import 'katex/dist/katex.min.css';
|
||||
|
||||
@@ -25,7 +26,18 @@ export default function Layout({ children }: LayoutProps<'/docs'>) {
|
||||
{
|
||||
type: 'custom',
|
||||
on: 'nav',
|
||||
children: <TryHanzoDropdown />,
|
||||
children: <MeetHanzo />,
|
||||
},
|
||||
{
|
||||
type: 'custom',
|
||||
on: 'nav',
|
||||
children: (
|
||||
<HanzoAppLauncher
|
||||
currentApp="docs"
|
||||
quickSwitchKey={false}
|
||||
label="Meet Hanzo apps"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'custom',
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Brand tokens (monochrome --hanzo-*, --font-size-*, --z-*) load first so the
|
||||
// Fumadocs theme + Tailwind layers in global.css can override where they meet.
|
||||
import '@hanzo/brand/styles/variables.css';
|
||||
import './global.css';
|
||||
import type { Viewport } from 'next';
|
||||
import { baseUrl, createMetadata } from '@/lib/metadata';
|
||||
|
||||
@@ -1,177 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { Sun, Moon } from 'lucide-react';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Products',
|
||||
links: [
|
||||
{ label: 'Cloud', href: 'https://cloud.hanzo.ai' },
|
||||
{ label: 'Chat', href: 'https://hanzo.chat' },
|
||||
{ label: 'Console', href: 'https://console.hanzo.ai' },
|
||||
{ label: 'Bot', href: 'https://hanzo.bot' },
|
||||
{ label: 'Flow', href: 'https://flow.hanzo.ai' },
|
||||
{ label: 'Platform', href: 'https://platform.hanzo.ai' },
|
||||
{ label: 'Storage', href: 'https://s3.hanzo.ai' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Developers',
|
||||
links: [
|
||||
{ label: 'Documentation', href: '/docs/services' },
|
||||
{ label: 'API Reference', href: '/docs/openapi' },
|
||||
{ label: 'SDKs', href: '/docs/sdks' },
|
||||
{ label: 'MCP Tools', href: '/docs/mcp' },
|
||||
{ label: 'Research Papers', href: '/docs/research' },
|
||||
{ label: 'HIPs', href: 'https://hips.hanzo.ai' },
|
||||
{ label: 'Zen LM', href: 'https://zenlm.org' },
|
||||
{ label: 'GitHub', href: 'https://github.com/hanzoai' },
|
||||
{ label: 'Status', href: 'https://status.hanzo.ai' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Company',
|
||||
links: [
|
||||
{ label: 'About', href: 'https://hanzo.ai/about' },
|
||||
{ label: 'Blog', href: 'https://hanzo.ai/blog' },
|
||||
{ label: 'Careers', href: 'https://hanzo.ai/careers' },
|
||||
{ label: 'Contact', href: 'https://hanzo.ai/contact' },
|
||||
{ label: 'Industries', href: 'https://hanzo.industries' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Legal',
|
||||
links: [
|
||||
{ label: 'Terms', href: 'https://hanzo.ai/terms' },
|
||||
{ label: 'Privacy', href: 'https://hanzo.ai/privacy' },
|
||||
{ label: 'Security', href: 'https://hanzo.ai/security' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
function ThemeSwitch() {
|
||||
const { resolvedTheme, setTheme } = useTheme();
|
||||
return (
|
||||
<button
|
||||
onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}
|
||||
className="text-[#525252] hover:text-[#fafafa] transition-colors"
|
||||
title="Toggle theme"
|
||||
>
|
||||
{resolvedTheme === 'dark' ? <Sun className="size-4" /> : <Moon className="size-4" />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
import { HanzoFooter } from '@hanzogui/shell';
|
||||
|
||||
/**
|
||||
* The shared 6-column ecosystem footer (HANZO_FOOTER_COLUMNS + bottom legal
|
||||
* bar), byte-identical across every Hanzo property. Docs is hanzo.ai-adjacent
|
||||
* and is not itself a flagship product, so `currentProductId` stays unset.
|
||||
*/
|
||||
export function Footer() {
|
||||
return (
|
||||
<footer className="border-t border-[#1a1a1a] bg-[#050505]">
|
||||
<div className="mx-auto max-w-[1400px] px-6 py-16 md:px-12">
|
||||
<div className="grid grid-cols-2 gap-8 md:grid-cols-4">
|
||||
{columns.map((column) => (
|
||||
<div key={column.title}>
|
||||
<h3 className="mb-4 text-sm font-semibold text-[#fafafa]">
|
||||
{column.title}
|
||||
</h3>
|
||||
<ul className="space-y-2.5">
|
||||
{column.links.map((link) => (
|
||||
<li key={link.label}>
|
||||
{link.href.startsWith('http') ? (
|
||||
<a
|
||||
href={link.href}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
className="text-sm text-[#666] hover:text-[#fafafa] transition-colors"
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
) : (
|
||||
<Link
|
||||
href={link.href}
|
||||
className="text-sm text-[#666] hover:text-[#fafafa] transition-colors"
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Social + branding + theme */}
|
||||
<div className="mt-14 flex flex-col items-center justify-between gap-6 border-t border-[#1a1a1a] pt-8 md:flex-row">
|
||||
<div className="flex items-center gap-3">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
className="size-5 text-[#fafafa]"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium text-[#fafafa]">
|
||||
Hanzo AI
|
||||
</span>
|
||||
<span className="text-xs text-[#525252]">
|
||||
Techstars '17
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-5">
|
||||
{/* GitHub */}
|
||||
<a
|
||||
href="https://github.com/hanzoai"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
className="text-[#525252] hover:text-[#fafafa] transition-colors"
|
||||
title="GitHub"
|
||||
>
|
||||
<svg className="size-4" viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" /></svg>
|
||||
</a>
|
||||
{/* HuggingFace */}
|
||||
<a
|
||||
href="https://huggingface.co/zenlm"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
className="text-[#525252] hover:text-[#fafafa] transition-colors"
|
||||
title="HuggingFace"
|
||||
>
|
||||
<svg className="size-4" viewBox="0 0 120 120" fill="currentColor"><path d="M37.6 62.7c-1.2 0-2.3.5-3.1 1.3-.8.8-1.3 2-1.3 3.1 0 1.2.5 2.3 1.3 3.1.8.9 2 1.4 3.1 1.4 1.2 0 2.3-.5 3.1-1.4.9-.8 1.4-2 1.4-3.1 0-1.2-.5-2.3-1.4-3.1-.8-.8-1.9-1.3-3.1-1.3zm44.8 0c-1.2 0-2.3.5-3.1 1.3-.9.8-1.4 2-1.4 3.1 0 1.2.5 2.3 1.4 3.1.8.9 1.9 1.4 3.1 1.4 1.2 0 2.3-.5 3.1-1.4.8-.8 1.3-2 1.3-3.1 0-1.2-.5-2.3-1.3-3.1-.8-.8-2-1.3-3.1-1.3zM60 0C26.9 0 0 26.9 0 60s26.9 60 60 60 60-26.9 60-60S93.1 0 60 0zm28.8 80.3c-.3.4-.8.6-1.3.6-.3 0-.5-.1-.8-.2-4.5-2.7-9.4-4.4-14.6-5.1-1-.1-1.7-1-1.6-2 .1-1 1-1.7 2-1.6 5.6.7 10.9 2.6 15.8 5.5.8.5 1.1 1.6.5 2.4zM33.7 73.7c-.1 1-1 1.7-2 1.6-1-.1-1.7-1-1.6-2 .7-5.6 2.6-10.9 5.5-15.8.5-.8 1.6-1.1 2.4-.5.8.5 1.1 1.6.5 2.4-2.6 4.5-4.4 9.5-5.1 14.6zM60 96c-1 0-1.8-.8-1.8-1.8 0-1 .8-1.8 1.8-1.8 14.7 0 27.4-8.8 33-21.3.4-.9 1.5-1.3 2.4-.9.9.4 1.3 1.5.9 2.4C90.2 86 75.9 96 60 96z" /></svg>
|
||||
</a>
|
||||
{/* X / Twitter */}
|
||||
<a
|
||||
href="https://x.com/hanaboroshi"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
className="text-[#525252] hover:text-[#fafafa] transition-colors"
|
||||
title="X"
|
||||
>
|
||||
<svg className="size-4" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" /></svg>
|
||||
</a>
|
||||
{/* Discord */}
|
||||
<a
|
||||
href="https://discord.gg/hanzo"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
className="text-[#525252] hover:text-[#fafafa] transition-colors"
|
||||
title="Discord"
|
||||
>
|
||||
<svg className="size-4" viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.947 2.418-2.157 2.418z" /></svg>
|
||||
</a>
|
||||
|
||||
<div className="w-px h-4 bg-[#262626]" />
|
||||
|
||||
{/* Theme toggle */}
|
||||
<ThemeSwitch />
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-[#404040]">
|
||||
© {new Date().getFullYear()} Hanzo AI, Inc.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
return <HanzoFooter />;
|
||||
}
|
||||
|
||||
@@ -1,45 +1,41 @@
|
||||
import type { BaseLayoutProps, LinkItemType } from '@hanzo/docs/ui/layouts/shared';
|
||||
import { U } from '@hanzogui/shell';
|
||||
import { HanzoDocsIcon } from '@/app/layout.client';
|
||||
|
||||
// Canonical ecosystem top-nav, sourced from the shell registry (`U`). One shape
|
||||
// across every Hanzo property: Models · Agents · Solutions · Developers ·
|
||||
// Pricing · Enterprise. "Developers" is docs itself, so it stays internal;
|
||||
// the rest resolve to their canonical hanzo.ai URLs. Doc-section navigation
|
||||
// (API, SDKs, sections) lives in the Fumadocs sidebar + the Meet-Hanzo menu.
|
||||
export const linkItems: LinkItemType[] = [
|
||||
{
|
||||
text: 'Docs',
|
||||
text: 'Models',
|
||||
url: U.models,
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
text: 'Agents',
|
||||
url: U.agents,
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
text: 'Solutions',
|
||||
url: U.solutions,
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
text: 'Developers',
|
||||
url: '/docs',
|
||||
active: 'nested-url',
|
||||
},
|
||||
{
|
||||
text: 'Network',
|
||||
url: '/docs/network',
|
||||
active: 'nested-url',
|
||||
},
|
||||
{
|
||||
text: 'API',
|
||||
url: '/docs/openapi',
|
||||
active: 'nested-url',
|
||||
},
|
||||
{
|
||||
text: 'SDKs',
|
||||
url: '/docs/sdks',
|
||||
active: 'nested-url',
|
||||
},
|
||||
{
|
||||
text: 'Research',
|
||||
url: '/docs/research',
|
||||
active: 'nested-url',
|
||||
},
|
||||
{
|
||||
text: 'Blog',
|
||||
url: '/blog',
|
||||
active: 'nested-url',
|
||||
},
|
||||
{
|
||||
text: 'HIPs',
|
||||
url: 'https://hips.hanzo.ai',
|
||||
text: 'Pricing',
|
||||
url: U.pricing,
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
text: 'Models',
|
||||
url: 'https://zenlm.org',
|
||||
text: 'Enterprise',
|
||||
url: U.enterprise,
|
||||
external: true,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import { MeetHanzoMenu } from '@hanzogui/shell';
|
||||
|
||||
/**
|
||||
* The one shared "Meet Hanzo" affordance — a nav trigger that opens the
|
||||
* universal <MeetHanzoMenu> (the ecosystem mega-menu driven by HANZO_FLAGSHIP +
|
||||
* MEET_HANZO_GROUPS). Replaces the bespoke try-hanzo-dropdown so docs discovers
|
||||
* the whole ecosystem the same way every other Hanzo property does.
|
||||
*
|
||||
* `anchor` (56px) matches the Fumadocs nav row height so the panel drops
|
||||
* flush beneath the header.
|
||||
*/
|
||||
export function MeetHanzo() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const panelId = 'meet-hanzo-menu';
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded={open}
|
||||
aria-controls={panelId}
|
||||
onClick={() => setOpen((v) => !v)}
|
||||
className="inline-flex items-center gap-1 rounded-full px-3 py-1.5 text-sm font-medium text-fd-muted-foreground transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground"
|
||||
>
|
||||
Meet Hanzo
|
||||
<ChevronDown
|
||||
className={`size-3.5 transition-transform duration-200 ${open ? 'rotate-180' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
<MeetHanzoMenu
|
||||
id={panelId}
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
anchor={56}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
Sparkles,
|
||||
Code,
|
||||
Zap,
|
||||
Eye,
|
||||
MessageCircle,
|
||||
Terminal,
|
||||
Monitor,
|
||||
ChevronDown,
|
||||
ExternalLink,
|
||||
ArrowRight,
|
||||
} from 'lucide-react';
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
|
||||
const zenModels = [
|
||||
{
|
||||
name: 'Zen4 Max',
|
||||
tag: 'Frontier',
|
||||
description: 'Reasoning, analysis, agentic coding',
|
||||
icon: Sparkles,
|
||||
href: 'https://cloud.hanzo.ai',
|
||||
},
|
||||
{
|
||||
name: 'Zen4 Coder',
|
||||
tag: 'Code',
|
||||
description: 'Code generation, review, debugging',
|
||||
icon: Code,
|
||||
href: 'https://cloud.hanzo.ai',
|
||||
},
|
||||
{
|
||||
name: 'Zen4 Mini',
|
||||
tag: 'Fast',
|
||||
description: 'Ultra-fast — $5 free credit on signup',
|
||||
icon: Zap,
|
||||
href: 'https://cloud.hanzo.ai',
|
||||
},
|
||||
{
|
||||
name: 'Zen3 Omni',
|
||||
tag: 'Multimodal',
|
||||
description: 'Text, vision, audio in one model',
|
||||
icon: Eye,
|
||||
href: 'https://cloud.hanzo.ai',
|
||||
},
|
||||
];
|
||||
|
||||
const products = [
|
||||
{ label: 'Hanzo Chat', description: 'Chat with 14 Zen + 100+ models', href: 'https://hanzo.chat', icon: MessageCircle },
|
||||
{ label: 'Hanzo Dev', description: 'AI coding agent for your IDE', href: 'https://hanzo.ai/dev', icon: Terminal },
|
||||
{ label: 'Console', description: 'Keys, usage, billing', href: 'https://console.hanzo.ai', icon: Monitor },
|
||||
];
|
||||
|
||||
export function TryHanzoDropdown() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
function handleClickOutside(e: MouseEvent) {
|
||||
if (ref.current && !ref.current.contains(e.target as Node)) {
|
||||
setOpen(false);
|
||||
}
|
||||
}
|
||||
function handleEscape(e: KeyboardEvent) {
|
||||
if (e.key === 'Escape') setOpen(false);
|
||||
}
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
document.addEventListener('keydown', handleEscape);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
document.removeEventListener('keydown', handleEscape);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="relative"
|
||||
onMouseEnter={() => setOpen(true)}
|
||||
onMouseLeave={() => setOpen(false)}
|
||||
>
|
||||
<button
|
||||
className="inline-flex items-center gap-1.5 rounded-full bg-white px-4 py-1.5 text-sm font-medium text-black hover:bg-neutral-200 transition-colors"
|
||||
>
|
||||
Try Zen
|
||||
<ChevronDown
|
||||
className={`size-3.5 transition-transform duration-200 ${open ? 'rotate-180' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
|
||||
{open && (
|
||||
<div className="absolute right-0 top-full z-50 mt-2 w-[380px] rounded-2xl border border-[#262626] bg-[#111111]/95 backdrop-blur-xl shadow-2xl overflow-hidden">
|
||||
{/* Zen Models */}
|
||||
<div className="p-3">
|
||||
<div className="flex items-center justify-between mb-2 px-1">
|
||||
<span className="text-[10px] font-semibold text-[#666] uppercase tracking-wider">
|
||||
Zen AI Models
|
||||
</span>
|
||||
<a
|
||||
href="https://zenlm.org"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
onClick={() => setOpen(false)}
|
||||
className="text-[10px] text-[#525252] hover:text-white transition-colors"
|
||||
>
|
||||
All 44 models →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-1.5">
|
||||
{zenModels.map((model) => (
|
||||
<a
|
||||
key={model.name}
|
||||
href={model.href}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
onClick={() => setOpen(false)}
|
||||
className="group flex items-start gap-2.5 p-2.5 rounded-xl hover:bg-white/[0.06] transition-colors"
|
||||
>
|
||||
<div className="w-7 h-7 rounded-lg bg-white/[0.06] flex items-center justify-center shrink-0 group-hover:bg-white/10 transition-colors">
|
||||
<model.icon className="size-3.5 text-[#666] group-hover:text-white transition-colors" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-[13px] font-medium text-[#fafafa]">{model.name}</span>
|
||||
<span className="text-[9px] font-semibold tracking-wider uppercase text-[#525252] bg-white/[0.06] px-1 py-px rounded">
|
||||
{model.tag}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-[11px] text-[#525252] leading-tight mt-0.5">{model.description}</p>
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-[#1a1a1a]" />
|
||||
|
||||
{/* Products */}
|
||||
<div className="p-3">
|
||||
<div className="px-1 mb-1.5">
|
||||
<span className="text-[10px] font-semibold text-[#666] uppercase tracking-wider">
|
||||
Products
|
||||
</span>
|
||||
</div>
|
||||
{products.map((item) => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
onClick={() => setOpen(false)}
|
||||
className="flex items-center gap-2.5 py-2 px-2.5 rounded-lg hover:bg-white/[0.06] transition-colors group"
|
||||
>
|
||||
<item.icon className="size-4 text-[#525252] shrink-0 group-hover:text-white transition-colors" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<span className="text-[13px] font-medium text-[#fafafa]">{item.label}</span>
|
||||
<span className="text-[11px] text-[#525252] ml-2">{item.description}</span>
|
||||
</div>
|
||||
<ExternalLink className="size-3 text-[#333] shrink-0" />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* CTA */}
|
||||
<div className="p-3 pt-0">
|
||||
<a
|
||||
href="https://console.hanzo.ai"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
onClick={() => setOpen(false)}
|
||||
className="flex items-center justify-center gap-2 w-full py-2 rounded-lg bg-white text-black text-sm font-medium hover:bg-neutral-200 transition-colors"
|
||||
>
|
||||
Get API Key — $5 free credit
|
||||
<ArrowRight className="size-3.5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -38,6 +38,10 @@ const config: NextConfig = {
|
||||
basePath: isGitHubPages ? '/docs' : undefined,
|
||||
assetPrefix: assetPrefix || undefined,
|
||||
reactStrictMode: true,
|
||||
// Shared Hanzo shell chrome (header/mega-menu/footer) + brand tokens ship as
|
||||
// ESM with 'use client' boundaries — transpile them through the app build so
|
||||
// the client/server split and JSX runtime resolve correctly.
|
||||
transpilePackages: ['@hanzogui/shell', '@hanzo/brand'],
|
||||
// Turbopack is the Next 16 default and correctly compiles MDX bodies via the
|
||||
// createMDX loader rules (the --webpack path emits empty bodies on Next 16).
|
||||
// Turbopack ignores the webpack resolve.alias below, so the virtual content
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"@ai-sdk/openai-compatible": "^2.0.48",
|
||||
"@ai-sdk/react": "^3.0.193",
|
||||
"@floating-ui/react-dom": "^2.1.8",
|
||||
"@hanzo/brand": "^1.4.1",
|
||||
"@hanzo/docs": "workspace:*",
|
||||
"@hanzo/docs-base-ui": "workspace:*",
|
||||
"@hanzo/docs-core": "workspace:*",
|
||||
@@ -31,6 +32,7 @@
|
||||
"@hanzo/docs-ui": "workspace:*",
|
||||
"@hanzo/iam": "^0.13.2",
|
||||
"@hanzo/logo": "^1.0.5",
|
||||
"@hanzogui/shell": "^7.4.2",
|
||||
"@llmgateway/ai-sdk-provider": "^3.8.0",
|
||||
"@mixedbread/sdk": "^0.72.0",
|
||||
"@openrouter/ai-sdk-provider": "^2.9.0",
|
||||
|
||||
@@ -33,6 +33,10 @@ try {
|
||||
}
|
||||
const { SNAPSHOT, docsServicesMeta, docsCoverage } = products
|
||||
|
||||
// Guard the DERIVED-nav contract, not just the import: an installed @hanzo/products
|
||||
// that predates the docs nav API (no SNAPSHOT / docsServicesMeta / docsCoverage)
|
||||
// must fall back to the committed meta.json and exit 0 — same "never break the
|
||||
// build" guarantee as a missing package.
|
||||
if (
|
||||
!Array.isArray(SNAPSHOT) ||
|
||||
typeof docsServicesMeta !== "function" ||
|
||||
|
||||
Generated
+46
@@ -599,6 +599,9 @@ importers:
|
||||
'@floating-ui/react-dom':
|
||||
specifier: ^2.1.8
|
||||
version: 2.1.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
'@hanzo/brand':
|
||||
specifier: ^1.4.1
|
||||
version: 1.4.1(react@19.2.6)
|
||||
'@hanzo/docs':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/hanzo-docs
|
||||
@@ -638,6 +641,9 @@ importers:
|
||||
'@hanzo/logo':
|
||||
specifier: ^1.0.5
|
||||
version: 1.0.5(react@19.2.6)
|
||||
'@hanzogui/shell':
|
||||
specifier: ^7.4.2
|
||||
version: 7.4.2(@hanzo/iam@0.13.2(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
|
||||
'@llmgateway/ai-sdk-provider':
|
||||
specifier: ^3.8.0
|
||||
version: 3.8.0(ai@6.0.191(zod@4.4.3))(zod@4.4.3)
|
||||
@@ -7473,6 +7479,15 @@ packages:
|
||||
'@hanzo/attachment@0.6.19':
|
||||
resolution: {integrity: sha512-mbwgYyeWIE6VOBh/hmCY1jMF+evvjX9lHC68cWNYAxdaPiYeqsP6WjhHXTTJo0FqgZusCEbAm5ezRmEGNmR5gg==}
|
||||
|
||||
'@hanzo/brand@1.4.1':
|
||||
resolution: {integrity: sha512-tApXct8gE/HOYa61h6TWQfDp07l1pmB+vqmxlJtU+MhocbwEkW4VPJrQdPuwF/5GPZYQauNT2uaRpnZdCK8ikw==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
react: '>=18'
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
|
||||
'@hanzo/card@0.6.5':
|
||||
resolution: {integrity: sha512-bez6CgDGxhPxE0EbQmtHWGcx8HGdnaa7PdFGa7zxscIaoP49V1a0sZcW6JX3XcwiwYEJd504uu/NIDQf9lmslQ==}
|
||||
deprecated: moved to @hanzoteam/card
|
||||
@@ -7499,6 +7514,14 @@ packages:
|
||||
react:
|
||||
optional: true
|
||||
|
||||
'@hanzo/logo@1.0.13':
|
||||
resolution: {integrity: sha512-94VA6S7oVY5UZ816295Ez12p8a76ZGEct14JQwE6r5UCutD3K9TBgx5V01gjwxwVL9tWnXn/yut4PHRAY/9RNQ==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
|
||||
'@hanzo/logo@1.0.5':
|
||||
resolution: {integrity: sha512-1xqOCkUDBw28ApxZoIj1XBIoPGjUUab//I6P1i46qSSCiJ+5S/M4hGP1VwRJLYwpJ9oJ9MOTkG6If0kWf+sj5g==}
|
||||
peerDependencies:
|
||||
@@ -7665,6 +7688,13 @@ packages:
|
||||
resolution: {integrity: sha512-UcqqwnYNTTP8hnOQsV985XZhkkOetKxBWZti245T5M2PY0iUtQaPH2VTcOCRYmhjl/c9ZIq5Jj8OHW93SIs2cA==}
|
||||
deprecated: moved to @hanzoteam/workbench
|
||||
|
||||
'@hanzogui/shell@7.4.2':
|
||||
resolution: {integrity: sha512-Haig4FLJUAgNbHvYxgsX/Y4D+VZW9fzvYoYi6Z19ZKkYCXnFG6S0wQmwZhqFW5KCmlnwUV7jUSJw9vOdvqj7nw==}
|
||||
peerDependencies:
|
||||
'@hanzo/iam': ^0.13.1
|
||||
react: '*'
|
||||
react-dom: '*'
|
||||
|
||||
'@headlessui/tailwindcss@0.2.2':
|
||||
resolution: {integrity: sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -21545,6 +21575,12 @@ snapshots:
|
||||
'@hanzo/ui': 0.6.21
|
||||
'@hanzo/workbench': 0.6.21
|
||||
|
||||
'@hanzo/brand@1.4.1(react@19.2.6)':
|
||||
dependencies:
|
||||
'@hanzo/logo': 1.0.13(react@19.2.6)
|
||||
optionalDependencies:
|
||||
react: 19.2.6
|
||||
|
||||
'@hanzo/card@0.6.5':
|
||||
dependencies:
|
||||
'@hanzo/core': 0.6.40
|
||||
@@ -21605,6 +21641,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
react: 19.2.6
|
||||
|
||||
'@hanzo/logo@1.0.13(react@19.2.6)':
|
||||
optionalDependencies:
|
||||
react: 19.2.6
|
||||
|
||||
'@hanzo/logo@1.0.5(react@19.2.6)':
|
||||
dependencies:
|
||||
sharp: 0.34.5
|
||||
@@ -21842,6 +21882,12 @@ snapshots:
|
||||
'@hanzo/ui': 0.6.21
|
||||
'@hanzo/view': 0.6.18
|
||||
|
||||
'@hanzogui/shell@7.4.2(@hanzo/iam@0.13.2(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
|
||||
dependencies:
|
||||
'@hanzo/iam': 0.13.2(react@19.2.6)
|
||||
react: 19.2.6
|
||||
react-dom: 19.2.6(react@19.2.6)
|
||||
|
||||
'@headlessui/tailwindcss@0.2.2(tailwindcss@4.3.0)':
|
||||
dependencies:
|
||||
tailwindcss: 4.3.0
|
||||
|
||||
Reference in New Issue
Block a user