mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
The owner's spec for a landing page is the models bento's: monochrome, the words left and the art right, no extra prose. The folds carried two to four sentences under each heading, and some a claim, a lede and a list besides. Each now says one line: ProductLanding the tagline where a page states one (the lede still describes it to search), a claim alone where the claim is the line (/payments, /treasury, /zap, the extension), and elsewhere the sentence that says what the thing is. /philosophy's two points, /dns' claim that repeated its title, /calculator's capabilities line and the Spare clauses on /research and /learn go.
257 lines
13 KiB
TypeScript
257 lines
13 KiB
TypeScript
'use client'
|
||
|
||
/**
|
||
* /enterprise — the page a large organization reads before it talks to us.
|
||
*
|
||
* One call to action, "Talk to sales" (/contact-sales), at the top and again at
|
||
* the end; the closing call the marketing layout mounts is quiet here
|
||
* (components/marketing/Closing `QUIET`).
|
||
*
|
||
* Every claim has a record behind it:
|
||
* - what Enterprise includes: the `enterprise` plan of GET /v1/billing/plans,
|
||
* and Team's "Single sign-on, roles and an audit log" under it;
|
||
* - where it runs: the same plan (components/sales/Deploy);
|
||
* - security: the mechanisms /trust states from the code, and the Privacy
|
||
* Policy's Service Only default for business accounts (content/legal/privacy.md);
|
||
* - proof: the research runs and the data room's case studies
|
||
* (components/sales/Proof);
|
||
* - savings: the same tokens at list, on Hanzo Cloud and on the reader's
|
||
* own GPUs, every rate read from the price list and the plan list when the
|
||
* page opens (components/sales/Savings);
|
||
* - own GPUs: Zen 6's prefill as Hanzo measured it on one DGX Spark
|
||
* (lib/data/zen6-spark.json) and what a Zen 6 Max rack is made of, from
|
||
* NVIDIA's own pages (components/enterprise/Rack);
|
||
* - working with Hanzo: the affiliate programme, the White-label and agency
|
||
* plans as the plan list sells them, and the clouds Hanzo deploys on
|
||
* (components/sales/Partners). No partner is named: none is on record.
|
||
*
|
||
* The cards are the funnel's (components/sales/kit): the `--muted` ground, the
|
||
* hairline, the 56px pill.
|
||
*/
|
||
|
||
import type { ReactNode } from 'react'
|
||
import dynamic from 'next/dynamic'
|
||
import { useAnalytics } from '@hanzo/event/react'
|
||
import { Check, Cpu, FileCheck, Headphones, KeyRound, Lock, ScrollText, Server, Sparkles, UserCheck, Users } from 'lucide-react'
|
||
import type { LucideIcon } from 'lucide-react'
|
||
import { Text, XStack, YStack } from '@hanzo/ui'
|
||
import { Grid } from '@hanzo/ui/grid'
|
||
import { Faq, Lede, More, TextLink, Title } from '@hanzo/ui/marketing'
|
||
import { Band, Head } from '@/components/marketing/band'
|
||
import { FaqJsonLd } from '@/components/marketing/FaqJsonLd'
|
||
import Deploy, { STOPS } from '@/components/sales/Deploy'
|
||
import { Fold } from '@/components/marketing/fold'
|
||
import { Steps } from '@/components/preview/steps'
|
||
import Proof from '@/components/sales/Proof'
|
||
import { MAILBOX, Mark, Talk, Tile } from '@/components/sales/kit'
|
||
import { phrase } from '@hanzo/i18n'
|
||
import { useI18n } from '@hanzo/i18n/react'
|
||
|
||
// Below the first screen, so each is prerendered into the HTML and its script
|
||
// loads at low priority, outside the first load perf.budget.json holds.
|
||
const Savings = dynamic(() => import('@/components/sales/Savings'))
|
||
const Own = dynamic(() => import('@/components/enterprise/Own'))
|
||
const Partners = dynamic(() => import('@/components/sales/Partners'))
|
||
|
||
type Point = { icon: LucideIcon; title: string; body: string }
|
||
|
||
/** What the Enterprise plan includes, in the plan's own terms. */
|
||
const INCLUDES: readonly Point[] = [
|
||
{ icon: Server, title: phrase('Your infrastructure'), body: phrase('Run Hanzo in your cloud, on your own servers, or fully offline.') },
|
||
{ icon: Cpu, title: phrase('Dedicated compute'), body: phrase('Compute set aside for your organization alone.') },
|
||
{ icon: Sparkles, title: phrase('Your own models'), body: phrase('Train and host your own models, on your own data.') },
|
||
{ icon: FileCheck, title: phrase('Commitments in writing'), body: phrase('An uptime guarantee and a security review, both in your contract.') },
|
||
{ icon: Headphones, title: phrase('24/7 engineering support'), body: phrase('Engineering support around the clock, and hands-on onboarding to get your teams started.') },
|
||
{ icon: Users, title: phrase('Your whole company'), body: phrase('Unlimited members, single sign-on, roles and an audit log.') },
|
||
]
|
||
|
||
/** What a security review finds, each a mechanism /trust states from the code. */
|
||
const SECURITY: readonly Point[] = [
|
||
{ icon: KeyRound, title: phrase('Single sign-on'), body: phrase('Sign in through your own OpenID Connect provider. SCIM 2.0 creates, updates and removes accounts from your directory.') },
|
||
{ icon: Lock, title: phrase('Your data, apart'), body: phrase("On Hanzo Base, each organization's data is its own database file, kept apart from every other organization. Identity comes only from a verified token.") },
|
||
{ icon: ScrollText, title: phrase('Audit log'), body: phrase('Every request is recorded: who acted, from where, what they called and the status it returned.') },
|
||
{ icon: UserCheck, title: phrase('Roles and second factors'), body: phrase('Grant access by organization, workspace and project. Every account can add an authenticator app, or a code by SMS or email.') },
|
||
]
|
||
|
||
/** The questions, in the reader's language; the schema reads the same nodes. */
|
||
const faq = (t: ReturnType<typeof useI18n>['t']): readonly { q: string; a: ReactNode }[] => [
|
||
{
|
||
q: t('How is Enterprise priced?'),
|
||
a: t('Each contract is priced for your organization: where Hanzo runs and the compute you need. Members are unlimited. {link} for a quote.', {
|
||
link: <TextLink href="/contact-sales">{t('Talk to sales')}</TextLink>,
|
||
}),
|
||
},
|
||
{
|
||
q: t('Where do the savings figures come from?'),
|
||
a: t('Every rate is read from our price list and our plan list when the page opens; the volumes, the people and the GPUs are yours. The figure for your own GPUs counts them on all month at an hourly rate and leaves out the Enterprise agreement, which our team prices with you.'),
|
||
},
|
||
{
|
||
q: t('Can Hanzo run fully offline?'),
|
||
a: t('Yes. Hanzo runs air-gapped on your own servers, with models served on machines you control.'),
|
||
},
|
||
{
|
||
q: t('How is our data used?'),
|
||
a: t("Your data is used to run your service. Training Hanzo models on it takes your administrator's choice or a written agreement. {link}.", {
|
||
link: <TextLink href="/privacy">{t('Read the Privacy Policy')}</TextLink>,
|
||
}),
|
||
},
|
||
{
|
||
q: t('Which identity providers work?'),
|
||
a: t('Your own OpenID Connect provider, for single sign-on. SCIM 2.0 creates, updates and removes accounts as your directory changes.'),
|
||
},
|
||
{
|
||
q: t('Can we start on Team and move up?'),
|
||
a: t('Yes. Team covers 2 to 100 people today, with single sign-on, roles and an audit log. Move to Enterprise when you want your own infrastructure, dedicated compute or more people. {link}.', {
|
||
link: <TextLink href="/pricing">{t('Compare plans')}</TextLink>,
|
||
}),
|
||
},
|
||
]
|
||
|
||
/** The three promises under the hero's call. */
|
||
const PROMISES = [phrase('Unlimited members'), phrase('24/7 engineering support'), phrase('Runs fully offline')]
|
||
|
||
export default function Enterprise() {
|
||
const events = useAnalytics()
|
||
const { t } = useI18n()
|
||
const FAQ = faq(t)
|
||
return (
|
||
<>
|
||
{/* The first screen: the outcome, what it is, the one call, and where it runs, from the fastest start to the most control. */}
|
||
<Fold
|
||
label="Hanzo Enterprise"
|
||
title={
|
||
<>
|
||
{t('Give every team AI.')}{' '}
|
||
<br />
|
||
{t('Run it where you choose.')}
|
||
</>
|
||
}
|
||
lede={t('Models, agents and one shared workspace for everyone in your company, in your cloud, on your servers or fully offline.')}
|
||
actions={<Talk onClick={() => events.capture('enterprise_cta', { at: 'hero' })} />}
|
||
below={
|
||
<XStack flexWrap="wrap" justify="center" columnGap={24} rowGap={8} $lg={{ justify: 'flex-start' }}>
|
||
{PROMISES.map((promise) => (
|
||
<XStack key={promise} items="center" gap={6}>
|
||
<Check width={14} height={14} color="var(--foreground)" aria-hidden />
|
||
<Text fontSize="$2" color="var(--muted-foreground)">
|
||
{t(promise)}
|
||
</Text>
|
||
</XStack>
|
||
))}
|
||
</XStack>
|
||
}
|
||
preview={<Steps title={t('Where it runs')} steps={STOPS.map((s) => ({ title: t(s.name), body: t('{where}. {line}', { where: t(s.where), line: t(s.line) }) }))} />}
|
||
/>
|
||
|
||
<Band id="includes" rule={false} pad="$11" measure={1152}>
|
||
<Head loud eyebrow={t('What you get')} title={t('What Enterprise includes.')} lede={t('Your own infrastructure, dedicated compute, and engineering support around the clock.')} />
|
||
<Grid columns={{ min: 280, max: 3 }} gap={16}>
|
||
{INCLUDES.map(({ icon: Icon, title, body }) => (
|
||
<Tile key={title}>
|
||
<Mark>
|
||
<Icon width={20} height={20} aria-hidden />
|
||
</Mark>
|
||
<Text render="h3" fontSize="$5" lineHeight="1.75rem" fontWeight="600" color="$ink">
|
||
{t(title)}
|
||
</Text>
|
||
<Text render="p" fontSize="$3" lineHeight="1.5rem" color="var(--muted-foreground)">
|
||
{t(body)}
|
||
</Text>
|
||
</Tile>
|
||
))}
|
||
</Grid>
|
||
</Band>
|
||
|
||
<Band id="deploy" pad="$11" measure={1152}>
|
||
<Head loud eyebrow={t('Deployment')} title={t('Run it where your data lives.')} lede={t('One platform, four places to run it. Choose one, or start in our cloud and move when you are ready.')} />
|
||
<Deploy />
|
||
</Band>
|
||
|
||
<Band id="savings" pad="$11" measure={1152}>
|
||
<Head
|
||
loud
|
||
eyebrow={t('Savings')}
|
||
title={t('What the same tokens cost.')}
|
||
lede={t('Put in what your teams use today. The page prices it at the providers’ list rates, on Hanzo Cloud, and on GPUs of your own, every rate read from our price list as you look.')}
|
||
/>
|
||
<Savings />
|
||
<XStack justify="center" mt={32}>
|
||
<More href="/calculator">{t('The whole operating-cost model')}</More>
|
||
</XStack>
|
||
</Band>
|
||
|
||
<Band id="gpus" pad="$11" measure={1152}>
|
||
<Head
|
||
loud
|
||
eyebrow={t('Your own GPUs')}
|
||
title={t('Run the models on machines you own.')}
|
||
lede={t('Zen 6 runs on one DGX Spark. Zen 6 Max wants a rack of Blackwell servers. What we measured, and what a rack is made of.')}
|
||
/>
|
||
<Own />
|
||
</Band>
|
||
|
||
<Band id="proof" pad="$11" measure={1152}>
|
||
<Head
|
||
loud
|
||
eyebrow={t('Proof')}
|
||
title={t('Results on the record.')}
|
||
lede={t("Our models' scores come from research runs anyone can open. Customer results come from the case studies of launches Hanzo ran.")}
|
||
/>
|
||
<Proof />
|
||
<XStack justify="center" mt={32}>
|
||
<More href="/customers">{t('All customer stories')}</More>
|
||
</XStack>
|
||
</Band>
|
||
|
||
<Band id="partners" pad="$11" measure={1152}>
|
||
<Head loud eyebrow={t('Partners')} title={t('Work with Hanzo.')} lede={t('Refer customers, resell Hanzo under your own brand, or have Hanzo’s agency build it with you.')} />
|
||
<Partners />
|
||
</Band>
|
||
|
||
<Band id="security" pad="$11" measure={1152}>
|
||
<Head loud eyebrow={t('Security')} title={t('Ready for your security review.')} lede={t('A security review is part of every Enterprise contract. We answer your questionnaire against the code, and the engineers who wrote it walk your reviewers through it.')} />
|
||
<Grid columns={{ min: 260, max: 2 }} gap={16}>
|
||
{SECURITY.map(({ icon: Icon, title, body }) => (
|
||
<Tile key={title} flexDirection="row" gap={16}>
|
||
<Mark>
|
||
<Icon width={20} height={20} aria-hidden />
|
||
</Mark>
|
||
<YStack gap={6} minW={0} shrink={1}>
|
||
<Text render="h3" fontSize="$5" lineHeight="1.75rem" fontWeight="600" color="$ink">
|
||
{t(title)}
|
||
</Text>
|
||
<Text render="p" fontSize="$3" lineHeight="1.5rem" color="var(--muted-foreground)">
|
||
{t(body)}
|
||
</Text>
|
||
</YStack>
|
||
</Tile>
|
||
))}
|
||
</Grid>
|
||
<XStack justify="center" flexWrap="wrap" columnGap={32} rowGap={12} mt={32}>
|
||
<More href="/security">{t('How Hanzo is secured')}</More>
|
||
<More href="/trust">{t('Trust center')}</More>
|
||
</XStack>
|
||
</Band>
|
||
|
||
<Band id="faq" pad="$11" measure={880}>
|
||
<FaqJsonLd path="/enterprise" items={FAQ.map((f) => ({ name: f.q, answer: f.a }))} />
|
||
<Faq heading={t('Questions')} items={FAQ} onOpen={(q) => events.capture('faq_opened', { q, page: 'enterprise' })} />
|
||
</Band>
|
||
|
||
{/* The call again, where the page ends. */}
|
||
<Band id="talk" pad="$12" measure={880}>
|
||
<YStack items="center" gap={20} $platform-web={{ textAlign: 'center' }}>
|
||
<Title>{t('Tell us what you want to build.')}</Title>
|
||
<Lede maxW={600}>{t('Share a few details about your company. We come back with a plan: where Hanzo runs, what it costs and how you start.')}</Lede>
|
||
<XStack mt={8}>
|
||
<Talk onClick={() => events.capture('enterprise_cta', { at: 'end' })} />
|
||
</XStack>
|
||
<Text render="p" fontSize="$2" color="var(--muted-foreground)">
|
||
{t('Or email {mailbox}', { mailbox: <TextLink href={`mailto:${MAILBOX}`}>{MAILBOX}</TextLink> })}
|
||
</Text>
|
||
</YStack>
|
||
</Band>
|
||
</>
|
||
)
|
||
}
|