Files
zeekayandGitHub 3df66c3990 i18n: /m* through /r* and the product kits draw their words through t (#70)
Pages from /machines to /risk, the model pages, and the kits they are made of
(page-kit, ProductLanding, LayerPage, Stack, the models kit, band's Head) mark
authored copy where it is written and draw it in the reader's language. A server
page marks a literal phrase('…') or wraps it in <T>; a client page calls t. The
kits translate a string prop through useSay (components/marketing/say), so a
page passes phrase('…') and markup passes as written. An arrow that points
turns over right to left (data-i18n-mirror).

Rebased on main: the fold-based heroes (Fold, PageHero, MachinesHero, the
product and layer pages) keep main's structure and copy, with their label,
title and lede marked phrase. /platform is main's CloudLanding; the deleted
/platform/layers and the old referral components stay deleted.

Claude-Session: https://claude.ai/code/session_015XYKLjZtDTJEnMo4eK3AFH
2026-10-30 00:18:44 -07:00

417 lines
17 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 { Fold } from '@/components/marketing/fold'
import { Answer, type Spoken } from '@/components/preview/answer'
import { phrase } from '@hanzo/i18n'
import { T } from '@hanzo/i18n/react'
import { ProviderMark } from '@hanzo/app/ProviderMark'
import { TryChat } from '@/components/models/TryChat'
import { Modality, Tile } from '@/components/models/kit'
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 { Box, Text, XStack } from '@/components/ui'
import { Action, Lede, More, 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 { 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, USES } from '@/lib/zen'
import { KAI as RESULTS } from '@/lib/bench-data'
import { p50 } from '@/lib/kai'
import { Code } from '@/components/code'
import { examples } from '@/lib/models/examples'
import { Samples } from '@/components/models/Samples'
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, size?: number) {
if (/^zen/.test(id)) return <ProviderMark org="zoo" model={id} size={size} ink />
if ([...ENSO, ...KAI].includes(id)) return <ProviderMark org="hanzo" size={size} ink />
return <ProviderMark org={getOrgAndSlug(id).org} model={id} size={size} />
}
/** 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>
)
}
/** The deep link a section ends on: the page or the docs that go further than the cards. */
function Onward({ href, children }: { href: string; children: string }) {
return (
<XStack mt="$6" justify="center">
<More href={href}><T>{children}</T> →</More>
</XStack>
)
}
/** A model as the first screen's preview says it: its name, its words, its mark and the facts the catalog states. */
function spoken(m: ModelData, name = modelName(m), says = m.description ?? ''): Spoken {
const ctx = context(m)
return { id: m.id, name, says, mark: markOf(m.id, 16), facts: [...(ctx ? [formatContext(ctx)] : []), ...(m.modalities ?? []).slice(0, 2)] }
}
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, in four languages.
const called = FEATURED.find((id) => byId.has(id))
const request = called ? examples({ id: called, endpoint: byId.get(called)?.endpoint }) : null
// The first screen's models, each answering in its own words: the router, the
// open weights (lib/zen's words, since the catalog gives Zen none) and the first
// flagship the page lists from another lab. Kai answers at /v1/decisions, not
// here, so its own page draws its decision.
const asked: Spoken[] = [
...enso.slice(0, 1).map((m) => spoken(m)),
...zen.slice(0, 1).map((m) => spoken(m, NOW.name, USES.map((u) => u.detail).join(' '))),
...top.slice(0, 1).map((m) => spoken(m)),
].filter((m) => m.says)
return (
<Box minH="100vh" $platform-web={{ color: 'var(--foreground)' }}>
<Fold
label={phrase('Models')}
title={phrase('Frontier AI families')}
lede={phrase('Proprietary and open weight models for text, decisions, video, image, and more — one account, one API key.')}
actions={
<>
<Action href={KEYS} fill>
<T>Get API key</T>
</Action>
<Action href="#catalog">
<T>Every model</T>
</Action>
</>
}
below={<Live />}
preview={<Answer models={asked} />}
/>
{/* The three families side by side, then how Enso and Zen are had (LLM.md "/models explains the three families"). */}
<Family />
<Versus />
<Box position="relative" width="100%" maxW={896} mx="auto" px="$4" $sm={{ px: '$5' }} $lg={{ px: '$6' }} $platform-web={{ textAlign: 'center' }}>
<Band pad="$11" measure={1152}>
<Title quiet mb={40}>
<T>Enso models</T>
</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>
<Onward href="/enso">{phrase('Enso: the router, its presets and its runs')}</Onward>
</Band>
<Band pad="$11" measure={1152}>
<Title quiet mb={8}>
<T>Zen models</T>
</Title>
<Lede mb={40} maxW={720}>
<T
values={{
zoo: (
<Text render={<a href={ZOO} />} color="inherit" $platform-web={{ textDecoration: 'underline', textUnderlineOffset: '3px' }}>
Zoo Labs Foundation
</Text>
),
hub: (
<Text render={<a href={ZENLM} />} color="inherit" $platform-web={{ textDecoration: 'underline', textUnderlineOffset: '3px' }}>
huggingface.co/zenlm
</Text>
),
}}
>
{'Open weights, made with {zoo}. Download every Zen model at {hub}, or call it here.'}
</T>
</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>
<Onward href="https://docs.hanzo.ai/docs/models/zen">{phrase('Run Zen: the docs')}</Onward>
</Band>
<Band pad="$11" measure={1152}>
<Title quiet mb={40}>
<T>Kai decision models</T>
</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={<T>Decision Benchmarks</T>}
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={<T>benchmarks</T>} />
</XStack>
</Tile>
<Cell col={dKai}>
<Tile
size="lg"
href="/kai#types"
mark={markOf('kai')}
name={<T>Autonomous Agent Steering</T>}
id="decision-ready"
blurb={<T>{"A choice, a score or a yes/no, each with its probabilities, for agent loops such as Hanzo Dev's."}</T>}
>
<XStack flexWrap="wrap" gap="$1">
<Modality name="choice" />
<Modality name="score" />
<Modality name="noul" />
</XStack>
</Tile>
</Cell>
</Grid>
<Onward href="/kai">{phrase('Kai: decisions and their benchmarks')}</Onward>
</Band>
<Band id="creative" pad="$11" measure={1152}>
<Title quiet mb={8}>
<T>Creative models</T>
</Title>
<Lede mb={40} maxW={720}>
<T>Video, images, 3D, sound effects, voice and music, each its own model, in research preview.</T>
</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={<T>Research preview</T>}
blurb={<T>{m.lede}</T>}
>
<XStack flexWrap="wrap" gap="$1" items="center" justify="space-between" width="100%">
<Modality name={<T>{m.role}</T>} />
<Text
fontSize="$1"
color="var(--muted-foreground)"
fontFamily="$mono"
>
{endpoint}
</Text>
</XStack>
</Tile>
)
})}
</Grid>
<Onward href="/studio">{phrase('Make something in Studio')}</Onward>
</Band>
<Band pad="$11" measure={1152} ground={LIFT}>
<Title quiet mb={40}>
<T>Flagships from other labs</T>
</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>
<Onward href="#catalog">{phrase('Every model, priced')}</Onward>
</Band>
<Band id="catalog" pad="$11" measure={1152}>
<Title quiet>
<T>Every model, and what it costs</T>
</Title>
<Lede mt="$3.5" mb={40} maxW={672}>
<T>Dollars per million tokens, in and out, from the live catalog.</T>
</Lede>
<Catalog />
<Onward href="https://docs.hanzo.ai/docs/models">{phrase('How models are called and billed')}</Onward>
</Band>
<Band pad="$11" measure={1152} ground={LIFT}>
<Title quiet>
<T>Try any model</T>
</Title>
<Lede mt="$3.5" mb={40} maxW={672}>
<T>Test any model directly on the gateway. Switch models by changing one string.</T>
</Lede>
<TryChat />
</Band>
{request ? (
<Band pad="$11" measure={896}>
<Card p="$6" $md={{ p: '$8' }}>
<Box mb="$6" $platform-web={{ textAlign: 'center' }}>
<Title quiet>
<T>Your first request</T>
</Title>
<Lede mt="$3.5" mx="auto" maxW={672}>
<T>The chat-completions shape you already send, at api.hanzo.ai/v1, in the language you write.</T>
</Lede>
</Box>
<Box $platform-web={{ textAlign: 'start' }}>
<Samples
samples={[
{ lang: 'cURL', code: request.curl, sample: <Code lang="bash" code={request.curl} /> },
{ lang: 'Python', code: request.py, sample: <Code lang="python" code={request.py} /> },
{ lang: 'TypeScript', code: request.ts, sample: <Code lang="typescript" code={request.ts} /> },
{ lang: 'Go', code: request.go, sample: <Code lang="go" code={request.go} /> },
]}
/>
</Box>
<XStack mt="$5" flexWrap="wrap" columnGap={24} rowGap={8} justify="center">
<More href={KEYS}><T>Get an API key</T> →</More>
<More href="https://docs.hanzo.ai/docs/quickstart"><T>The quickstart</T> →</More>
</XStack>
</Card>
</Band>
) : null}
{PRODUCT && <Related product={PRODUCT} />}
</Box>
</Box>
)
}