mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
Pages from /machines to /risk, the model pages, and the kits they are made of
(page-kit, ProductLanding, LayerPage, Stack, the models kit, band's Head) mark
authored copy where it is written and draw it in the reader's language. A server
page marks a literal phrase('…') or wraps it in <T>; a client page calls t. The
kits translate a string prop through useSay (components/marketing/say), so a
page passes phrase('…') and markup passes as written. An arrow that points
turns over right to left (data-i18n-mirror).
Rebased on main: the fold-based heroes (Fold, PageHero, MachinesHero, the
product and layer pages) keep main's structure and copy, with their label,
title and lede marked phrase. /platform is main's CloudLanding; the deleted
/platform/layers and the old referral components stay deleted.
Claude-Session: https://claude.ai/code/session_015XYKLjZtDTJEnMo4eK3AFH
111 lines
5.3 KiB
TypeScript
111 lines
5.3 KiB
TypeScript
'use client'
|
|
|
|
import { ArrowRight, Globe, KeyRound, Layers, Shield, UserCheck, Zap } from 'lucide-react'
|
|
import { ProductLanding, Session } from '@/components/product/ProductLanding'
|
|
import { ProductFooter } from '@/components/products/ProductFooter'
|
|
import { Text } from '@hanzo/ui'
|
|
import { mix } from '@hanzo/app/lib/mix'
|
|
import { phrase } from '@hanzo/i18n'
|
|
|
|
/**
|
|
* Registry, through the ONE product kit.
|
|
*
|
|
* registry and tunnel had byte-identical className sets: a hero, a six-card
|
|
* grid, a terminal and two calls to action. See LLM.md, "Tailwind is NOT gone".
|
|
*
|
|
* EVERY WORD IS THE ONE THAT WAS HERE, the coloured session included — the
|
|
* prompt, the command and its argument are three tones, which is how the
|
|
* sample reads, so `code.source` takes markup rather than a string.
|
|
*
|
|
* TWO THINGS MOVED. The session was in the hero and is now the kit's terminal
|
|
* section, where it gains the heading that used to sit above the paragraph
|
|
* below it. And the trailing "Get started with Registry" card is dropped, as on
|
|
* every other page here: its docs and GitHub links are both already reachable.
|
|
*/
|
|
|
|
/**
|
|
* The three tones the sample reads in. A prompt and a comment are quiet, the
|
|
* command is body ink, and its argument is white — so they are three values,
|
|
* named, rather than a colour repeated at seven spans.
|
|
*/
|
|
const DIM = mix('var(--foreground)', 60)
|
|
const CMD = 'var(--foreground)'
|
|
const ARG = 'var(--white)'
|
|
|
|
const SESSION = (
|
|
<>
|
|
<Text color={DIM}>$</Text> <Text color={CMD}>hanzo</Text> <Text color={ARG}>login oci.hanzo.ai</Text>
|
|
<br/>
|
|
<Text color={DIM}># IAM mints a short-lived token</Text>
|
|
<br/>
|
|
<Text color={DIM}>$</Text> <Text color={CMD}>docker push</Text> <Text color={ARG}>oci.hanzo.ai/acme/api:v1.2.3</Text>
|
|
</>
|
|
)
|
|
|
|
export default function RegistryPage() {
|
|
return (
|
|
<>
|
|
<ProductLanding
|
|
badge={phrase("Container Registry")}
|
|
title={"Hanzo Registry"}
|
|
lede={phrase("A private registry for your container images at oci.hanzo.ai. It serves the OCI distribution API, so docker, podman, buildkit, skopeo and crane already know how to talk to it — and the credential is a short-lived token minted by your Hanzo IAM login, not a password living in a dockerconfigjson secret.")}
|
|
ctas={[
|
|
{ label: phrase("View Source"), href: "https://github.com/hanzoai" },
|
|
]}
|
|
what={{
|
|
title: phrase("Built on Hanzo IAM"),
|
|
sub: phrase("The credential expires on its own, so there is nothing to rotate and nothing to leak"),
|
|
pillars: [
|
|
{
|
|
icon: KeyRound,
|
|
title: phrase("IAM Token Auth"),
|
|
body: phrase("An unauthenticated pull gets a 401 naming Hanzo IAM. Your client fetches a token there, the registry checks its signature against a certificate it holds, and the push goes through. No password is stored at either end."),
|
|
},
|
|
{
|
|
icon: UserCheck,
|
|
title: phrase("Org-Scoped Repos"),
|
|
body: phrase("A repository name begins with your org, and what a token may do with it is decided by IAM at the moment the token is minted. Adding a teammate is one grant in one place, not a secret copied into a second."),
|
|
},
|
|
{
|
|
icon: Shield,
|
|
title: phrase("Cosign + Attestation"),
|
|
body: phrase("cosign signatures and in-toto attestations are ordinary OCI artifacts, so they push and pull to the same repository as the image they describe. Verification happens where the image runs, against exactly what the registry stored."),
|
|
},
|
|
{
|
|
icon: Layers,
|
|
title: phrase("OCI Compliant"),
|
|
body: phrase("The registry HTTP API v2 at /v2/, and nothing bespoke on top of it. Every client, scanner and admission controller that reads an image already speaks it, which is the whole point of not inventing one."),
|
|
},
|
|
{
|
|
icon: Zap,
|
|
title: phrase("Tags come off cleanly"),
|
|
body: phrase("Deletes are enabled, so a tag you pushed by mistake goes away and the blobs behind it are reclaimed. A registry you can only add to is one that only grows."),
|
|
},
|
|
{
|
|
icon: Globe,
|
|
title: phrase("The same account as everything else"),
|
|
body: phrase("Whoever signs into Hanzo Cloud is who pushes an image. One directory of people, one place to revoke someone — and no separate registry account to remember when they leave."),
|
|
},
|
|
],
|
|
}}
|
|
code={{
|
|
head: { title: phrase("Delete the dockerconfigjson secret"), sub: phrase("Put a token IAM mints in its place, and let it expire on its own. There is nothing left to rotate.") },
|
|
name: "terminal",
|
|
source: <Session>{SESSION}</Session>,
|
|
ctas: [
|
|
{ label: phrase("Quickstart"), href: "https://docs.hanzo.ai/docs/openapi/registry/", icon: ArrowRight },
|
|
{ label: phrase("About IAM"), href: "/iam" }
|
|
],
|
|
}}
|
|
finalCta={{
|
|
title: phrase("Get started with Registry"),
|
|
buttons: [
|
|
{ label: phrase("View on GitHub"), href: "https://github.com/hanzoai" },
|
|
],
|
|
}}
|
|
/>
|
|
<ProductFooter slug={"registry"} name={"Registry"} />
|
|
</>
|
|
)
|
|
}
|