A heading is not a row, and the tree now says so without being read

Both were sentence-case text at one size, each carrying an icon, so the only
thing separating a section from a link was indentation you had to measure. The
headings are the half that changes: uppercase, tracked, smaller, muted, and no
icon — the label register every docs tree uses for a thing you cannot click.
Rows keep their icons, and the four that lacked one now have one, so "has an
icon" means "is a row" with no exceptions to remember.

Three names said the same word three times. `Integrate` held `Integrations`,
while `Integrations & Extensions` sat under Surfaces — all three wearing the
Puzzle glyph. They are not one thing: `apps` is where Hanzo INSTALLS (browser,
editor, desktop, design, business), so it is Extensions; `integrations` is what
POINTS AT Hanzo (agno, crewai, dspy, autogen), so it is Frameworks. The section
keeps its verb and takes the Plug, and each row now names what it is rather than
what its neighbour is.

`Programs > Startup Program` was the same defect one section down; the page is
Startups. Enso is a proper noun and is capitalised, and its mark is a circle,
which is what an ensō is — a sparkle said "AI" about the one thing here that
does not need telling.

The landing rail starts OPEN, like every other route. It started collapsed on
the argument that a reader who typed the domain has not asked for a table of
contents — but the front door is exactly where somebody does not know what is
here, and a collapsed rail answers that by showing nothing. It also cost the
page its wordmark, since the sidebar is what renders it.

And search is offered once. The sidebar carries the field, the collapsed rail
carries a button beside its own toggle; the third one on the far right was the
same action in a third shape.
This commit is contained in:
2026-08-22 12:12:19 -07:00
parent f3028ff29a
commit 575d3d06e0
13 changed files with 47 additions and 27 deletions
+8 -5
View File
@@ -25,12 +25,15 @@ export default function Layout({ children }: LayoutProps<'/'>) {
is a plain class selector, so nesting it redefines the tokens for
everything below — chrome included, which is why it sits here and not
on the page's own <main>. */}
{/* The rail starts collapsed HERE only. The tree is still one click away
via the sidebar trigger, but the front door leads with the page, not
with 12 rows of nav — a reader who typed the domain has not yet asked
for the table of contents. /docs/** keeps it open, where they have. */}
{/* THE TREE IS THE POINT, so it starts open here as it does everywhere
else. It started collapsed on the argument that a reader who typed the
domain has not asked for a table of contents — but the front door is
exactly where somebody does not yet know what is here, and a collapsed
rail answers that by showing nothing. It also cost the page its
wordmark: the sidebar renders it, so collapsing the sidebar rendered no
brand at all. One state, every route. */}
<div className="dark bg-fd-background text-fd-foreground">
<Docs themeSwitch={{ enabled: false }} sidebar={{ defaultCollapsed: true }}>
<Docs themeSwitch={{ enabled: false }} sidebar={{ defaultCollapsed: false }}>
{children}
</Docs>
</div>
+5 -1
View File
@@ -90,7 +90,11 @@ export function DocsNavbar(props: ComponentProps<'header'>) {
correctly and rendered by nobody. Named explicitly so the omission
cannot happen silently again. */}
<div className="flex items-center gap-2">
{slots.searchTrigger && <slots.searchTrigger.sm hideIfDisabled className="p-2" />}
{/* NO SEARCH HERE. The sidebar carries the search field itself, and the
collapsed rail carries a search button beside its own toggle — so a
third one on the far right was the same action offered twice on one
screen, and the two were not even the same shape. Search lives where
the tree lives. */}
{/* ONE ecosystem affordance, the same on every page. The home layout used to
render BOTH this and <MeetHanzo>, which said the same thing twice and put an
unlabeled grid icon next to a labelled menu; the inner pages then showed only
+2 -2
View File
@@ -1,6 +1,6 @@
{
"title": "Integrations & Extensions",
"description": "Install and connect Hanzo everywhere you work — one API key, one identity.",
"title": "Extensions",
"description": "Install and connect Hanzo everywhere you work \u2014 one API key, one identity.",
"icon": "Puzzle",
"defaultOpen": false,
"pages": [
+1
View File
@@ -1,4 +1,5 @@
---
icon: LayoutDashboard
title: Console
description: The unified cloud console for Hanzo Cloud -- manage every product, key, and organization from one app at console.hanzo.ai.
---
+2 -2
View File
@@ -1,6 +1,6 @@
---
icon: Sparkles
title: Meet enso
icon: Circle
title: Meet Enso
description: Hanzo's own model family — enso, enso-flash, and enso-ultra. What each one is for, and how to pick.
---
+1
View File
@@ -1,4 +1,5 @@
---
icon: TriangleAlert
title: Error codes
description: Every error code Hanzo Index can return, with its HTTP status and type. The `link` in an error body points here.
---
@@ -1,7 +1,7 @@
{
"title": "Integrations",
"description": "Point any agent framework at Hanzo — the exact parameter, for sixteen frameworks.",
"icon": "Puzzle",
"title": "Frameworks",
"description": "Point any agent framework at Hanzo \u2014 the exact parameter, for sixteen frameworks.",
"icon": "Component",
"pages": [
"agno",
"autogen",
+9 -9
View File
@@ -1,6 +1,6 @@
{
"pages": [
"---[Rocket]Get started---",
"---Get started---",
"index",
"quickstart",
"api-keys",
@@ -8,40 +8,40 @@
"environments",
"events",
"webhooks",
"---[Blocks]Concepts---",
"---Concepts---",
"concepts",
"architecture",
"network",
"---[Boxes]Capabilities---",
"---Capabilities---",
"openapi",
"---[BookOpen]Reference---",
"---Reference---",
"cli",
"sdks",
"mcp-tools",
"pricing",
"errors",
"---[SquareTerminal]Build with---",
"---Build with---",
"start",
"mcp",
"zap",
"dev",
"---[AppWindow]Surfaces---",
"---Surfaces---",
"console",
"mission-control",
"studio",
"chat",
"apps",
"usage",
"---[Users]Programs---",
"---Programs---",
"startups",
"enso",
"games",
"run-your-org",
"proof-of-ai",
"---[Puzzle]Integrate---",
"---Integrate---",
"integrations",
"migrate",
"---[GitFork]Open source---",
"---Open source---",
"projects",
"contributing"
]
+1 -1
View File
@@ -1,5 +1,5 @@
---
icon: Radio
icon: Activity
title: Mission Control
description: One board for every agent session your org is running — the live event stream, the subagent tree, and the four controls: pause, resume, stop, message.
---
+3 -2
View File
@@ -4,5 +4,6 @@
"pages": [
"index",
"hanzoai"
]
}
],
"icon": "FolderGit2"
}
+2 -1
View File
@@ -1,5 +1,6 @@
---
title: Run Your Org
icon: Building2
title: Run your org
description: From signup to a running brain, team, and bot for your organization — under ten minutes.
---
+2 -1
View File
@@ -1,5 +1,6 @@
---
title: Startup Program
icon: Rocket
title: Startups
description: Up to $150,000 in Hanzo Cloud credits for venture-backed startups -- plus $5 free for everyone and bring-your-own-compute.
---
@@ -319,6 +319,14 @@ function SidebarSeparator({ className, style, children, ...props }: ComponentPro
// mt-3, not mt-6: 24px above a 20px label is more air than the label is
// tall, and a tree pays it once per group.
'inline-flex items-center gap-2 mb-1 px-2 mt-3 empty:mb-0 [&_svg]:size-4 [&_svg]:shrink-0',
// A HEADING IS NOT A ROW, and the tree has to say which without being
// read. Both used to be sentence-case text at the same size, separated
// only by an icon each carried — so a row with an icon and a heading with
// one were the same shape, and the reader counted indentation to tell
// them apart. Uppercase, tracked, smaller and muted is the label register
// every docs tree uses for exactly this, and it costs the heading nothing:
// it was never something you click.
'text-[0.6875rem] font-medium uppercase tracking-[0.08em] text-fd-muted-foreground',
depth === 0 && 'first:mt-0',
className,
)}