The theme is codeTheme from @hanzo/ui/core: Dracula on dark, GitHub
Light on light, the one every Hanzo surface draws. lib/shiki.ts and each
app's source.config.ts import it rather than naming a theme, so vesper
and github-dark are gone. @hanzo/ui moves to 8.27.83, the first release
that carries it.
A block's code area paints the theme's own ground and ink from the pre
shiki wrote, #282a36 in the dark, rather than the site's panel.
The docs home drew its hero and its eight domain snippets as plain text,
and so did the models page's fallback request. The hero highlights its
three doors in a server part (components/hero.tsx); the snippets and the
fallback are Example props in the MDX. No highlighter reaches the
browser.
A version written into a manifest is written into every manifest that wants it,
which is how eslint came to exist in a hundred and four forms across this estate
and how a package came to resolve twice at run time. The catalog moves the number
out of the manifest: a manifest names the package, the workspace names the
version.
Four are held below their latest because the newer release cannot be used, and
the reason is recorded rather than the version alone: @noble/hashes 2 renamed
every subpath the web3 stack imports, @splinetool/runtime 2 depends on a package
that was never published, @dynamic-labs 5.4.1 the same, and react-resizable-panels
3 points its types condition at the bundle.
Co-authored-by: Hanzo Dev <[email protected]>
Every dependency on a @hanzo/@luxfi/@zooai package now names the same version
across the repo: a catalog entry where pnpm supports one, an exact pin where it
does not, and a range only where a peer genuinely means one.
pnpm itself is pinned too — the estate ran eighteen different versions, five of
them too old to read a catalog.
Co-authored-by: Hanzo Dev <[email protected]>
One app carried the Hanzo shell and twenty did not, so a reader crossing from
base.hanzo.ai to zen.hanzo.ai left the ecosystem and landed somewhere that only
resembled it. Five of those twenty had hand-rolled a footer of their own —
sixteen lines of copyright and a repo link, written five separate times.
Each app now loads the brand tokens before its own sheet, reports through
docs-analytics under its own product name, and renders HanzoFooter from
@hanzogui/shell — the same 6-column ecosystem footer, defined once, that
apps/docs already used.
A footer written inside a layout was chrome pretending to be content, and it is
gone. A footer written inside a page is content pretending to be chrome: those
keep their words and become sections, so each page has one contentinfo landmark
instead of two.
Three manifests listed @hanzo/font twice in the same object.
Builds verified across the four shapes this repo has: a static export, a
next.config.mjs app, a single-page app with no route groups, and one that
already reported analytics. Every one renders exactly one footer.
Co-authored-by: Hanzo Dev <[email protected]>
Thirty-one manifests asked for @hanzo/font ^1.9.1 while the lockfile still
resolved 1.8.0, 1.8.2 and 1.8.12, so pnpm install --frozen-lockfile — which is
every workflow under .hanzo — refused to install anything at all.
The floor is 1.9.2 rather than 1.9.1 because 1.9.1's zen.css carries the
@font-face rules and nothing else: the :root block binding --font-zen-sans and
--font-zen-mono is absent, and a sheet reading either property gets an invalid
value and the OS default without saying so. 1.9.2 publishes them again.
Twelve example layouts imported `ZenSans` from `@hanzo/font/sans`, a name
the package stopped exporting at 1.9.0 — the family is called Zen, so the
binding is `Zen`. Every one of those layouts would fail to resolve the
import against a current install, and the `^1.8.x` ranges they pinned kept
resolving to the old export instead of surfacing it.
The data products are Hanzo SQL, Hanzo SQLite, Hanzo DocDB and Hanzo
Datastore. Customer-facing prose named the upstream engine instead, which
reads as a resale rather than a product — and reads that way beside pages
that already say Datastore for the columnar store.
Fifteen lines of prose across base, insights, tasks and platform, plus the
three repo descriptions the project pages are generated from, so the next
sync of orm and sql-vector is a no-op rather than a revert.
Measured over the hand-authored surface: 77 lines matched `postgres`, now
63. Every one of the 63 is a literal that breaks if renamed, and each was
read before it was left — connection-string schemes, POSTGRES_* names, mount
paths, Temporal's postgres12 driver value, image references, a compose
service name and the k8s Service DNS that must agree with it, the
postgresConnectionRef CRD field, the mcp-server-postgres package, the
pg_isready role, and an integration catalog of third-party software.
The rendered export shows both halves: platform prints `sql-prod-data` and
still prints `postgres://`, `postgres:17-alpine` and `pg_isready -U postgres`
byte for byte.
openapi-specs/public.yaml holds five more and is not editable here. It is a
sha256-pinned snapshot of cloud's contract, and that prose has one home — the
handler doc comment that also becomes the SDK docstring, the MCP tool
description and the CLI help.
Datastore, SQL, KV and DocumentDB — the four Kinds HIP-0401 through HIP-0404
define. 112 files.
Left as written: DSN schemes, the env an image reads, package and extension
names, version requirements a reader must match, the wire protocols DocumentDB
and KV implement, and the fork provenance and licence on the pages that are
about the fork.
Box art keeps its width.
Reverses my own deletion of api/{vms,containers,clusters}.mdx. I deleted them
because platform's dokploy root.ts registers no cluster/vm/container router and
the dotted tRPC form 404s. Both facts are true and the conclusion was still
wrong: those capabilities DO exist, in cloud's visor and platform apps, under
different names. Rewriting beats deleting when the surface is real.
Mapped to source, each probed 403 against a 404 bogus control:
vm.all -> GET /v1/machines visor.go:143
vm.one -> GET /v1/machines/{id} visor.go:149
vm.launch -> POST /v1/machines {name,size,region,dryRun} visor.go:148
vm.destroy -> DELETE /v1/machines/{id} visor.go:151
cluster.all -> GET /v1/clusters visor.go:184
cluster.one -> GET /v1/k8s/clusters/{id} visor.go:208
cluster.create -> POST /v1/k8s/clusters | POST /v1/clusters (BYO)
addNode/removeNode -> pool ops: POST /v1/clusters/{id}/pools[/{pool}/scale]
container.* -> /v1/platform/projects/{project}/apps... platform.go:230
Operations with no route are DELETED, not invented: vm start/stop/restart,
vm volumes, web terminal, cluster update/rename, per-cluster access grants.
The pages now say so instead of documenting them.
Two /api/ remain and both are correct: captable.mdx:159 describes the
SELF-HOSTED Next.js route handlers (and states the hosted service serves
neither), and platform api/index.mdx links doc-site routes (/docs/api/...),
which are directory names, not endpoints.
Nav restored for the three pages. Dangling meta.json entries: 15, vs 22 on
origin/main -- still a net improvement, none introduced.
Co-authored-by: Hanzo Dev <[email protected]>
Every production URL on this page was https://tasks.hanzo.ai/api/v1/... and
every one of them 404s. The gateway mounts Tasks at /v1/tasks/ — there is no
/api/ prefix in front of it. Copy-pasting any curl here got you nothing.
Rewrote the 10 fully-qualified tasks.hanzo.ai URLs to /v1/tasks/. Each one
probed: /api/v1/* -> 404, /v1/tasks/* -> 403, which is the auth wall, i.e.
the endpoint is there and wants a token.
http://localhost:8233/api/v1 is left alone — different host, and the local
server's own routes are not something this change verified.
Co-authored-by: Hanzo Dev <[email protected]>
`@hanzo/docs-mdx` writes the collection modules to its outDir, `.docs/`.
Nothing read them there. Apps read a committed `docs/` copy instead, reached
three different ways:
13 apps `@hanzo/mdx:collections/server` + a webpack alias -> ./docs/*.ts
3 apps `@/docs/server`, straight into the committed copy
2 apps the alias, with no committed copy at all
The two with no copy — bootnode-docs and tasks-docs — could not build:
./lib/source.tsx
Module not found: Can't resolve '@hanzo/mdx:collections/server'
and four more built from a copy that no longer matched the content beside it:
./docs/server.ts
Module not found: Can't resolve
'../content/docs/reference/templates/USER.mdx?collection=docs&only=frontmatter'
That is what committing generated code buys: the build reads a snapshot of
the content rather than the content.
One name, one location, every app: `@hanzo/mdx:collections/*`, resolved to
`.docs/` — the generator's own output, rewritten on every build, gitignored.
`tsconfig` gains the matching `paths` entry so the specifier type-checks
instead of relying on `ignoreBuildErrors`; apps/docs stops overriding outDir
in both `next.config.mts` and `gen:collections`; turbo caches `.docs/**`. The
16 committed mirrors are deleted. Examples already did it this way.
`.source` goes with them — this fork's outDir has been `.docs` for a while,
leaving `.source` in the vite plugin's JSDoc, an example's import map, an
oxlint ignore and `.gitignore` pointing at a directory nothing writes.
Also declares in `globalEnv` the env vars the build scripts actually read
(HANZO_DOCS_SYNC, HIPS_REPO_DIR, DOCS_SECTION, the search vars...). Turbo
does not forward undeclared vars, so `HANZO_DOCS_SYNC=0 turbo run build` had
no effect on the sync it names.
turbo run build --filter='./apps/*' --continue
before Tasks: 33 successful, 40 total
Failed: bootnode-docs, docs, engine-docs, ml-docs, router-docs,
spec, tasks-docs
after Tasks: 38 successful, 40 total
Failed: docs, spec (both for unrelated reasons, fixed next)
(cherry picked from commit 3d11394b092530489b60931e46b4938a88a2bdd5)
Co-authored-by: Hanzo Dev <[email protected]>
apps/docs imported the same component library under three names — 11 files
from `@hanzo/docs/ui/*` (a pure re-export shell), 10 from `@hanzo/docs-ui`
(the Radix fork), plus 5 hand-copied shadcn files under components/ui.
All of it now resolves to `@hanzo/docs-base-ui`.
The 5 local copies are deleted. badge, hover-card, select and the container
card move into base-ui on `@base-ui/react` — preview-card is the hover-card
analog and Select.Value already takes `placeholder`, so the swap is 1:1 and
introduces no Radix. buttonVariants gains `xs`/`md`/`lg` and `link`, purely
additive, so no existing caller changes. Three Radix packages leave
apps/docs; `presence` and `tooltip` stay because non-shadcn code uses them.
global.css now takes base-ui's preset rather than the Radix fork's. The two
are not duplicates: `neutral.css` defines the colours, `preset.css` carries
base styles plus the `@source inline` safelists. Only `default-colors.css`
declares a `--color-fd-*` value, and it is byte-identical across both forks,
so no colour moves.
`types:check` never ran. pnpm installs the mdx bin scope-stripped as
`docs-mdx`, so `@hanzo/docs-mdx &&` died at `sh: no such file` and took
`tsc` with it — silently, in every app, for `lint` too. Fixed in all 32
scripts. apps/docs reports 107 first-party errors; that is the real number,
unchanged by this commit.
Also unbreaks two undefined references in openapi's server entry that a
large upstream merge left behind: PlaygroundAuthProvider was used but never
imported, and pickSchema/encodeInternalRef were orphaned utilities. Both
crashed the docs export. More remain in that package (renderResponse is a
missing function, not an import) — noted, not guessed at.
Co-authored-by: Hanzo Dev <[email protected]>
Three things the workspace disagreed with itself about.
Versions. apps/docs ran ahead on next 16.2.6 / react 19.2.6 / TS 6, the other
21 apps trailed on next 16.1.6 / react 19.2.3 / TS 5.9.3, and the packages sat
somewhere between with five different @types/react pins. Everything is now on
the newest patch of the line it was already on — react 19.2.8, next 16.2.12,
@types/react 19.2.18, @types/react-dom 19.2.4 — and the TS-5 stragglers join
the TS 6.0.3 the root and every package already used. No majors were invented:
6.0.3 IS the top of the 6.x line, and TS 7 is blocked because [email protected]
declares `typescript: ^5.5.0 || ^6.0.0`.
The duplicate key. next.config.mts declared `transpilePackages` twice in one
object literal, so the later list won and @hanzogui/shell and @hanzo/brand had
never been transpiled — the comment explaining why they must be outlived the
setting it described. tsc had been reporting this the whole time as
next.config.mts(193,3) TS1117; the app's `types:check` never reaches tsc (its
script starts with a bare `@hanzo/docs-mdx`, which is not the bin's name and
fails immediately), so nobody saw it. One list now, both groups in it.
Dead weight. Twelve packages apps/docs declared and no file, config, script or
browserslist field referenced: @radix-ui/react-dialog, @floating-ui/react-dom,
@mixedbread/sdk, @orama/orama, openapi-sampler, react-remove-scroll,
algoliasearch, gray-matter, tinyexec, tinyglobby, @types/three (types for a
package that isn't installed) and shadcn (no components.json exists anywhere in
the repo, so the CLI was never initialized). The ones that are real
dependencies of packages/openapi, packages/core and packages/cli keep their own
copies — pnpm's node_modules is isolated, so nothing lost a resolution.
@orama/core stays: apps/docs/app/static.json/route.ts pulls OramaDocument
through @hanzo/docs-core/search/orama-cloud, which types against it.
Verified against a clean worktree at HEAD, since the working tree carries
gigabytes of untracked synced project docs that CI never checks out:
turbo build, apps + packages 43/52 before, 43/52 after, same 9 failures
docs export 1764 html pages, byte-identical page count
deploy.yml gate index/docs/services present, /docs has nav
tsc --noEmit in apps/docs 325 errors before, 324 after (the TS1117)
vitest 169 passed / 13 failed, both sides
The 9 build failures and 13 test failures are unchanged from HEAD and none are
version-related: 7 sibling apps cannot resolve @hanzo/mdx:collections/server
under `next build --webpack`, zen-docs has a committed docs/server.ts importing
a deleted zen5-coder-flash.mdx, and packages/preview cannot resolve its own
@/lib/source alias under waku/vite.
Co-authored-by: Hanzo Dev <[email protected]>
Two independent defects made every documented 'first API call' fail:
1. FICTIONAL MODEL IDS. `zen-omni` and `zen-coder` appear ZERO times in the
live catalog (api.hanzo.ai/v1/models, 440 models). Every SDK sample -
python, typescript, go, cpp, swift, kotlin - told the customer to call a
model that does not exist, so even a correct request 400s. Corrected to the
real ids: zen5 and zen5-coder.
2. DEAD HOST + STALE PINNED MODEL. llm.hanzo.ai is retired and 301s (a POST
returns the literal string 'Permanent Redirect', not a completion), and
`claude-sonnet-4-5-20250929` is long superseded. Both removed: the host is
gone from customer-facing docs entirely rather than documented as retired,
and pinned upstream ids give way to our own current zen5.
50 files. Verified against the live catalog, not assumed.
- spec: remove dead 'Components' nav item (/docs/components) — spec renders
only synced HIPs (index + hip-*.mdx via scripts/sync-hips.ts), it has no
components section, so the route 404s. Drop now-unused ComponentIcon import.
- tasks-docs: point home 'REST API' link at /docs/sdk/api (the real REST API
reference) instead of the non-existent /docs/api.
Follow-up to 903b1c38: the package-name normalization covered JS/TS imports +
package.json but missed four other surfaces that name the same phantom packages,
relocating the breakage from 'pnpm install' to 'next/vite/astro build':
- H1: 46 CSS @import strings (@hanzo/docs-{base-ui,ui,openapi}/css/*) → real pkgs
(preserved legit @hanzo/docs-{twoslash,story} CSS)
- H2: examples/astro .astro imports (base-ui/mdx→fumadocs-ui/mdx, docs-core/toc→fumadocs-core/toc)
- L1: .changeset/config.json fixed-array lockstep names
- L2: removed apps/docs/next.config.mts dead phantom→phantom self-alias + dup keys
Found by adversarial red review of 903b1c38.
The fumadocs-fork rebrand left ~13 apps + examples referencing packages under
names that don't exist in the workspace (in BOTH directions: some kept
fumadocs-*, some became @hanzo/docs-*). pnpm install failed outright. Mapped
every reference (deps + imports, 607 source + 61 package.json) to the package
that actually exists, by suffix:
@hanzo/docs-{core,mdx,ui,base-ui} → fumadocs-{core,mdx,ui} / @fumadocs/base-ui
@fumadocs/{story,cli,mdx-remote,tailwind} → @hanzo/docs-{story,cli,...}
fumadocs-{docgen,epub,twoslash,typescript} → @hanzo/docs-{...}
drop phantom eslint-config-custom
Guarded @hanzo/docs-mdx vs -mdx-remote. Also fixes a pre-existing cli bug
(createConfigSchema referenced undefined isSrc) that blocked the package build.
Verified: pnpm install resolves clean (46.8s, was broken); package dist
regenerates phantom-free from the corrected source (hanzo-docs 430→0). Full
app build-green is blocked only by a node v26 toolchain bug in fumadocs-mdx's
config loader (repo targets node >=24.14; CI node builds it).