Files
hanzo.ai/app/(marketing)/models/page.tsx
zeekay 6c65e3e941 @hanzo/app 0.2.0: the app SDK, renamed from @hanzo/rooms
Every import, the catalog pin and the docs name @hanzo/app and
github.com/hanzoai/app. lib/rooms.ts is lib/app.ts and
components/rooms.tsx is components/app.tsx.
2026-10-22 19:07:20 -07:00

404 lines
14 KiB
TypeScript

/**
* /models — the one overview of Hanzo's three model families, then every model
* the gateway answers for and what it costs.
*
* Order: the promise and the scale; `Family` (what Zen, Enso and Kai each do,
* each card to its own page); `Versus` (how Enso and Zen are had); the featured
* Enso and Zen models; one flagship per other lab; the priced catalogue; a
* thread to try; the request itself. The counts and the priced catalogue are
* read when the page opens (components/api/count, components/models/Catalog);
* the featured cards are the models this build wrote pages for, by id, so one
* the gateway stops serving drops off rather than 404s.
*/
import { KEYS } from '@/components/home/nav-data'
import { Live } from '@/components/models/Live'
import { ProviderMark } from '@hanzo/app/ProviderMark'
import { TryChat } from '@/components/models/TryChat'
import { Modality, Sample, Tile } from '@/components/models/kit'
import { GuestKey } from '@/components/models/guest'
import type { ModelData } from '@/lib/models'
import { context, getOrgAndSlug, formatContext, modelName, modelPagePath } from '@/lib/models'
import { fetchModels } from '@/lib/models/served'
import Catalog from '@/components/models/Catalog'
import { Tally } from '@/components/api/count'
import { Box, Text, View, XStack } from '@/components/ui'
import { Action, Display, Lede, Title } from '@hanzo/ui/marketing'
import { Grid, Cell } from '@hanzo/ui/grid'
import { Request } from '@/components/models/preview'
import { Band, Card } from '@/components/marketing/band'
import { AgentPrompt } from '@/components/product/AgentPrompt'
import { Family } from '@/components/family/Family'
import { Versus } from '@/components/family/Versus'
import { Related } from '@/components/product/Related'
import { product } from '@/lib/product'
import { NEXT, NOW } from '@/lib/zen'
import { KAI as RESULTS } from '@/lib/bench-data'
import { p50 } from '@/lib/kai'
import { Code } from '@/components/code'
import { CREATIVE_MODELS } from '@/lib/creative'
export const revalidate = 3600
/** What the shared product blocks say about this page: the audited command, the
* route the catalog proves it by, and the docs page or null. */
const PRODUCT = product('models')
/** The ground a band lifts to when it is told from its neighbour by colour as
* well as by a rule. */
const LIFT = 'color-mix(in oklab, var(--secondary) 10%, transparent)'
/**
* A card deck that never leaves a hole in the last row. Two-up, always: three
* tracks pass through two as the measure narrows, and a count that divides by
* three then strands its ninth card half across the row. Two divides everything
* but an odd count, and an odd count's last card simply takes the whole row.
*/
const tail = (n: number) => (n % 2 === 0 ? undefined : '1 / -1')
/** Ours, trained by Hanzo and served here only. */
const ENSO = ['enso', 'enso-flash', 'enso-ultra']
/** Zoo Labs Foundation's, weights published: the generation that answers now
* first (lib/zen), then the one before it and the specialists. */
const ZEN = [...NOW.ids, 'zen5', 'zen5-pro', 'zen5-coder', 'zen5-flash', 'zen-vl', 'zen-embedding']
const KAI = ['kai']
/** Kai's results card reads the research runs (lib/kai): the first harness claim
* that holds, the measured p50 when there is one, and the record sentence. */
const RESULT = RESULTS.claims.find((c) => c.board === 'kai-harness')
const TIMED = p50(RESULTS)
const FEATURED = [...ENSO, ...ZEN, ...KAI]
/**
* A model's mark, in the page's ink: Hanzo's H for ours (Enso, Kai and the
* creative models), Zoo Labs Foundation's venn for Zen, a lab's own mark for
* every other model.
*/
function markOf(id: string) {
if (/^zen/.test(id)) return <ProviderMark org="zoo" model={id} ink />
if ([...ENSO, ...KAI].includes(id)) return <ProviderMark org="hanzo" ink />
return <ProviderMark org={getOrgAndSlug(id).org} model={id} />
}
/** Where Zen's weights are published, and who makes them with us. */
const ZENLM = 'https://huggingface.co/zenlm'
const ZOO = 'https://zoo.ngo'
/** One flagship per lab, in the order we would point a visitor at. The model is
* resolved from the live catalogue, so a version bump follows on its own. */
const TOP_LABS = ['anthropic', 'openai', 'google', 'deepseek', 'x-ai', 'meta', 'mistral', 'cohere']
/** A lab's headline general-purpose model: no alias namespace, no point
* variant, no speed or size cut, no dated snapshot, no specialised modality. */
function isCanonical(id: string): boolean {
const slug = id.split('/').pop() ?? id
if (id.startsWith('~') || id.includes(':')) return false
if (/(?:^|[-])(?:fast|flash|mini|nano|tiny|small|lite|air|preview|exp|latest|thinking|code|base|instruct|image|video|audio|voice|tts|embed|embedding|rerank|ocr|guard|moderation)(?:$|[-])/i.test(slug))
return false
if (/-\d{6,}$/.test(slug)) return false
return true
}
function ModelCard({ model }: { model: ModelData }) {
const ctx = context(model)
return (
<Tile
size="lg"
href={modelPagePath(model.id)}
mark={markOf(model.id)}
name={modelName(model)}
id={model.id}
ctx={ctx ? formatContext(ctx) : undefined}
blurb={model.description}
>
{model.modalities && model.modalities.length > 0 && (
<XStack flexWrap="wrap" gap="$1">
{model.modalities.slice(0, 3).map((m) => (
<Modality key={m} name={m} />
))}
</XStack>
)}
</Tile>
)
}
export default async function ModelsPage() {
const data = await fetchModels()
const available = data.models
const byId = new Map(available.map((m) => [m.id, m]))
const enso = ENSO.flatMap((id) => byId.get(id) ?? [])
const zen = ZEN.flatMap((id) => byId.get(id) ?? [])
const kai = KAI.flatMap((id) => byId.get(id) ?? [])
const featured = new Set(FEATURED.flatMap((id) => byId.get(id) ?? []).map((m) => m.id))
const top = TOP_LABS.flatMap((lab) => {
const m = available.find(
(x) => getOrgAndSlug(x.id).org.replace(/^~/, '') === lab && !featured.has(x.id) && isCanonical(x.id),
)
return m ? [m] : []
})
const dEnso = tail(enso.length)
const dZen = tail(zen.length + 1)
const dKai = tail(kai.length + 2)
const dTop = tail(top.length)
// The sample calls an id this catalogue serves: the first featured one.
const called = FEATURED.find((id) => byId.has(id))
const request =
called &&
`curl https://api.hanzo.ai/v1/chat/completions \\
-H "Authorization: Bearer $HANZO_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"model": "${called}",
"messages": [{ "role": "user", "content": "Hello" }]
}'`
return (
<Box minH="100vh" $platform-web={{ color: 'var(--foreground)' }}>
<Box
render="section"
position="relative"
overflow="hidden"
pt={128}
pb={96}
px="$4"
$sm={{ px: '$5' }}
$md={{ pb: 112 }}
$lg={{ px: '$6' }}
>
<View
aria-hidden
position="absolute"
t={0}
l="50%"
x="-50%"
width={800}
height={480}
pointerEvents="none"
backgroundImage="radial-gradient(circle, var(--white-10) 0%, transparent 68%)"
filter="blur(100px)"
/>
<Box position="relative" z="var(--z-raised)" width="100%" maxW={896} mx="auto" $platform-web={{ textAlign: 'center' }}>
<Live />
<Display mb={24}>Every model. One endpoint.</Display>
<Lede mb={32} width="100%" maxW={672} mx="auto">
One API key for every lab. Switch models by changing one string.
</Lede>
{/* The scale, one quiet line: 43 characters at its longest, one row at 390. */}
<Text render="p" display="block" mb="$8" fontSize="$2" lineHeight="$2" color="var(--muted-foreground)">
<Tally of="totalModels" />{' '}
models
<Text aria-hidden px="$2">
·
</Text>
<Tally of="providers" />{' '}
providers
<Text aria-hidden px="$2">
·
</Text>
<Tally of="freeModels" />{' '}
free to call
</Text>
<XStack flexWrap="wrap" justify="center" gap="$4">
<Action href={KEYS} fill>
Get free API key
</Action>
</XStack>
<Box mt="$8" maxW={640} mx="auto" $platform-web={{ textAlign: 'left' }}>
<GuestKey model="zen-free" />
</Box>
</Box>
</Box>
<Family />
<Versus />
{PRODUCT && <AgentPrompt product={PRODUCT} />}
<Band pad="$11" measure={1152}>
<Title quiet mb={40}>
Enso models
</Title>
<Grid columns={{ min: 250, max: 2 }} gap={24}>
{enso.map((model, i) =>
i === enso.length - 1 ? (
<Cell key={model.id} col={dEnso}>
<ModelCard model={model} />
</Cell>
) : (
<ModelCard key={model.id} model={model} />
),
)}
</Grid>
</Band>
<Band pad="$11" measure={1152}>
<Title quiet mb={8}>
Zen models
</Title>
<Lede mb={40} maxW={720}>
Open weights, made with{' '}
<Text render={<a href={ZOO} />} color="inherit" $platform-web={{ textDecoration: 'underline', textUnderlineOffset: '3px' }}>
Zoo Labs Foundation
</Text>
. Download every Zen model at{' '}
<Text render={<a href={ZENLM} />} color="inherit" $platform-web={{ textDecoration: 'underline', textUnderlineOffset: '3px' }}>
huggingface.co/zenlm
</Text>
, or call it here.
</Lede>
<Grid columns={{ min: 250, max: 2 }} gap={24}>
{zen.map((model) => (
<ModelCard key={model.id} model={model} />
))}
<Cell col={dZen}>
<Tile size="lg" mark={markOf(NEXT.id)} name={NEXT.name} id={NEXT.id} blurb={NEXT.blurb}>
<Request />
</Tile>
</Cell>
</Grid>
</Band>
<Band pad="$11" measure={1152}>
<Title quiet mb={40}>
Kai decision models
</Title>
<Grid columns={{ min: 250, max: 2 }} gap={24}>
{kai.map((model) => (
<ModelCard key={model.id} model={model} />
))}
<Tile
size="lg"
href="/kai#benchmarks"
mark={markOf('kai')}
name="Decision Benchmarks"
id={RESULT ? `${RESULT.figure} ${RESULT.label.split(',')[0].toLowerCase()}` : undefined}
ctx={TIMED ? `${TIMED.ms} ms` : undefined}
blurb={RESULTS.headline.lede}
>
<XStack flexWrap="wrap" gap="$1">
<Modality name="benchmarks" />
</XStack>
</Tile>
<Cell col={dKai}>
<Tile
size="lg"
href="/kai#types"
mark={markOf('kai')}
name="Autonomous Agent Steering"
id="decision-ready"
blurb="A choice, a score or a yes/no, each with its probabilities, for agent loops such as Hanzo Dev's."
>
<XStack flexWrap="wrap" gap="$1">
<Modality name="choice" />
<Modality name="score" />
<Modality name="noul" />
</XStack>
</Tile>
</Cell>
</Grid>
</Band>
<Band id="creative" pad="$11" measure={1152}>
<Title quiet mb={8}>
Creative models
</Title>
<Lede mb={40} maxW={720}>
Video, images, 3D, sound effects, voice and music, each its own model, in research preview.
</Lede>
<Grid columns={{ min: 280, max: 3 }} gap={24}>
{CREATIVE_MODELS.map((m) => {
const endpoint = {
koma: 'api.hanzo.ai/v1/video',
iro: 'api.hanzo.ai/v1/images',
mori: 'api.hanzo.ai/v1/3d',
oto: 'api.hanzo.ai/v1/foley',
koe: 'api.hanzo.ai/v1/audio/speech',
uta: 'api.hanzo.ai/v1/music',
}[m.slug] ?? `api.hanzo.ai/v1/${m.slug}`
return (
<Tile
key={m.id}
size="lg"
href={m.route}
mark={<ProviderMark org="hanzo" ink />}
name={m.name}
id={m.modelId}
ctx="Research preview"
blurb={m.lede}
>
<XStack flexWrap="wrap" gap="$1" items="center" justify="space-between" width="100%">
<Modality name={m.role.toLowerCase()} />
<Text
fontSize="$1"
color="var(--muted-foreground)"
fontFamily="$mono"
>
{endpoint}
</Text>
</XStack>
</Tile>
)
})}
</Grid>
</Band>
<Band pad="$11" measure={1152} ground={LIFT}>
<Title quiet mb={40}>
Flagships from other labs
</Title>
<Grid columns={{ min: 250, max: 2 }} gap={24}>
{top.map((model, i) =>
i === top.length - 1 ? (
<Cell key={model.id} col={dTop}>
<ModelCard model={model} />
</Cell>
) : (
<ModelCard key={model.id} model={model} />
),
)}
</Grid>
</Band>
<Band pad="$11" measure={1152}>
<Title quiet>Every model, and what it costs</Title>
<Lede mt="$3.5" mb={40} maxW={672}>
Dollars per million tokens, in and out, from the live catalog.
</Lede>
<Catalog />
</Band>
<Band pad="$11" measure={1152} ground={LIFT}>
<Title quiet>Try any model</Title>
<Lede mt="$3.5" mb={40} maxW={672}>
Test any model directly on the gateway. Switch models by changing one string.
</Lede>
<TryChat />
</Band>
{request ? (
<Band pad="$11" measure={896}>
<Card p="$6" $md={{ p: '$8' }}>
<Box mb="$6" $platform-web={{ textAlign: 'center' }}>
<Title quiet>Your first request</Title>
<Lede mt="$3.5" mx="auto" maxW={672}>
The chat-completions shape you already send, at api.hanzo.ai/v1.
</Lede>
</Box>
<Sample lang="bash">
<Code lang="bash" code={request} />
</Sample>
</Card>
</Band>
) : null}
{PRODUCT && <Related product={PRODUCT} />}
</Box>
)
}