mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
Try Hanzo opens /signup directly instead of /chat bouncing a stranger there, which cost a whole page load on a phone (13 s throttled). /login no longer sends a new address to /signup: both pages send the link at once and make the account once the code proves the address, so the person stays on the page they chose. /login, /signup and /auth/callback preconnect to api.hanzo.ai from the head, so the methods read, the token exchange and the discovery a provider press needs start on a warm connection. A member at /login is marked before first paint (the app's BOOT under data-member), the form stays off screen while the page moves them on, and the panel asks IAM for no sign-in methods it would never draw. The callback starts the bind and the standing read together instead of one after the other.
637 lines
24 KiB
TypeScript
637 lines
24 KiB
TypeScript
/**
|
|
* Where the site goes: the hosts it links out to, and the one nav tree.
|
|
*
|
|
* The hosts come first, named once so no page hard-codes a URL. The tree comes
|
|
* last (`MENUS`, `LOGIN`, `TRY`, `GET_KEY`, `LEGAL`). The bar and the phone
|
|
* sheet draw `MENUS`. The footer draws `FOOT`. The wordmark opens Company, including About, on hover or a press. A page the sitemap offers
|
|
* is linked from the footer, because a menu's rows are not in the HTML until
|
|
* it opens.
|
|
*/
|
|
|
|
import type { GlyphName } from '@hanzogui/shell'
|
|
import { phrase } from '@hanzo/i18n'
|
|
import { LOGIN as SIGNIN, signUp } from '@hanzo/app/lib/destination'
|
|
import { dev, GET, WORKSPACE } from '@hanzo/app/lib/host'
|
|
import { NEXT, NOW } from '@/lib/zen'
|
|
import blog from '@/lib/data/blog.json' with { type: 'json' }
|
|
import menu from '@/lib/data/menu.json' with { type: 'json' }
|
|
|
|
const INDEX = menu.index
|
|
const kind = (id: string) => menu.solutions.find((k) => k.id === id)?.links ?? []
|
|
|
|
// The app IS this site: `/` signed in, and it signs in here, at /login and
|
|
// /signup, never on another host.
|
|
//
|
|
// APP is what hanzo.app is now: the page you get the Hanzo App from — the
|
|
// download, the CLI, or the app in the browser. A link that means "get the
|
|
// product" and a link that means "open it" are different promises, and one
|
|
// constant serving both is how a download button quietly becomes a second
|
|
// front door.
|
|
export const APP = GET
|
|
export const SH = 'https://hanzo.sh'
|
|
export const CLOUD = 'https://cloud.hanzo.ai'
|
|
export const CONSOLE = 'https://platform.hanzo.ai'
|
|
/**
|
|
* Where a reader gets the one key everything is billed against. The console
|
|
* signs a reader in or up on the way, and a key costs nothing to hold, so this
|
|
* is where every "free" call to action ends: /signup ends at /chat, whose
|
|
* workspace is the paid plan. `/api-keys` is the address the console's own
|
|
* bundle links to; platform.hanzo.ai answers 200 with identical HTML for any
|
|
* path, so read the console's resolver before changing it.
|
|
*/
|
|
export const KEYS = `${CONSOLE}/api-keys`
|
|
/** Where a reader sets up Claude Code, Codex, Cursor or Antigravity to run through Hanzo:
|
|
* install, sign in, `hanzo code <tool>`. The platform page, not a second copy of it here. */
|
|
export const CODING = `${CONSOLE}/accelerate`
|
|
/** Hanzo Dev, the builder: the door that signs a stranger in and opens the
|
|
* app in Dev. hanzo.build forwards here. */
|
|
export const BUILD = dev()
|
|
/** Where a new person starts: this site's sign-up, then the app at `/`. Try
|
|
* Hanzo and the fold's Get started are both this one door. */
|
|
export { signUp }
|
|
export const STATUS = 'https://status.hanzo.ai'
|
|
export const GITHUB = 'https://github.com/hanzoai'
|
|
export const DOCS = 'https://docs.hanzo.ai'
|
|
export const BLOG = 'https://blog.hanzo.ai'
|
|
export const AGENCY = 'https://hanzo.agency'
|
|
export const STUDIO = 'https://studio.hanzo.ai'
|
|
export const UNIVERSITY = 'https://hanzo.university'
|
|
|
|
/** A call with the team, booked: Hanzo AI's page at Cal.com, where a visitor
|
|
* picks the 15- or 30-minute call. */
|
|
export const BOOKING = 'https://cal.com/hanzo'
|
|
|
|
/** The 30-minute intro itself. An event page, unlike the profile, takes the
|
|
* `name`, `email` and `notes` the sales form fills in. */
|
|
export const INTRO = `${BOOKING}/30min`
|
|
|
|
/** The ONE way into the chat, and it is no longer a hand-off.
|
|
*
|
|
* It used to forward the prompt to hanzo.chat, because this site did not
|
|
* implement a chat. It does: /chat on this origin IS the product. So the text
|
|
* travels as `?q=` on a same-origin navigation and the reader never leaves.
|
|
*
|
|
* `hz_ref=site` is gone with the crossing it existed for: hanzo.ai and
|
|
* hanzo.chat were separate origins, so a logged-out visitor had a DIFFERENT
|
|
* anonymousId on each and no per-person funnel could span them — the param
|
|
* carried the source surface so the far side could stamp its own event. One
|
|
* origin has one identity and the funnel joins itself.
|
|
*
|
|
* `submit=true` is gone for a stronger reason: it asked the far side to SEND
|
|
* on arrival, and /chat deliberately refuses to. A link is not consent to
|
|
* spend somebody's credits, so the text is TYPED INTO the composer and a
|
|
* human presses send. Passing a flag that the destination is right to ignore
|
|
* is a promise this code should stop making. */
|
|
/** The chat's address, WITH ITS TRAILING SLASH, named once.
|
|
*
|
|
* /chat is a mounted single-page app, not a Next route, and its index declares
|
|
* `<base href="/chat/">`. So the slash is not cosmetic and it is not optional:
|
|
* fetched at `/chat` the shell still answers 200, the base resolves against
|
|
* `/chat` as a FILE, the router matches nothing, and the app renders an empty
|
|
* body — 1016 bytes against 24990, no console error, no failed request. A
|
|
* blank page that reports success is the worst shape a bug can take, and it
|
|
* was on this site's primary call to action.
|
|
*
|
|
* hanzo.chat redirects to `/chat/` and therefore always worked; every link on
|
|
* this site said `/chat` and therefore never did. That asymmetry is why nobody
|
|
* caught it: the door people tested was not the door people clicked.
|
|
*
|
|
* IT IS `/chat`, WITHOUT THE SLASH — the trailing form was the fix for that and
|
|
* it moved the failure rather than removing it. `next.config.mjs` sets
|
|
* `trailingSlash: false`, so the export writes `out/chat.html` and no
|
|
* `out/chat/index.html`: a static host answers `/chat` with the page and
|
|
* `/chat/` with a 404. Every submitted question went to the second one.
|
|
*
|
|
* Measured on both planes. The export: `/chat` 200, `/chat/` 404. Production:
|
|
* `/chat?q=hi` 301s to `/chat/?q=hi` — the query rides the redirect, so the
|
|
* slashless form reaches the same room there with the question intact. One
|
|
* spelling that works in the export, in dev, and in production.
|
|
*
|
|
* One constant because there were nine spellings of this address and the tenth
|
|
* would have been wrong too. */
|
|
export const CHAT = '/chat'
|
|
/** The door for an AI agent, said once: the Developers menu and the Platform footer column lead with it, onto the headless path. */
|
|
export const AGENTS: Link = { label: phrase('Agents sign up free'), href: '/agents#headless' }
|
|
|
|
export function goToChat(prompt = '') {
|
|
const q = prompt.trim()
|
|
window.location.href = q ? `${CHAT}?q=${encodeURIComponent(q)}` : CHAT
|
|
}
|
|
|
|
// ── The nav tree ─────────────────────────────────────────────────────────────
|
|
//
|
|
// Shaped after openai.com's sitemap, entry for entry where Hanzo has the page:
|
|
// Company, Research, Products, Solutions (their Business), Developers, Learn
|
|
// (their Support and More), and Terms & Policies at the foot. A label with no
|
|
// page on this site has no row; a row is a page that answers.
|
|
//
|
|
// Every label, title and hint is English marked with `phrase` (@hanzo/i18n), so
|
|
// the extractor finds it, and drawn through `t` in the reader's language. A name
|
|
// standing alone (Hanzo Dev, Enso 1, Koma, GitHub) is not marked and is drawn as
|
|
// written, and so are the blog's article titles, which are English articles.
|
|
|
|
/** A destination. `hint` is a short second line, used only where a row needs one. */
|
|
export interface Link {
|
|
label: string
|
|
href: string
|
|
hint?: string
|
|
}
|
|
|
|
/** A titled column. A `lead` column sets its links in display type, first. */
|
|
export interface Group {
|
|
title: string
|
|
links: Link[]
|
|
lead?: boolean
|
|
}
|
|
|
|
/**
|
|
* A top-level entry: its label and mark, the page it stands for, and the
|
|
* columns it opens. `glyph` names a mark from the shell's one set. An entry
|
|
* with no columns opens nothing: it is a link to its page.
|
|
*/
|
|
export interface Menu {
|
|
id: string
|
|
label: string
|
|
href: string
|
|
glyph: GlyphName
|
|
groups: Group[]
|
|
}
|
|
|
|
/** A link leaves the site when it names a host. It says so with ↗ and a new tab. */
|
|
export const away = (href: string): boolean => /^https?:\/\//.test(href)
|
|
|
|
/** The company, opened from the wordmark. */
|
|
export const COMPANY: Menu = {
|
|
id: 'company',
|
|
label: phrase('Company'),
|
|
href: '/about',
|
|
glyph: 'user',
|
|
groups: [
|
|
{
|
|
title: phrase('Explore Company'),
|
|
lead: true,
|
|
links: [
|
|
{ label: phrase('About Us'), href: '/about' },
|
|
{ label: phrase('Reviews'), href: '/reviews' },
|
|
{ label: phrase('Careers'), href: '/careers' },
|
|
{ label: phrase('News'), href: '/press' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Resources'),
|
|
links: [
|
|
{ label: phrase('Brand Guidelines'), href: '/brand' },
|
|
{ label: phrase('Philosophy'), href: '/philosophy' },
|
|
{ label: phrase('Investors'), href: '/investors' },
|
|
{ label: phrase('Contact'), href: '/contact' },
|
|
],
|
|
},
|
|
],
|
|
}
|
|
|
|
/** The complete site navigation. Company opens from the wordmark; Dev stays
|
|
* under Products rather than occupying a top-level door. */
|
|
export const MENUS: Menu[] = [
|
|
{
|
|
id: 'research',
|
|
label: phrase('Research'),
|
|
href: '/research',
|
|
glyph: 'pulse',
|
|
groups: [
|
|
{
|
|
title: phrase('Releases'),
|
|
lead: true,
|
|
links: [
|
|
{ label: 'Enso 1', href: '/enso' },
|
|
{ label: 'Kai 1', href: '/kai' },
|
|
{ label: NOW.name, href: '/zen' },
|
|
{ label: 'Kata 1', href: '/kata' },
|
|
{ label: 'Gen 1', href: '/gen' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Creative AI'),
|
|
links: [
|
|
{ label: 'Koma', href: '/koma' },
|
|
{ label: 'Iro', href: '/iro' },
|
|
{ label: 'Mori', href: '/mori' },
|
|
{ label: 'Oto', href: '/oto' },
|
|
{ label: 'Koe', href: '/koe' },
|
|
{ label: 'Uta', href: '/uta' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Explore Research'),
|
|
links: [
|
|
{ label: phrase('Overview'), href: '/research' },
|
|
{ label: phrase('Benchmarks'), href: '/benchmarks' },
|
|
{ label: phrase('Compare'), href: '/compare' },
|
|
{ label: phrase('Open source'), href: '/open-source' },
|
|
{ label: phrase('Specifications'), href: 'https://hips.hanzo.ai' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Safety'),
|
|
links: [
|
|
{ label: phrase('Security'), href: '/security' },
|
|
{ label: phrase('Trust & transparency'), href: '/trust' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'products',
|
|
label: phrase('Products'),
|
|
href: '/products',
|
|
glyph: 'blocks',
|
|
groups: [
|
|
{
|
|
title: phrase('AI Models'),
|
|
lead: true,
|
|
links: [
|
|
{ label: phrase('All models'), href: '/models' },
|
|
{ label: phrase('LLMs'), href: '/zen' },
|
|
{ label: phrase('Decisions'), href: '/kai' },
|
|
{ label: phrase('Routing'), href: '/enso' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Creative AI'),
|
|
links: [
|
|
{ label: phrase('Video'), href: '/koma' },
|
|
{ label: phrase('Images'), href: '/iro' },
|
|
{ label: phrase('3D'), href: '/mori' },
|
|
{ label: phrase('Sound effects'), href: '/oto' },
|
|
{ label: phrase('Voice'), href: '/koe' },
|
|
{ label: phrase('Music'), href: '/uta' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('API Platform'),
|
|
links: [
|
|
{ label: phrase('Overview'), href: '/platform' },
|
|
{ label: phrase('API'), href: '/api' },
|
|
{ label: phrase('Playground'), href: '/playground' },
|
|
{ label: phrase('Gateway'), href: '/gateway' },
|
|
{ label: phrase('Agents'), href: '/agents' },
|
|
{ label: 'Base', href: '/base' },
|
|
{ label: phrase('Machines'), href: '/machines' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Apps and tools'),
|
|
links: [
|
|
{ label: 'Hanzo App', href: APP },
|
|
{ label: 'Hanzo Bot', href: '/bot' },
|
|
{ label: 'Hanzo CLI', href: '/cli' },
|
|
{ label: 'Hanzo Dev', href: BUILD },
|
|
{ label: 'Hanzo Gen', href: '/gen' },
|
|
{ label: 'Hanzo Kata', href: '/kata' },
|
|
{ label: 'Hanzo Team', href: WORKSPACE },
|
|
{ label: 'MCP', href: '/mcp' },
|
|
{ label: phrase('Skills'), href: '/skills' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Install'),
|
|
links: [
|
|
{ label: phrase('CLI'), href: '/cli' },
|
|
{ label: phrase('Desktop app'), href: '/desktop' },
|
|
{ label: phrase('Browser extension'), href: '/extension' },
|
|
{ label: phrase('IDE'), href: '/ide' },
|
|
{ label: phrase('All downloads'), href: '/download' },
|
|
{ label: phrase('Release notes'), href: `${GITHUB}/cli/releases` },
|
|
],
|
|
},
|
|
// Hanzo OS: the product index and its layers (lib/layers.ts). Every
|
|
// product page is linked from its layer, so it is two clicks from here.
|
|
{
|
|
title: 'Hanzo OS',
|
|
links: [{ label: phrase('All products'), href: '/products' }, ...menu.layers],
|
|
},
|
|
{
|
|
title: phrase('More from Hanzo'),
|
|
links: [
|
|
{ label: phrase('Start from a template'), href: '/templates' },
|
|
{ label: phrase('Agents at work'), href: '/agents/crew' },
|
|
{ label: phrase('Cloud on your laptop'), href: '/cloud/local' },
|
|
{ label: phrase('Start a company'), href: '/start' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'solutions',
|
|
label: phrase('Solutions'),
|
|
href: INDEX,
|
|
glyph: 'puzzle',
|
|
groups: [
|
|
{
|
|
title: phrase('Explore Solutions'),
|
|
lead: true,
|
|
links: [
|
|
{ label: phrase('All solutions'), href: INDEX },
|
|
{ label: phrase('Enterprise'), href: '/enterprise' },
|
|
{ label: phrase('Agency'), href: AGENCY },
|
|
{ label: phrase('Customer stories'), href: '/customers' },
|
|
{ label: phrase('Contact sales'), href: '/contact-sales' },
|
|
],
|
|
},
|
|
// Teams, Industries, Use cases: every entry lib/data/solutions.ts holds, by kind.
|
|
...menu.solutions.filter((k) => k.id !== 'reserved').map((k) => ({ title: k.title, links: k.links })),
|
|
{
|
|
title: phrase('Programs'),
|
|
links: [
|
|
...kind('reserved'),
|
|
{ label: phrase('Startups'), href: '/startups' },
|
|
{ label: phrase('Partner network'), href: '/affiliate' },
|
|
{ label: phrase('Cost calculator'), href: '/calculator' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'developers',
|
|
label: phrase('Developers'),
|
|
href: DOCS,
|
|
glyph: 'code',
|
|
groups: [
|
|
{
|
|
title: phrase('Explore Developers'),
|
|
lead: true,
|
|
links: [
|
|
AGENTS,
|
|
{ label: phrase('Documentation'), href: DOCS },
|
|
{ label: phrase('API reference'), href: `${DOCS}/docs/openapi/` },
|
|
{ label: phrase('Quickstart'), href: `${DOCS}/docs/quickstart/` },
|
|
{ label: phrase('SDKs'), href: '/sdks' },
|
|
{ label: phrase('Open models'), href: 'https://huggingface.co/zenlm' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Resources'),
|
|
links: [
|
|
{ label: phrase('API keys'), href: KEYS },
|
|
{ label: 'Claude Code, Codex, Cursor', href: CODING, hint: phrase('Use Hanzo with your coding tools') },
|
|
{ label: phrase('Integrations'), href: '/integrations' },
|
|
{ label: phrase('Examples'), href: '/gallery' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Community'),
|
|
links: [
|
|
{ label: 'GitHub', href: GITHUB },
|
|
{ label: phrase('Status'), href: STATUS },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'learn',
|
|
label: phrase('Learn'),
|
|
href: '/learn',
|
|
glyph: 'book',
|
|
groups: [
|
|
{
|
|
title: phrase('Blog'),
|
|
links: [
|
|
...blog.posts.slice(0, 3).map((post) => ({
|
|
label: post.title,
|
|
href: post.link,
|
|
hint: post.category ? post.category.toUpperCase() : undefined,
|
|
})),
|
|
{ label: phrase('All articles'), href: '/blog' },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Research & Guides'),
|
|
links: [
|
|
{ label: phrase('Overview'), href: '/learn' },
|
|
{ label: phrase('Technical Blog'), href: BLOG },
|
|
{ label: phrase('Kai & Decision Models'), href: '/blog/kai-decision-models' },
|
|
{ label: phrase('Coding agents'), href: `${DOCS}/docs/coding` },
|
|
{ label: phrase('Guides'), href: `${DOCS}/docs/guides/` },
|
|
{ label: phrase('Cookbook'), href: `${DOCS}/docs/guides/cookbook/` },
|
|
],
|
|
},
|
|
{
|
|
title: phrase('Support'),
|
|
links: [
|
|
{ label: phrase('Documentation'), href: DOCS },
|
|
{ label: phrase('Help center'), href: '/support' },
|
|
],
|
|
},
|
|
// Last: the university, then each of its courses (app/(marketing)/university/courses-data.ts).
|
|
{
|
|
title: 'Hanzo University',
|
|
links: [
|
|
{ label: 'Hanzo University', href: UNIVERSITY, hint: phrase('Courses and certifications') },
|
|
{ label: phrase('Agentic coding'), href: '/university/agentic-coding' },
|
|
{ label: phrase('Reinforcement learning'), href: '/university/reinforcement-learning' },
|
|
{ label: phrase('Systems engineering'), href: '/university/systems-engineering' },
|
|
{ label: phrase('AI practitioner'), href: '/university/ai-practitioner' },
|
|
{ label: phrase('AI architect'), href: '/university/ai-architect' },
|
|
{ label: phrase('Agentic marketing'), href: '/university/agentic-marketing' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
// Last: Pricing is one page, so it is a link to it rather than a menu.
|
|
{ id: 'pricing', label: phrase('Pricing'), href: '/pricing', glyph: 'card', groups: [] },
|
|
]
|
|
|
|
/** Log in goes straight to this site's sign-in. */
|
|
export const LOGIN: Link = { label: phrase('Log in'), href: SIGNIN }
|
|
|
|
/**
|
|
* Log in's two doors (owner, 2026-10-30): the app (Chat, Dev and Studio, on this
|
|
* origin) and the API Platform (keys, usage and billing at platform.hanzo.ai,
|
|
* which sends a stranger back here to sign in with its own request).
|
|
*/
|
|
export const LOGINS: readonly (Link & { line: string })[] = [
|
|
{ label: phrase('Hanzo App'), line: phrase('Chat, Dev and Studio'), href: `${SIGNIN}?next=${encodeURIComponent(CHAT)}` },
|
|
{ label: phrase('API Platform'), line: phrase('API keys, usage and billing'), href: CONSOLE },
|
|
]
|
|
|
|
/** The filled control in the bar: the one key everything is billed against. */
|
|
export const GET_KEY: Link = { label: phrase('Get API Key'), href: KEYS }
|
|
|
|
/** Try Hanzo: the filled control in the bar, and the door a solution page offers.
|
|
* It is the sign-up, which goes on to the app at /chat (lib/auth/arrive) on
|
|
* whatever free access the account has, and nothing asks for a plan. Not /chat
|
|
* itself: there a stranger reads Chat's page and presses again to sign up, one
|
|
* page and one press the funnel loses. A signed-in reader is shown `OPEN`. */
|
|
export const TRY: Link = { label: phrase('Try Hanzo'), href: signUp() }
|
|
|
|
/** What the same control says to a reader who is signed in: the app, at /chat. `/` is the landing for them too. */
|
|
export const OPEN: Link = { label: phrase('Open Hanzo'), href: CHAT }
|
|
|
|
/** Terms & Policies. The documents live here so the export keeps them; the
|
|
* footer shows the short line below, and /legal indexes the rest. */
|
|
export const LEGAL: Link[] = [
|
|
{ label: phrase('Terms of use'), href: '/terms' },
|
|
{ label: phrase('Privacy policy'), href: '/privacy' },
|
|
{ label: phrase('Usage policy'), href: '/aup' },
|
|
{ label: phrase('Cookie policy'), href: '/cookies' },
|
|
{ label: phrase('Privacy choices'), href: '#choices' },
|
|
{ label: phrase('Other policies'), href: '/legal' },
|
|
]
|
|
|
|
/**
|
|
* The footer. The bar is six doors; a page the sitemap offers still needs a
|
|
* link in the HTML, and a menu's rows are not in the HTML until it opens.
|
|
* Solutions keeps four. The index stays on those pages, not in this chrome.
|
|
*/
|
|
export const FOOT: Menu[] = [
|
|
{
|
|
id: 'models-foot',
|
|
label: phrase('Models'),
|
|
href: '/models',
|
|
glyph: 'pulse',
|
|
groups: [
|
|
{
|
|
title: phrase('Models'),
|
|
lead: true,
|
|
links: [
|
|
{ label: phrase('All models'), href: '/models' },
|
|
{ label: 'Enso', href: '/enso' },
|
|
{ label: 'Kai', href: '/kai' },
|
|
{ label: NOW.name, href: '/zen' },
|
|
{ label: phrase('Benchmarks'), href: '/benchmarks' },
|
|
{ label: phrase('Creative AI'), href: '/studio' },
|
|
{ label: NEXT.name, href: NEXT.request },
|
|
{ label: 'Zen 6 Max', href: '/zen/zen6-max' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'platform-foot',
|
|
label: phrase('Platform'),
|
|
href: '/platform',
|
|
glyph: 'blocks',
|
|
groups: [
|
|
{
|
|
title: phrase('Platform'),
|
|
lead: true,
|
|
links: [
|
|
AGENTS,
|
|
{ label: phrase('Gateway'), href: '/gateway' },
|
|
{ label: 'MCP', href: '/mcp' },
|
|
{ label: 'Base', href: '/base' },
|
|
{ label: phrase('Search'), href: '/search' },
|
|
{ label: 'Studio', href: '/studio' },
|
|
{ label: phrase('Machines'), href: '/machines' },
|
|
{ label: phrase('Observability'), href: '/o11y' },
|
|
{ label: phrase('Insights'), href: '/insights' },
|
|
{ label: phrase('Commerce'), href: '/commerce' },
|
|
{ label: phrase('Datastore'), href: '/datastore' },
|
|
{ label: phrase('Memory'), href: '/products/memory' },
|
|
{ label: 'Realtime', href: '/realtime' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'developers-foot',
|
|
label: phrase('Developers'),
|
|
href: DOCS,
|
|
glyph: 'code',
|
|
groups: [
|
|
{
|
|
title: phrase('Developers'),
|
|
lead: true,
|
|
links: [
|
|
{ label: phrase('Dev'), href: BUILD },
|
|
{ label: phrase('Download'), href: '/download' },
|
|
{ label: phrase('Chat'), href: CHAT },
|
|
{ label: 'Hanzo App', href: APP },
|
|
{ label: 'Hanzo Bot', href: '/bot' },
|
|
{ label: 'Console', href: CONSOLE },
|
|
{ label: 'Gen', href: '/gen' },
|
|
{ label: 'Tabs', href: '/tabs' },
|
|
{ label: phrase('CLI'), href: '/cli' },
|
|
{ label: phrase('SDKs'), href: '/sdks' },
|
|
{ label: phrase('Documentation'), href: DOCS },
|
|
{ label: 'GitHub', href: GITHUB },
|
|
{ label: phrase('Status'), href: STATUS },
|
|
{ label: phrase('Open source'), href: '/open-source' },
|
|
{ label: 'Forge', href: 'https://forge.hanzo.ai' },
|
|
{ label: phrase('Security'), href: '/security' },
|
|
{ label: phrase('Compare'), href: '/compare' },
|
|
{ label: phrase('Startups'), href: '/startups' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'solutions-foot',
|
|
label: phrase('Solutions'),
|
|
href: '/solutions/engineering',
|
|
glyph: 'puzzle',
|
|
groups: [
|
|
{
|
|
title: phrase('Solutions'),
|
|
lead: true,
|
|
links: [
|
|
{ label: phrase('Engineering'), href: '/solutions/engineering' },
|
|
{ label: phrase('Agents'), href: '/solutions/agents' },
|
|
{ label: phrase('Research'), href: '/solutions/research' },
|
|
{ label: phrase('Data'), href: '/solutions/data' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'learn-foot',
|
|
label: phrase('Learn'),
|
|
href: '/learn',
|
|
glyph: 'book',
|
|
groups: [
|
|
{
|
|
title: phrase('Learn'),
|
|
lead: true,
|
|
links: [
|
|
{ label: phrase('Blog'), href: '/blog' },
|
|
{ label: phrase('Guides'), href: `${DOCS}/docs/guides/` },
|
|
{ label: phrase('Cookbook'), href: `${DOCS}/docs/guides/cookbook/` },
|
|
{ label: phrase('Help center'), href: '/support' },
|
|
{ label: phrase('Customer stories'), href: '/customers' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'company-foot',
|
|
label: phrase('Company'),
|
|
href: '/about',
|
|
glyph: 'user',
|
|
groups: [
|
|
{
|
|
title: phrase('Company'),
|
|
lead: true,
|
|
links: [
|
|
{ label: phrase('About'), href: '/about' },
|
|
// The beta is opt-in: the landing's banner and this row are its doors.
|
|
{ label: phrase('Join Beta'), href: '/beta' },
|
|
{ label: phrase('Careers'), href: '/careers' },
|
|
{ label: phrase('News'), href: '/press' },
|
|
{ label: phrase('Brand'), href: '/brand' },
|
|
{ label: phrase('Philosophy'), href: '/philosophy' },
|
|
{ label: phrase('Investors'), href: '/investors' },
|
|
{ label: phrase('Contact'), href: '/contact' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
|
|
/** The line under the columns. /legal holds the policies that are not named here. */
|
|
export const FOOT_LINE: Link[] = [
|
|
{ label: phrase('Terms'), href: '/terms' },
|
|
{ label: phrase('Privacy'), href: '/privacy' },
|
|
{ label: phrase('Usage policy'), href: '/aup' },
|
|
{ label: phrase('Privacy choices'), href: '#choices' },
|
|
]
|