mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
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.
105 lines
4.6 KiB
TypeScript
105 lines
4.6 KiB
TypeScript
'use client'
|
||
|
||
/**
|
||
* Working with Hanzo on /enterprise, from what exists and nothing else: the
|
||
* affiliate programme (/affiliate, which states its own rates), the White-label
|
||
* plan and the agency's plans as the plan list sells them (GET
|
||
* /v1/billing/plans, read when the page opens), and the clouds and silicon
|
||
* Hanzo deploys on (lib/constants/partner-logos `infrastructureLogos`).
|
||
*
|
||
* NO PARTNER IS NAMED, because none is on record: the marks under the cards are
|
||
* vendors Hanzo runs on, and the line beside them says exactly that, never
|
||
* "partners" or "trusted by" (the claim partner-logos.ts was split to keep
|
||
* apart).
|
||
*/
|
||
|
||
import type { LucideIcon } from 'lucide-react'
|
||
import { Handshake, Megaphone, Palette } from 'lucide-react'
|
||
import { Text, View, XStack, YStack } from '@hanzo/ui'
|
||
import { More } from '@hanzo/ui/marketing'
|
||
import { money } from '@hanzo/app/lib/pay'
|
||
import { usePlans } from '@/lib/api/use'
|
||
import type { Plan } from '@/lib/api/read'
|
||
import { infrastructureLogos } from '@/lib/constants/partner-logos'
|
||
import { AGENCY } from '@/components/home/nav-data'
|
||
import { Mark, SALES, Tile } from './kit'
|
||
|
||
type Way = { icon: LucideIcon; title: string; body: string; price?: string; href: string; go: string }
|
||
|
||
/** The cheapest monthly price among rows, as the cards write money. */
|
||
const from = (rows: Plan[]): string | undefined => {
|
||
const prices = rows.map((p) => p.priceMonthly ?? 0).filter((v) => v > 0)
|
||
return prices.length ? money(Math.min(...prices)) : undefined
|
||
}
|
||
|
||
export default function Partners() {
|
||
const reading = usePlans()
|
||
const rows = reading.state === 'ready' ? reading.data : []
|
||
const label = rows.find((p) => p.category === 'white-label')
|
||
const agency = rows.filter((p) => p.category === 'agency')
|
||
const ways: Way[] = [
|
||
{
|
||
icon: Megaphone,
|
||
title: 'Refer customers',
|
||
body: 'Bring organizations to Hanzo and earn a share of Hanzo’s margin on what they spend, every period they spend. The customer’s price does not change.',
|
||
href: '/affiliate',
|
||
go: 'The affiliate programme',
|
||
},
|
||
{
|
||
icon: Palette,
|
||
title: label?.name ? `${label.name}: resell under your brand` : 'Resell under your brand',
|
||
body: label?.description ?? 'Your own AI agency, under your brand, on your domain.',
|
||
price: label?.priceMonthly ? `${money(label.priceMonthly)} a month` : undefined,
|
||
href: SALES,
|
||
go: 'Ask about White-label',
|
||
},
|
||
{
|
||
icon: Handshake,
|
||
title: 'Have Hanzo build it',
|
||
body: agency.length ? `${agency.map((p) => p.name).join(', ')}: Hanzo’s agency ships the work with you, from one workstream to an embedded team.` : 'Hanzo’s agency ships the work with you, from one workstream to an embedded team.',
|
||
price: from(agency) ? `From ${from(agency)} a month` : undefined,
|
||
href: AGENCY,
|
||
go: 'Hanzo Agency',
|
||
},
|
||
]
|
||
return (
|
||
<YStack gap={32}>
|
||
<View display="grid" gap={16} gridTemplateColumns="minmax(0, 1fr)" $md={{ gridTemplateColumns: 'repeat(3, minmax(0, 1fr))' }} data-slot="partners">
|
||
{ways.map(({ icon: Icon, title, body, price, href, go }) => (
|
||
<Tile key={go}>
|
||
<Mark>
|
||
<Icon width={20} height={20} aria-hidden />
|
||
</Mark>
|
||
<Text render="h3" fontSize="$5" lineHeight="1.75rem" fontWeight="600" color="$ink">
|
||
{title}
|
||
</Text>
|
||
<Text render="p" fontSize="$3" lineHeight="1.5rem" color="var(--muted-foreground)">
|
||
{body}
|
||
</Text>
|
||
{price ? (
|
||
<Text render="p" fontSize="$3" fontWeight="600" color="$ink" $platform-web={{ fontVariantNumeric: 'tabular-nums' }}>
|
||
{price}
|
||
</Text>
|
||
) : null}
|
||
<XStack mt="auto" pt={8}>
|
||
<More href={href}>{`${go} →`}</More>
|
||
</XStack>
|
||
</Tile>
|
||
))}
|
||
</View>
|
||
<YStack gap={16} items="center">
|
||
<Text render="p" fontSize="$2" color="var(--muted-foreground)" text="center" maxW={560}>
|
||
Hanzo runs in your cloud and on these. They are the clouds and the silicon Hanzo deploys on, not partners or customers.
|
||
</Text>
|
||
<XStack flexWrap="wrap" justify="center" items="center" columnGap={40} rowGap={20} data-slot="runs-on">
|
||
{infrastructureLogos.map((l) => (
|
||
<View key={l.name} height={l.height ?? 24} filter="brightness(0) invert(1)" $theme-light={{ filter: 'brightness(0)' }} opacity={0.7}>
|
||
<View render={<img src={l.src} alt={l.name} loading="lazy" />} display="block" height={l.height ?? 24} width="auto" />
|
||
</View>
|
||
))}
|
||
</XStack>
|
||
</YStack>
|
||
</YStack>
|
||
)
|
||
}
|