Files
zeekayandGitHub 949608fd9d i18n: pages and components c–l draw their copy through @hanzo/i18n (#67)
Calculator, captable, careers, cloud, compare, contact and contact-sales,
customers, dashboards, dataroom, datastore, dev, download, enso,
enterprise, extension, family, integrations, investors, kai, learn,
legal and their components say their words through t() in client code,
<T> in server components and phrase() where copy is held as data; one
sentence is one key, figures and links its arguments.

Rebased on main: in every conflict main's file stands (its copy, layout
and styling) and only the wrapping is added back, including copy main
added since.

Claude-Session: https://claude.ai/code/session_015XYKLjZtDTJEnMo4eK3AFH
2026-10-30 01:15:31 -07:00

106 lines
5.0 KiB
TypeScript

'use client'
import type { ReactNode } from 'react'
import { ArrowRight, Activity, BarChart3, Clock, DollarSign, Eye, GitBranch, Shield } from 'lucide-react'
import { OSSRevenueBanner } from '@/components/oss/OSSRevenueBanner'
import { useI18n } from '@hanzo/i18n/react'
import { ProductLanding } from '@/components/product/ProductLanding'
import { ProductFooter } from '@/components/products/ProductFooter'
/**
* Console, through the ONE product kit.
*
* One of NINE pages — console, insights, kms, kv, mq, pubsub, sql, storage,
* stream — that shared a class set 100%: the same hero, stat row, six-card
* grid, terminal and call to action, written out nine times in ~310 utility
* classes each. They now pass one typed props object to `ProductLanding` and
* carry zero layout classes. See LLM.md, "Tailwind is NOT gone", for the rule.
*
* EVERY WORD IS THE ONE THAT WAS HERE, the four stat tiles included: 28 of the
* group's 36 carry a port, a version, a licence or a coding the prose does not
* (measured), so unlike /ledger's four they are not restatements and they stay.
*
* One fix the move makes by construction: ProductFooter sat INSIDE the final
* card's `max-w-4xl` wrapper on all nine, so the OSS attribution and deploy
* block rendered narrower here than on every other product page.
*/
export default function ConsolePage({ source }: { source: ReactNode }) {
const { t } = useI18n()
return (
<>
<ProductLanding
badge={"platform.hanzo.ai"}
badgeIcon={Activity}
title={"Hanzo Console"}
tagline={t("One admin for everything you run")}
lede={t("Every product on Hanzo Cloud has a module here — providers and models, keys, applications, stores, agents, clusters, domains, billing. Sign in once and the sidebar is whatever your organization actually uses.")}
ctas={[
{ label: t("Open Console"), href: "https://platform.hanzo.ai", icon: ArrowRight },
{ label: t("Documentation"), href: "https://docs.hanzo.ai/docs/console" },
]}
what={{
title: t("A module per product, one shell around them"),
sub: t("Add what you use. Hide what you don't. The shell stays the same."),
pillars: [
{
icon: Eye,
title: t("Providers and models"),
body: t("Every model your organization can call, and which provider serves it. Connect an account of your own and its models appear beside the ones we run."),
},
{
icon: DollarSign,
title: t("Usage and balance"),
body: t("A usage record per call and one balance per organization, so spend is attributed where it happened instead of totalled at the end of the month."),
},
{
icon: Clock,
title: t("Keys"),
body: t("Issue an API key, scope it, revoke it. The key you paste into a client is minted here, and revoking it here is what stops it working."),
},
{
icon: BarChart3,
title: t("Applications and stores"),
body: t("Register an app, hand it an identity, give it a store. The console writes the same resources the CLI does, because both are clients of the same API."),
},
{
icon: GitBranch,
title: t("Find it by typing it"),
body: t("A command palette reaches every module and every record without learning where anything lives. The sidebar is yours to reorder and prune."),
},
{
icon: Shield,
title: t("Scoped to the org on your token"),
body: t("Sign-in is OIDC against Hanzo IAM. What you see is what your organization owns, and switching organization switches the whole page — there is no global view to fall into by accident."),
},
],
}}
stats={{
items: [
{ value: "/v1", label: t("One API behind it") },
{ value: "OIDC", label: t("Sign in with Hanzo IAM") },
{ value: t("Per-org"), label: t("Data scoped to your org") },
{ value: "OSS", label: t("MIT or Apache-2.0") },
],
}}
code={{
head: { title: t("The console is a client. So is your code."), sub: t("Everything on these screens is a call to api.hanzo.ai/v1, and the typed clients are generated from the same document.") },
name: "app.py",
source,
}}
finalCta={{
title: t("Open the console"),
sub: t("Sign in with your Hanzo identity. The organization you land in is the one that gets billed, and everything on these screens belongs to it."),
buttons: [
{ label: t("Open Console"), href: "https://platform.hanzo.ai", icon: ArrowRight },
{ label: t("View on GitHub"), href: "https://github.com/hanzoai" },
],
}}
>
<OSSRevenueBanner />
</ProductLanding>
<ProductFooter slug={"console"} name={"Console"} />
</>
)
}