mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
73 lines
2.9 KiB
TypeScript
73 lines
2.9 KiB
TypeScript
'use client'
|
|
|
|
import { H1, Paragraph, YStack } from '@hanzo/gui'
|
|
import { Grid } from '@hanzo/ui/grid'
|
|
|
|
import { SurfaceCard } from '@/components/download/surface-card'
|
|
import { LEAD, REST } from '@/data/downloads'
|
|
|
|
/**
|
|
* Every way to get Hanzo, on one page.
|
|
*
|
|
* THE PAGE IS HERE, and it is the only copy. It stood on hanzo.app and this
|
|
* route was a shell that forwarded to it — which held only while that host
|
|
* served the page itself. hanzo.app answers with a redirect now: its root sends
|
|
* a reader here and every other path to the builder, so a forward from this
|
|
* route arrived back at /dev and the download page could not be reached in a
|
|
* browser at all. A page that two hosts point at is a page with no home.
|
|
*
|
|
* A surface appears iff a READER can act on it. The builds come from
|
|
* `data/releases.json`, which `scripts/sync-releases.mjs` resolves anonymously
|
|
* against the real releases on every build, so a platform that publishes
|
|
* nothing — or publishes only where the public cannot reach — stops rendering
|
|
* rather than becoming a button that 404s. There is deliberately no mobile
|
|
* card: no iOS or Android build has shipped to either store, and a tile that
|
|
* apologises for itself occupies the place of a product. `data/downloads.ts`
|
|
* carries both measurements.
|
|
*
|
|
* The chrome is the marketing layout's, which draws the header and footer for
|
|
* every page in this group, and the title comes from `layout.tsx` beside this
|
|
* file — so this file is the content and nothing else.
|
|
*/
|
|
export default function DownloadPage() {
|
|
return (
|
|
<YStack
|
|
px="$4"
|
|
pt="$8"
|
|
pb="$10"
|
|
$md={{ px: '$6', pt: '$10' }}
|
|
>
|
|
{/* `width="100%"` is load-bearing on a centred column: without it
|
|
`alignSelf="center"` is shrink-to-fit and `maxWidth` caps a width the
|
|
column never takes, which reads as a section that is silently narrow. */}
|
|
<YStack self="center" width="100%" maxW={1152} gap="$8">
|
|
<YStack gap="$4" maxW={720}>
|
|
<H1
|
|
fontSize="$11"
|
|
fontWeight="500"
|
|
letterSpacing={-0.5}
|
|
color="$color"
|
|
$md={{ fontSize: 56 }}
|
|
>
|
|
Get Hanzo everywhere you work.
|
|
</H1>
|
|
<Paragraph fontSize="$5" color="$color11">
|
|
One account, one key. Install the coding agent, open the workspaces
|
|
that need nothing installed, and sign in to all of them the same way.
|
|
</Paragraph>
|
|
</YStack>
|
|
|
|
<SurfaceCard surface={LEAD} lead />
|
|
|
|
{/* auto-fit rather than auto-fill: the row is a fixed set of surfaces,
|
|
so a survivor stretches across the empty track instead of leaving it. */}
|
|
<Grid columns="repeat(auto-fit, minmax(min(460px, 100%), 1fr))" gap={20} items="flex-start">
|
|
{REST.map((s) => (
|
|
<SurfaceCard key={s.id} surface={s} />
|
|
))}
|
|
</Grid>
|
|
</YStack>
|
|
</YStack>
|
|
)
|
|
}
|