Correcting this branch's own conflict resolution, not upstream work. Origin
already imported `compile`, `ExampleRequestItem` and `RequestTabsRenderContext`
— relatively, further down the file — so taking the rescued commit's absolute
`@/ui/...` forms declared each name twice and tsdown refused to parse:
[PARSE_ERROR] Identifier `ExampleRequestItem` has already been declared
The rescued commit fixed real missing imports on ITS lineage; on this one they
were already there. Keeping origin's relative form.
Co-authored-by: Hanzo Dev <[email protected]>
Rendering a request body threw for any media type the adapter registry did
not cover, which ended the export of all 6,952 pages over one operation:
Error occurred prerendering page "/docs/openapi/smart-http/gitUploadPack"
Error: Media type application/x-git-upload-pack-request is not supported
(in /v1/git/{org}/{repo}/git-upload-pack)
Nothing in that subtree needs an adapter: it renders the schema and the
TypeScript definitions. The adapter is needed to SEND a body from the
playground, and `createBrowserFetcher` already handles its absence there with
a readable 400 naming the missing adapter. So the throw protected nothing and
cost the site — git's smart-HTTP protocol has a real media type, and a
reference that refuses to document it is worse than one that documents it and
says it cannot be sent from the browser.
Co-authored-by: Hanzo Dev <[email protected]>
(cherry picked from commit 811a5e8b30845fb94579039cd11996d1147dc163)
The upstream merge (9b95157ad) dropped the body of `renderResponse` from
`ui/operation/response-tabs.tsx` and kept the call to it. tsdown does not
type-check, so it shipped and the hub build died two phases later:
Generating static pages using 19 workers (0/6952) ...
ReferenceError: renderResponse is not defined
Restored from 337c93491, the last revision that had it, adapted to the
current signature: `renderResponseTabsDefault` is synchronous now, so the
renderer is too, and each `<Tab>` carries a key. Behaviour is the one the
imports in that file already describe — one accordion per example when there
are several, the example inline when there is one, the `empty` label when
there are none.
The same sweep over the rest of the package, by type-check rather than by
build failure:
ui/client/i18n.ts `useTranslationsBase` was the old name of the
context's `useTranslations`; `TranslationValue` was
never imported. `I18nLabel` is what the restored
renderer calls for an empty response, so this was
the next ReferenceError in line.
i18n.ts imported `TranslationsOption`, which no UI context
exports, and used `TranslationValue` /
`TranslationsAPIExtension`, which core does.
ui/schema/client.tsx `CheckIcon` and `LinkIcon` missing from the
lucide-react import beside them.
playground/fetcher.ts read `options.bodyMediaType` inside `fetch(url, data)`
— the parameter is `data`.
tsc --noEmit -p packages/openapi
before 17 errors
after 2, both real API drift rather than a missing name:
`@scalar/api-client-react` renamed its hook, and a test helper
references a boundary it does not import. Left for a decision.
(cherry picked from commit d7f880c8feb0670153c8ca7b1b71a3a5d6aac0bf)
Co-authored-by: Hanzo Dev <[email protected]>
`ui/base.tsx` referenced five identifiers it never imported. tsdown does not
type-check, so the package built clean and the references became runtime
ReferenceErrors. One of them took the hub build down:
Error occurred prerendering page
"/docs/openapi/orgs/post_v1_orgs_org_entitlements"
ReferenceError: PlaygroundAuthProvider is not defined
`base.tsx` is the server renderer; it reaches client components only through
the lazy boundary, which is where `PlaygroundAuthProvider` lives. The default
playground provider now closes over it there, beside the sibling that already
reached `PlaygroundClient` that way, and the boundary module exports it so
both boundaries carry the same set. The client renderer (`create-client.tsx`)
was already correct — it imports `AuthProvider` directly, which a client
module may do.
`pickSchema`, `encodeInternalRef` and `compile` are the other three: all live
(`renderPlaygroundDefault`, `generateTypeScriptDefinitions`), all one import
away, all latent ReferenceErrors on the playground and TS-definition paths.
`ExampleRequestItem` and `RequestTabsRenderContext` were type-only.
tsc --noEmit -p packages/openapi
before 8 errors in ui/base.tsx
after 0
Four files in the package still carry the same defect — `i18n.ts`,
`ui/client/i18n.ts`, `playground/fetcher.ts`, `scalar/client.tsx` — but each
needs an API decision (a renamed upstream export, a changed @scalar surface),
not an import. Left alone rather than guessed at; nothing on the current
render path reaches them.
(cherry picked from commit 10ccb563cc235268f0f7abfd1942f10a5d297c04)
Co-authored-by: Hanzo Dev <[email protected]>
hanzo.yaml's iam_ApiController.GetWebhooks requires `test_apiKey`;
components.securitySchemes defines bearerAuth, BearerAuth, oauth2, apiKey,
serviceKey and s3Auth, and not that. Every consumer looks the id up and then
reads a property of it — schemes[id].deprecated in useAuthInputs, again in
SecurityRequirement — so one line of a 58k-line document threw "Cannot read
properties of undefined" out of a prerendered page and ended the whole export
at 1510/6041 pages.
parseSecurities is where a requirement becomes entries, so it is where the
document stops being untrusted input: drop ids the document does not define,
name the operation and the scheme in the warning, and nothing downstream has to
re-check. An undefined scheme carries no credential to render or send, so
dropping it is also what it means.
The document bug is real and still wants fixing in hanzoai/openapi — this only
stops it costing the site.
Co-authored-by: Hanzo Dev <[email protected]>
c04da7fb6 took 334 upstream commits and resolved the conflicts by keeping this
fork's import lines above upstream's bodies. The bodies then reached for names
nothing imported — useMemo, CheckIcon, LinkIcon, useApiClient, compile,
ExampleRequestItem, RequestTabsRenderContext, TranslationValue,
TranslationsAPIExtension, ClientBoundary, processDocument — 24 type errors in a
package that kept publishing, because tsdown does not type-check. Each one is
restored from where upstream imports it, under our name for the fork.
renderResponse was the one that was not an import. The resolution kept our
`{tabs.map(renderResponse)}` and took upstream's rewrite of the function above
it, which had inlined that body and deleted the definition — a call with no
callee. Reconstructed from upstream's inlined form, keeping the fork's deltas
(base-ui tabs, and hanzo_docs_openapi_requests to match the responses group id
rather than leak the upstream brand into a storage key).
Three fixes come with it, all the same merge:
- fetcher returned the old {status,type,data} error shape from a `data`
parameter it called `options`, against upstream's new FetchResult union.
- request-tabs and schema/client carried imports for symbols they never use,
two of them from the Radix package.
- openapi-sampler goes: upstream replaced it with @/utils/schema/sample and
response-tabs was the last importer still pointing at the package.
63 tests pass — three suites could not even import test/utils before this.
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]>
openapi/story/cli/python imported @hanzo/docs-base-ui (and others) without
declaring it. Under pnpm strict isolation Turbopack resolves from the importing
package's node_modules and couldn't find base-ui's subpath exports
(components/ui/button, components/tabs, utils/use-copy-button) — webpack was
lenient. Declare the missing workspace deps so resolution is deterministic.
Same dropped-import class: page-actions (radix-ui/base-ui) and openapi's client
i18n call renderTranslation() without importing it from @hanzo/docs-core/i18n.
inputs.tsx imported FormatFlags from a path that no longer exists; the util
lives at src/utils/schema/to-string.ts. The stale path was silently
externalized by tsdown and leaked into dist, breaking the docs Next build.
Revert the exploratory tsdown alias — the fixed import resolves under the
package's existing default resolution.
The docs Next build failed on 24 unresolved modules, so no content pages
ever shipped (every /docs sub-page 404s live). Root causes, all fixed:
- @hanzo/docs-openapi dist leaked its internal `@/` path alias
(`@/utils/schema-to-string`, `@/playground/*`, `@/requests/*`) because
tsdown ran with unbundle:true and no alias mapping. Add
`alias: { '@': src }` so the built dist resolves to relative paths.
- @hanzo/docs-openapi imported `openapi-sampler` without declaring it — add
it as a dependency so consumers can resolve it.
- apps/docs imported packages it never declared (phantom deps under pnpm's
strict node_modules): @hanzo/docs-base-ui, @hanzo/logo, @hanzo/iam,
@radix-ui/react-select, @radix-ui/react-slot, openapi-sampler. Declare them.
- lib/source imports the bare `collections/server` specifier but only
`@hanzo/mdx:collections/*` was aliased. Alias the bare form too.
Three phantom/path stragglers the prior normalization passes did not cover,
all blocking the package build chain (`turbo run build --filter=./packages/*`):
- packages/cli: `@hanzo/docs-cli/build` was imported by apps/docs +
shared/radix-ui/base-ui registries but the cli package never exposed it.
The real registry-build API is fuma-cli/compiler (cli already deps on
fuma-cli). Add src/build.ts re-export + ./build export + tsdown entry so
`@hanzo/docs-cli/build` resolves to the real symbols (compile, writeRegistry,
Registry, Component, Reference, SubComponentReference, CompileOptions).
- packages/hanzo-docs core/content/index.ts: barrel re-exported a bare
fumadocs-core/content subpath that exists in no version (upstream or fork).
Aggregate the real sibling modules (./github + ./toc) instead — no symbol
collision (getGithubLastEdit vs getTableOfContents).
- packages/openapi src/ui/client/full.tsx: import of ./components/codeblock
resolved one dir too shallow (file lives in src/ui/client/, codeblock in
src/ui/components/). Fix to ../components/codeblock, matching create-client.tsx.
Verified: full package chain builds green from cold cache (29/29, node 24.18).
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).
* feat(openapi): anchor links on schema properties
Each property rendered inline in a request body, response body, or parameter
now gets a stable id and a hover-revealed link icon, enabling deep links to
specific fields from guides. Ids follow:
- body-<prop> for request bodies
- response-<status>-<prop> for responses
- parameters-<location>-<name> for parameters
A new idPrefix option on SchemaUI opts other Schema renderings into the same
behavior. See fuma-nama/fumadocs#3322.
* feat(openapi): deep-link nested schema properties
Extend the property anchor scheme to support hashes that point inside a
popover or below an array's "Show array" collapsible. Schema-internal
segments are joined with `.` so `#body.user.address.street` resolves
unambiguously regardless of dashes in property names.
On hash match, the inline anchor scrolls into view, the matching popover
auto-opens with its breadcrumb pre-navigated, the array collapsible
expands, and oneOf/anyOf tabs switch to the variant containing the
targeted field. The deep target is consumed after the first auto-open,
so subsequent user clicks on the same trigger get the base view; a
different deep hash re-arms it.
The hover anchor is now a copy-link button (matches fumadocs heading
anchors) that writes the full URL to the clipboard and updates the
address bar via history.replaceState (no hashchange, no popover reset).
* address PR review feedback
- Clarified the changeset: split anchor ID rules by context (request/response property paths vs flat parameter anchors) so dots aren't implied to apply to parameters.
- Namespaced anchors by media type when an operation has multiple request-body or response content types: prefix becomes `<media-slug>-body` / `response-<status>-<media-slug>`, and the content-type SelectTabs auto-switches to the targeted tab when a deep link arrives. Single-content-type operations keep the simple `body` / `response-<status>` form.
- Made findUnionPropMatch validate the *full* remaining path (via new pathResolves helper) so two variants that share the first prop name no longer race; the wrong tab can't be selected for a deep hash anymore.
- Reset SchemaUIPopover breadcrumb state when initialPath changes so a fresh deep hash takes effect on an already-open popover.
- Replaced the lossy slugifyPropertyName with encodeURIComponent (plus % encoding for `.`) so property anchors stay collision-safe across case-only differences, punctuation-only differences, and non-ASCII keys, while `.` remains exclusively a path separator.
* address PR review feedback
- Fix potential hydration mismatch in useTabValueFromHash by initializing state with the fallback value and resolving from the URL hash inside useEffect; the deep-linked tab now corrects after hydration on the client.
* fix(openapi): move useTabValueFromHash into a client component
The previous hydration-mismatch fix put `useEffect`/`useState` directly in
`operation/index.tsx`, which is a Server Component — Next refused to compile
because RSC modules can't import client-only React APIs. Extract the
hash-aware tab wrapper into `operation/hash-tabs.tsx` (with `"use client"`)
and switch both body and response sites to `HashAwareSelectTabs`. The parent
tree stays server-side; only the tab wrapper hydrates on the client.
* address PR review feedback
- Wrap decodeURIComponent in try/catch in both deep-link hash parsers so a malformed percent-encoded fragment (e.g. `#body%`) is treated as "no target" instead of throwing URIError and breaking tab / popover resolution.
* address PR review feedback
- Match the URL hash against DOM ids using the raw fragment first, with the fully-decoded form as a fallback, in both DeepLinkProvider and hash-tabs. Property anchors are generated via slugifyPropertyName (which percent-encodes reserved chars like `.`), so DOM ids contain the encoded form; decoding the hash before lookup caused links like `#body.foo%2Ebar` to miss the matching element.
* redesign
* fix types
---------
Co-authored-by: Fuma Nama <[email protected]>
* OpenAPI: render deprecated badge for deprecated operations
Show a yellow "Deprecated" badge for any OpenAPI operation marked
`deprecated: true`. The badge appears in two places: inline with the
operation heading when `showTitle` is true, and as a standalone header
above the playground card when `showTitle` is false (which is the
default for individual operation pages generated by `openapiSource`).
This restores the behaviour originally added in #2417, which was lost
during the v9→v10 move of the operation renderer from
`packages/openapi/src/render/operation/index.tsx` to
`packages/openapi/src/ui/operation/index.tsx`. The parameter-level,
schema-property-level and auth-scheme-level deprecated badges all
survived the refactor; the operation-level one was silently dropped.
The example spec's `deletePlanet` operation already claimed in its
description to be deprecated but never set the flag (inherited from the
upstream Scalar Galaxy fixture). Setting it both fixes the
inconsistency and provides a visible demo for the new badge.
* OpenAPI: improve operation deprecation styles
---------
Co-authored-by: Fuma Nama <[email protected]>