Files
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

103 lines
3.3 KiB
TypeScript

import type { ReactNode } from 'react'
import { Check } from 'lucide-react'
import { Box, Text, XStack, YStack } from '@/components/ui'
import { Eyebrow, More, Title } from '@hanzo/ui/marketing'
import { Grid } from '@hanzo/ui/grid'
import { Card } from '@/components/marketing/band'
import { ProviderMark } from '@hanzo/app/ProviderMark'
/**
* Enso against Zen, on /models: how each one is had. Enso is ours and answers
* on Hanzo Cloud only; Zen's weights are published. What each family does is
* Family's, above it, so neither card says it again. A server component, all
* gui props.
*/
const SIDES: readonly { name: string; model: string; org: string; terms: string; points: readonly string[]; href: string; lit?: boolean }[] = [
{
name: 'Enso',
model: 'hanzo',
org: 'hanzo',
terms: 'Proprietary · Hanzo Cloud only',
points: ['Flash, Pro and Ultra presets', 'OpenAI- and Anthropic-compatible', 'Metered and audited per organization'],
href: '/enso',
lit: true,
},
{
name: 'Zen',
model: 'zen6',
org: 'zoo',
terms: 'Open weights · Zoo Labs Foundation',
points: ['Free to download and self-host', 'Or call it on Hanzo Cloud', 'From a 501(c)(3) non-profit'],
href: '/zen',
},
]
function Point({ children }: { children: ReactNode }) {
return (
<Text render="li" display="flex" items="center" gap="$2" fontSize="$3" lineHeight="$3" color="var(--text-secondary)">
<Text display="inline-flex" shrink={0} color="$ink">
<Check size={16} />
</Text>
{children}
</Text>
)
}
export function Versus() {
return (
<Box
render="section"
aria-labelledby="versus-title"
py="$11"
px="$4"
$sm={{ px: '$5' }}
$lg={{ px: '$6' }}
borderTopWidth={1}
borderColor="var(--border)"
>
<Grid columns={1} gap={40} width="100%" maxW={1024} mx="auto">
<Grid columns={1} gap={14} width="100%" maxW={672} mx="auto" $platform-web={{ textAlign: 'center' }}>
<Eyebrow>Enso vs Zen</Eyebrow>
<Title id="versus-title">Proprietary orchestration, on open foundations</Title>
</Grid>
<Grid columns={{ min: 300, max: 2 }} gap={24}>
{SIDES.map((s) => (
<Card
key={s.name}
display="flex"
flexDirection="column"
gap="$5"
p="$6"
borderColor={s.lit ? 'var(--border-strong)' : 'var(--border)'}
bg={s.lit ? '$hover' : '$panel'}
>
<XStack items="center" gap="$3">
<ProviderMark org={s.org} model={s.model} ink />
<YStack>
<Text render="h3" fontSize="$6" lineHeight="$6" fontWeight="600" color="$ink">
{s.name}
</Text>
<Text fontSize="$2" lineHeight="$2" color="var(--muted-foreground)">
{s.terms}
</Text>
</YStack>
</XStack>
<Text render="ul" display="grid" gap="$2" m={0} p={0}>
{s.points.map((p) => (
<Point key={p}>{p}</Point>
))}
</Text>
<More href={s.href} mt="auto">
Explore {s.name} →
</More>
</Card>
))}
</Grid>
</Grid>
</Box>
)
}
export default Versus