Files
Cursor Agentandz c3af929c56 site: one API, one account, better cheaper faster
The bar is Models, Dev, Platform, Pricing, Docs, Enterprise, Log in, and Get API key. The homepage is seven sections. Launch pages stay in the tree and drop out of the index through lib/launch.ts. /platform forwards to /cloud. Model and repository floors come from the snapshots the build already keeps.

Co-authored-by: z <[email protected]>
2026-10-26 21:53:40 +00:00

82 lines
3.7 KiB
TypeScript

'use client'
import type { ReactNode } from 'react'
import { useAnalytics } from '@hanzo/event/react'
import { YStack } from '@hanzo/gui'
import { phrase, translate } from '@hanzo/i18n'
import { useI18n, type Say } from '@hanzo/i18n/react'
import { Faq, TextLink } from '@hanzo/ui/marketing'
import { FaqJsonLd, plain } from '@/components/marketing/FaqJsonLd'
/**
* The questions a stranger arrives with on the landing, answered against what
* Hanzo ships today. No price and no plan name is written here: the plans above
* draw both from the catalog, and an answer that names one is a second copy
* that goes stale (scripts/audit-price-literals.mjs).
*
* Each question is a phrase and each answer is drawn by the `t` it is handed:
* the reader's language on the page, and `english` for the structured copy
* (FaqJsonLd), which speaks for the English export to a crawler whatever the
* reader chose.
*/
const FAQ: readonly { q: string; a: (t: Say) => ReactNode }[] = [
{
q: phrase('What is Hanzo and how does it work?'),
a: (t) =>
t(
'Hanzo is an AI cloud on one account. Chat with frontier models, build and ship with Hanzo Dev, and call the same models from one API: Enso, our frontier model, and Kai, which makes a decision in one call. {link}.',
{ link: <TextLink href="/cloud">{t('How the platform fits together')}</TextLink> },
),
},
{
q: phrase('Can I keep using Claude Code?'),
a: (t) =>
t(
'Yes. Install the Hanzo CLI and sign in, then run Claude Code with its model calls going through api.hanzo.ai, or point your own Claude Code install at Hanzo. The commands are at the top of this page, ready to copy.',
),
},
{
q: phrase('Where do the numbers on this page come from?'),
a: (t) =>
t(
"Each one is read when the page opens: the race and the boards from Hanzo's research runs, the prices from our price list, and the plans from our plan list. A figure whose source does not answer is left out, never replaced with an older one. {link}.",
{ link: <TextLink href="/benchmarks">{t('Every board and its runs')}</TextLink> },
),
},
{
q: phrase('How much does it cost to use?'),
a: (t) =>
t(
'Free needs no card. Paid plans are sold by the month for one person and by the member for a team, and every paid plan can be cancelled any time. Enterprise is priced with our team. {link}.',
{ link: <TextLink href="/pricing">{t('See every plan and model rate')}</TextLink> },
),
},
{
q: phrase('Can Hanzo run in our own cloud or on our own GPUs?'),
a: (t) =>
t('Yes, with Enterprise: in your cloud, on your own servers or fully offline, with dedicated compute and your own models. {link}.', {
link: <TextLink href="/enterprise">Hanzo Enterprise</TextLink>,
}),
},
]
/** A message as written, its arguments read down to their words: the answers in the English the structured copy carries. */
const english: Say = (source: string, values: Readonly<Record<string, ReactNode>> = {}) =>
translate({}, source, Object.fromEntries(Object.entries(values).map(([k, v]) => [k, plain(v)])))
export default function Questions() {
const { t } = useI18n()
const events = useAnalytics()
return (
<YStack width="100%" py={56} $md={{ py: 80 }}>
<FaqJsonLd path="/" items={FAQ.map((f) => ({ name: f.q, answer: f.a(english) }))} />
<Faq
heading={t('FAQ')}
items={FAQ.map((f) => ({ q: t(f.q), a: f.a(t) }))}
// The event names the question as written, in whichever language it was read.
onOpen={(q) => events.capture('faq_opened', { q: FAQ.find((f) => t(f.q) === q)?.q ?? q })}
/>
</YStack>
)
}