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.
cloud computes the catalog in Go and serves it at /v1/pricing, so the
docs apps and the zen-models package read the endpoint directly rather
than a host that forwards to it. The Base page links to the pricing page
a reader can actually open.
Co-authored-by: Hanzo Dev <[email protected]>
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.
Thirteen shipped apps and every scaffold in packages/create-app pulled their
face from Google at request time — Inter through next/font/google in the
examples and the four Next templates, Geist and Geist_Mono in the apps, and in
the seven react-router roots a bare <link> to fonts.googleapis.com. That last
one never even applied what it fetched: nothing in those trees set a family, so
the browser downloaded Inter, spent two preconnects on it, and rendered
system-ui. So `create-app` handed a customer a new docs site whose first act was
a third-party font request for a face that is not ours.
The apps read the family back through --font-sans and --font-mono, which are
next/font's handles rather than names of anything, so those follow the binding
over to --font-zen-sans and --font-zen-mono. Eight of them had only ever bound
the mono and were leaning on Tailwind's default for the text face; they now name
both, or swapping the binding would have dropped the body copy to system-ui
without a word.
Zen and ZenMono are built faces, not constructors — subsetting, display: swap
and fallback metrics are already in them — so the call and its options go away.
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.
Both sides moved on the same files for the same reason, one release apart.
origin carried the fix for cloud dropping `_v1_` from its operationIds and for
the MCP door re-projecting to one tool per subsystem; this branch carries the
next step of both -- the internal exception named by ROUTE rather than by an id
(ids move, routes are the thing that exists), and an `openapi-surfaces` that
already reads the subsystem shape through `door()` and `toolOperations()`. Taking
this side's scripts keeps both fixes: theirs are the earlier form of what is here.
Resolved by rule, not file by file:
* everything outside apps/docs -- the deploy lanes, base-docs, insights-docs --
is origin's. Not this branch's subject.
* apps/docs/scripts, lib, app, .gitignore and openapi-specs are this branch's.
The pin is the newer one: cloud a327537c, 1,305 paths, 1,809 operations, 71
GA capabilities.
* the 116 pages origin modified and this branch deleted stay deleted. Editing a
page and removing it are not a disagreement about the text -- services/,
commerce/ and skills/ describe capabilities in prose written beside no code,
which is what the generated pages replace.
* ten root pages came back as ADDITIONS rather than conflicts, because origin
added what this branch had deleted from a different base. `check-routes`
caught all ten. Three name a served capability (automations, evals,
knowledge) and seven alias one; each had a generated page saying the same
thing with more authority.
Fourteen content conflicts were the same conflict: this side says
`/v1/account/keys` and `/docs/openapi/iam`, origin says `/v1/keys` and
`/docs/iam`. The fold moved the first and this branch deleted the second, and
check-endpoints is what proves which is true.
One real bug surfaced by the merge: the CLI generator wrote flat files, so the
`index` capability's page landed on the same filename as the section's own
index. Every group is a folder now, which is how the reference already solved it.
content/docs/projects/hanzoai/s3/ held 218 files of another project's server
documentation, published under our name at /docs/projects/hanzoai/s3: 11 MB,
23 Go files carrying AGPL-3.0 headers, and five go.mod files declaring that
project's module path. Its own meta.json lists exactly one page, `index`, so
none of it was reachable from the nav either -- a snapshot nobody navigated to
and nobody had read since it landed. What stays is the two-file placeholder
every repo without docs gets, so the route still resolves.
The rest is small and first-party: a table row, a retention sentence, a vendor
list, and S3_ENDPOINT in base-platform.yaml, which named a Service that exists
in no namespace -- our object store answers on s3.hanzo.svc:9000.
The two redirect source paths in public/_redirects keep the old spelling on
purpose. They are the URLs the deleted pages were published at, so they have
to match to catch an old link; the comment above them now says what the object
store is instead of what it is not.
Co-authored-by: Hanzo Dev <[email protected]>
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.
The rename left "Hanzo Datastore — Datastore analytics backend", "Datastore mode
(Datastore sidecar)" and "Datastore (Datastore native TCP)".
Comments in the kms action and the dev-docs lane describe the system rather than
how it got here.
Our own prose called the analytics store by the upstream's name — "ClickHouse-
powered analytics", boxes labelled ClickHouse in every architecture diagram,
"Hanzo Datastore (ClickHouse)". That now says Datastore.
The line held: a name a reader must type or resolve EXACTLY is a value, not
branding, and renaming it makes the docs wrong. So these stay — the Go module
path, the pip package and the Rust crate, the OTEL exporter component names,
the DSN scheme, /var/lib/clickhouse, the server image's own CLICKHOUSE_USER and
CLICKHOUSE_PASSWORD, and every "Apache-2.0 ClickHouse fork", which is
attribution the licence requires.
Substituting blind produced nonsense the first time — "a Datastore-compatible
engine", "Hanzo Datastore (Datastore)" — so where the vendor carried the fact,
the sentence states the fact instead: Datastore speaks SQL over HTTP on 8123 and
a native binary protocol on 9000, and standard OLAP drivers for either wire
connect without a shim. Box art keeps its width; the borders still line up.
Three things the debrand turned up, each fixed:
commerce reads DATASTORE_URL and nothing else (commerce.go:165), yet the docs
told readers to set CLICKHOUSE_URL, CLICKHOUSE_DATABASE, CLICKHOUSE_USER and
CLICKHOUSE_PASSWORD — and gave http://…:8123 where the code wants the native
DSN on 9000. One DSN now, carrying host, credentials and database.
`kubectl port-forward svc/clickhouse` names a service that does not exist. The
cluster has datastore, hanzo-datastore and insights-datastore.
projects/ mirrored repos that 404 — clickhouse-go, clickhouse-go-mock and
datastore-orm all moved to hanzo-ds, so those pages mirrored nothing and could
not regenerate. Gone, with the nav entries that pointed at them, and the dead
hanzoai/infi.clickhouse_orm entry out of projects.json.
apps/spec is generated from hanzoai/hips and is not fixable here.
Our own prose called the analytics store by the upstream's name — "ClickHouse-
powered analytics", boxes labelled ClickHouse in every architecture diagram,
"Hanzo Datastore (ClickHouse)". That now says Datastore.
The line held: a name a reader must type or resolve EXACTLY is a value, not
branding, and renaming it makes the docs wrong. So these stay — the Go module
path, the pip package and the Rust crate, the OTEL exporter component names,
the DSN scheme, /var/lib/clickhouse, the server image's own CLICKHOUSE_USER and
CLICKHOUSE_PASSWORD, and every "Apache-2.0 ClickHouse fork", which is
attribution the licence requires.
Substituting blind produced nonsense the first time — "a Datastore-compatible
engine", "Hanzo Datastore (Datastore)" — so where the vendor carried the fact,
the sentence states the fact instead: Datastore speaks SQL over HTTP on 8123 and
a native binary protocol on 9000, and standard OLAP drivers for either wire
connect without a shim. Box art keeps its width; the borders still line up.
Three things the debrand turned up, each fixed:
commerce reads DATASTORE_URL and nothing else (commerce.go:165), yet the docs
told readers to set CLICKHOUSE_URL, CLICKHOUSE_DATABASE, CLICKHOUSE_USER and
CLICKHOUSE_PASSWORD — and gave http://…:8123 where the code wants the native
DSN on 9000. One DSN now, carrying host, credentials and database.
`kubectl port-forward svc/clickhouse` names a service that does not exist. The
cluster has datastore, hanzo-datastore and insights-datastore.
projects/ mirrored repos that 404 — clickhouse-go, clickhouse-go-mock and
datastore-orm all moved to hanzo-ds, so those pages mirrored nothing and could
not regenerate. Gone, with the nav entries that pointed at them, and the dead
hanzoai/infi.clickhouse_orm entry out of projects.json.
apps/spec is generated from hanzoai/hips and is not fixable here.
content/docs/projects/hanzoai/s3/ held 218 files of another project's server
documentation, published under our name at /docs/projects/hanzoai/s3: 11 MB,
23 Go files carrying AGPL-3.0 headers, and five go.mod files declaring that
project's module path. Its own meta.json lists exactly one page, `index`, so
none of it was reachable from the nav either -- a snapshot nobody navigated to
and nobody had read since it landed. What stays is the two-file placeholder
every repo without docs gets, so the route still resolves.
The rest is small and first-party: a table row, a retention sentence, a vendor
list, and S3_ENDPOINT in base-platform.yaml, which named a Service that exists
in no namespace -- our object store answers on s3.hanzo.svc:9000.
The two redirect source paths in public/_redirects keep the old spelling on
purpose. They are the URLs the deleted pages were published at, so they have
to match to catch an old link; the comment above them now says what the object
store is instead of what it is not.
Co-authored-by: Hanzo Dev <[email protected]>
Measured across apps/*/content/**/meta.json: 76 separators, 2 with an
icon, 74 without. A bare "---Title---" renders as naked text between
icon-bearing rows, so the majority case looked like the broken one.
72 of 76 now carry one. The remaining 4 are in
content/docs/projects/hanzoai/python-sdk/, which is gitignored upstream
content mirrored by scripts/sync-project-docs.ts — this repo's rule for
ported docs is "port, don't re-author", and an edit there is overwritten
on the next sync anyway.
11 of the 72 could not be fixed by editing the file. services/meta.json
is REGENERATED from the @hanzo/products catalog on every build:pre, so a
hand-added icon survives until the next build and no further. The map
lives in the generator instead. It lives there and not in @hanzo/products
because the catalog owns the taxonomy while how a category is DRAWN is a
docs concern; putting it upstream leaks presentation into the product
catalog. A category with no entry now warns by name rather than quietly
shipping a bare separator again.
One vocabulary, reused on purpose: the same idea takes the same mark
everywhere (Getting Started/Setup -> Rocket, Commands -> Terminal,
Reference -> BookOpen, Security -> ShieldCheck, ...). Every name is a
verified lucide export; an unknown one would not fail the build, it would
warn and render nothing, which is the state this commit removes.
Co-authored-by: Hanzo Dev <[email protected]>
The KMS docs were a 549-file vendored Infisical mirror documenting a v2/v3
API that exists nowhere in our estate. Ground truth, from source:
cloud/apps/kms/mount.go registers exactly seven routes --
GET/POST /v1/kms/health, /config, /auth/login
GET/POST/DELETE /v1/kms/secrets[/+]
lux/kms (the standalone binary) registers ZERO /api/ routes in Go; the
only /api/v3 strings live in a vendored SPA under cmd/kms/web/assets,
JS calling an API nobody serves.
So rewriting /api/v3/secrets/raw to /v1/kms/secrets/raw would have
fabricated a surface: probed live, /v1/kms/secrets/raw and
/v1/kms/secrets/zzz-not-real both return 403, i.e. secrets/* is a wildcard
behind an auth wall and "raw" is not demonstrated to exist. A doc that says
nothing beats a doc that 404s -- so the mirror is deleted, not translated.
549 files -> 7, and both meta.json nav files pruned to pages that exist.
This also retires app.kms.hanzo.ai, an NXDOMAIN host the mirror cited 351
times.
Two edits here look like damage and are not; both verified against source:
- base-docs k8s probe /api/health -> /healthz is CORRECT. base
apis/health.go:14 binds /healthz at root ("platform standard"), with
/health only under the API group.
- the ported ingress docs /api -> /v1/ingress is CORRECT. hanzoai/ingress
is our Traefik fork and it renamed the prefix: pkg/api/handler.go:94-120
serves /v1/ingress/rawdata, /overview, /entrypoints, ...
Co-authored-by: Hanzo Dev <[email protected]>
Verified unreferenced across every source, style and config file in each
package — not an import, not a `@plugin`, not a script:
apps/docs shadcn 4.8.2 the only occurrences of the word are the
showcase entry for ui.shadcn.com and a
synced project description
apps/base-docs next-themes the app's provider does not use it
packages/shadcn tailwindcss a devDependency the package never invokes;
its peer on `shadcn` is what it integrates
`tailwindcss-animate` stays where it is: eleven apps load it with
`@plugin 'tailwindcss-animate'` in global.css, which is a real reference.
(cherry picked from commit 84d7384da9446ec22e735c51f45875e3c56742ac)
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]>
The placeholder was gated on `#app:empty` — but Scalar mounts as a SIBLING of
#app, so #app is empty forever and the loading message became a permanent
146px band pinned above the real reference on every visit, on both viewports.
The first thing a customer saw on our API reference was a load state that
never resolved.
Gated on `html.booting` instead, cleared by a MutationObserver on the first
rendered node with a load-event fallback — so it cannot outlive the load
regardless of where Scalar mounts.
Also: the file claimed 'no runtime CDN' while Scalar fetches fonts.scalar.com
(13 CSP-blocked requests per load, silently falling back off-brand). Comment
corrected to state the truth and Geist pinned so the reference matches docs.
Brand: 'LLM API gateway with all models' -> 'One API for every model';
'chat-completions proxy' -> 'chat completions'. Honesty: dropped the '$5 free
credit' line from base-docs pricing (that grant is disabled).
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).
Replaces all ghcr.io/hanzoai/<svc>:latest pins with the latest published
semver tag for each service. Per CLAUDE.md auto-bump policy: mutable
branch tags (:latest, :main, :dev) are deprecated for cluster pins —
only immutable semver permitted.
Bulk update across services with published v* tags. Services without a
published semver remain on :latest until their release pipeline cuts a
v* tag.
- Fix 6 wrong model prices in zen-docs pricing.mdx to match Go billing
controller (zen4-ultra, zen4-max, zen4-pro, zen4-coder-flash,
zen3-nano, zen3-guard)
- Fix zen-models compute tiers to match marketing (Nano $5 through
Power $49, not the old PaaS internal pricing)
- Fix platform AI model prices to include 1.2x third-party markup
(Claude Sonnet $3.60/$18, GPT-5 $1.50/$12, etc.)
- Update base-docs pricing to use marketing tiers matching
platform/visor ($5/$6/$12/$24/$36/$49 instead of PaaS $6-$384)
Replace hardcoded 3-tier pricing with dynamic fetch from
pricing.hanzo.ai/v1/pricing/cloud/plans. Shows all 6 canonical
PaaS compute tiers (Starter $6 through Enterprise $384) with
real vCPU/RAM/disk specs and hourly rates. Static fallback
ensures the page renders even when the API is unreachable.
New docs site for Hanzo Base following the monorepo docs framework pattern:
- Landing page with feature grid, quick start, and architecture highlights
- 9 documentation sections: getting-started, collections, auth, realtime,
file-storage, cloud-functions, SDK (JS + Go), and deployment
- K8s manifests for base.hanzo.ai (static docs) and api.base.hanzo.ai
(multi-tenant Base platform with IAM/KMS integration)
- Dockerfile with nginx for static export serving
- Monochrome Hanzo theme via neutral.css + Geist fonts