The responsive band runs 1000px past its container, so once that
section mounted the document was 1390px wide under a 390px screen again.
Clipping only the hero left every other backdrop free to do the same.
The clip moves into TintSection: each section is full-bleed, so its
edge is the page edge, and nothing on screen changes.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The hero's three lamps and its grid reach past the viewport on purpose,
and only the clip on html and body kept them out of sight. The document
itself was 960px wide under a 390px screen and 1790px under 1440.
The glow group now spans the page and clips its own lamps, and the hero
section clips its grid at the page edge. Nothing on screen moves; the
layout is as wide as the screen.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
apps/team moved to hanzo-apps/team with its history, and builds there
against the published @hanzo/gui. It leaves the workspace list, the
lockfile, and the Written-at-Hanzo list in every NOTICE (ten names
become nine).
Co-authored-by: Hanzo Dev <[email protected]>
497 is a point on Zen's variable axis, published by @hanzo/font as the
book preset alongside the faces it describes. It was reached through a
package that only restated it.
Co-authored-by: Hanzo Dev <[email protected]>
Playwright was told a port, so it started the suite as soon as the socket
opened and turbopack compiled the route inside the first test. A test's
time also covers its hooks, so that first test paid for launching chromium
on top of the two dev-server navigations every test makes.
Co-authored-by: Hanzo Dev <[email protected]>
The responsive section measured itself against a second container. Its
breakpoint ruler rode Container — the docs page's measure and gutter —
nested in the ContainerLarge every other section stands on, so a marker
labelled 500 stood 522px from the mock it measures, and below sm a
hand-fitted translate put the mock 25px left of its own heading, off the
page. Both take the section's own box now.
The preview strip scrolled to an arithmetic copy of its padding and gap
that had drifted from them by one gap per stop, so the ninth colour sat a
whole card off centre. It asks the layout instead.
A stop reaches the swatch, the demo, the ink and the stored accent, never
the ground, and a lamp carried past the hero is the ground by another
route — the wash still under the player row. The glow stays at the hero.
Two footer columns had no basis to size from once stacked and drew over
the next, nine swatches could not fit 390 in one row, and a title glued
to its last word was split mid-word instead.
Co-authored-by: Hanzo Dev <[email protected]>
A tint named an accent and then painted the page with it, so yellow put the
section on an olive ground and orange on a brown one — the complaint the
ramp was rebuilt to answer, reached by the other route. The ground and the
section surface now come off the neutral scale under all nine stops, which
measures as zero distance from the untinted ground on both schemes, and a
hue reaches the swatch, the demo, the ink and the stored accent instead.
That settles the rung too. With one ground per scheme rather than nine,
every stop is its solid step on dark, and only the light ground's nearness
to the bright end still pulls green and blue down one and orange two.
Co-authored-by: Hanzo Dev <[email protected]>
Yellow and orange were dropped for failing 3:1 against the light ground at
one uniform rung, which was a fact about the rung. Each stop now names the
rung that shows it on each scheme, and every dot carries an ink hairline —
the edge that draws white on white, black on black, and the yellow that no
rung can both darken and keep yellow. White, grey and black join as stops;
grey still clears the accent, and none of the three washes the page, since
an absolute palette under the other scheme's ink is a page with its text
turned off.
Dark is the default a reader who has named neither scheme gets: the meta
hands the UA dark rather than the machine's own answer, and the setting
that meant "ask the machine" is dropped, since the pre-paint script and the
app resolved it differently and the page turned light a frame after booting.
Co-authored-by: Hanzo Dev <[email protected]>
151 packages of Tamagui-derived code are on npm with no license text in
them. Checked four tarballs at 8.3.5 — @hanzogui/core, @hanzogui/web,
@hanzogui/shell and @hanzo/gui — and not one contains a LICENSE file.
MIT asks for one thing: "The above copyright notice and this permission
notice shall be included in all copies or substantial portions of the
Software." Shipping the code without it does not meet that.
The cause is mechanical rather than deliberate. npm includes a LICENSE
that sits in the package directory, and ours sits at the monorepo root,
where it reaches no tarball. So the license is now in each of the 153
publishable packages, and NOTICE beside it — that one npm will not take on
its own, so 152 manifests name it in `files`.
Verified by dry-run pack: 1.3kB LICENSE, 2.8kB NOTICE.
Already-published tarballs are immutable, so this corrects on the next
publish and not before.
The platform is what they were, so the menus name it once and the column
under it lists what the platform actually offers.
Co-authored-by: Hanzo Dev <[email protected]>
Three of the seven stops were yellow, which over the dark ground is an
olive, and the swatches sat in a Group, whose zeroed radii cut a straight
edge through each selection ring. The ramp now sweeps one arc of the
wheel and every stop is measured: the dimmest clears 3:1 against each of
the seven grounds the page can paint, on both schemes. Picking one writes
the accent through @hanzo/appearance, so the choice outlives the visit.
Co-authored-by: Hanzo Dev <[email protected]>
The framework was documented in hand-written MDX, which drifts the moment a
signature changes. The declarations each package emits already say what it
exports; a page that quotes them says the same thing and cannot say anything
else.
Co-authored-by: Hanzo Dev <[email protected]>
Every Hanzo surface reads @hanzo/design, @hanzo/tokens,
@hanzo/appearance and @hanzo/font; this site set its own type, so its
header, ramp and ground drifted from hanzo.ai and a reader's appearance
settings reached nothing here. Gui's $n ladder now resolves through the
design ramp, dark is the default, the chrome stays grey while the
landing sections keep their tints, and everything below the fold loads
as it nears the viewport. getFontSize reads the px fallback of a var()
size, which is what keeps icon sizing numeric once sizes live on a ramp.
The loader and the Next plugin only existed to drive webpack; Next runs
on Turbopack and Vite has its own plugin. kitchen-sink and the
integration app serve through vite, the optimizer suite drops the
webpack name, and its fixture packages join the workspace so a fresh
checkout links @my/ui.
The grid test asserts the element's own style, which is what the rule
sets; the computed value is jsdom's initial one.
Co-authored-by: Hanzo Dev <[email protected]>
Node's require never selects a package's react-native condition and
cannot load an ES module whose sources say a bare require, so the
extractor resolves that entry itself and translates such a file to
CommonJS as it loads. Directories are walked with the filesystem's
glob, negative numbers become AST through valueToNode, the swallowed
load error is named under DEBUG, and the optimize fixture is its
source again with the suite restoring it after each run.
Co-authored-by: Hanzo Dev <[email protected]>
Native sources say a bare require, which Metro provides and an ES
module cannot; marking dist/native CommonJS like dist/cjs lets Node
load it as written, so the optimizer's native pass runs again. The
.cjs sibling answers there too, the CLI imports its commands, the
loader names its css file by the emitted name, and the extractor
tolerates a dependency whose tsconfig extends a preset it lacks.
Co-authored-by: Hanzo Dev <[email protected]>
React passes ref as a prop, and a forwardRef over props with an index
signature drops every named prop through Omit; the font extras are
optional in a spread function's config.
Co-authored-by: Hanzo Dev <[email protected]>
A top-level `const require` is legal in a script and a syntax error
inside Node's CommonJS wrapper, which is where the emit actually runs,
so the local createRequire alias is now `need` and the runner names
any file that declares require, module, exports, __filename or
__dirname.
Co-authored-by: Hanzo Dev <[email protected]>
Every published manifest now states the same exports: types, the
native emit where the package builds one, ESM under import and
CommonJS under require, with src, types and dist in files. The nine
packages that read import.meta do so in one here.ts each, with a
here.cjs.ts sibling for the CommonJS emit; the stragglers on bun,
esbuild, plain tsc or hand-written shims build with the runner like
everything else, and the root-level .cjs shims that pointed at emits
no build produces are gone, as is the vite-plugin-cjs mirror.
Co-authored-by: Hanzo Dev <[email protected]>
turbo orders a build by declared dependencies, and a forced rebuild found
three packages typechecking against siblings they never named, one of them
through a subpath the types package no longer exports.
serve:railway just binds 0.0.0.0 (any container host, not a Railway
particular); call it serve:host and update the CI wrapper's three
call sites to match. The health-check comment drops the same
name-drop. RAILWAY_DEPLOYMENT_ID in setup.server.ts is Railway's own
env var and stays — it's the actual boot-time production guard.
Co-authored-by: Hanzo Dev <[email protected]>
Supabase auth, Stripe, purchase modals, Bento and Takeout promotion, the
consulting link and the vendor's talk images were the upstream business,
not documentation. The header, home page, theme page and quick nav lose
the account and promotion surfaces; the content loses the paid gating.
The browser bundle answered process.env.GUI_TARGET with an empty object,
so every web check failed after hydration and the page lost its classes;
the compiler plugin used to define it. reanimated leaves the manifest,
which is what routed the whole build through a Babel pass that Babel 8
cannot load, and one's inline sourcemap: false yields to a config hook.
esbuild emitted without looking, so a driver could return an animated
style the hook's type did not admit, read a styleState the core passes
but never declared, and widen a snapshot field on the way through a
helper. The Ink screen asked for props Ink never had, and the solito
test was already commented out of its index.
Every config augmented a module named hanzogui, which no package
provides, so TypeScript declared a fresh ambient module and the
shorthands never reached a component's props: 187 errors in demos alone.
The project files inherited the root paths map, so a package's typecheck
read its siblings' source instead of their published declarations and
failed on files that were never its own. An ESM-only manifest now names
no dist/cjs path under any condition, the native emit names its renamed
map, and the runner has a test of its own again.
The store is wired into the header and the home page, so deleting the files
that import it removed the site. Those files are back; a HeadAnchor variant is
named menu, because gui now has a grid style prop that shadows a variant of
that name; and the community page, which imports a component this repository
never held, is gone. The store's own files remain until their importers stop
importing them.
Stripe, Supabase, Bento, Takeout, seats, licenses and coupons came with the
fork of the site and sold nothing here. Identity is Hanzo IAM and there is no
store, so the forty-four routes, the purchase flow and the theme-history
persistence go, and what remains is a docs site.
The credential rode along as the last argument of every operation —
fetchRooms(token), fetchMessages(id, space, token), sendMessage(id, space,
text, token) — so who you are and what you are doing were stitched
together at every call site, and two modules each built their own client
against the same address. Applying the token once returns the operations
already bound to it: team(token).rooms(), .messages(id, space), .say(id,
space, text).
Transport and reading were the other pair. Billing mixed calling the route
with deciding what a balance looks like, which it has to do because
/v1/billing/balance states no response schema — so the reading moves to
money.ts, where it is a function from an untyped record to a Wallet and
can be read without the request around it.
Eleven lines shorter, and each file answers one question.
Ranges drift once nothing moves them: a caret that has not been rewritten
since it was written pins whatever was current that day, and an exact pin
cannot even take a patch. Both are updated here.
One line per package, so a surface reads the same components, the same
tokens and the same face as every other one.
One family. Font stacks name Zen and fall back to the native faces, tokens
name the role rather than a face, and the packages that used to supply a
face now point at @hanzo/font.
Self-hosted @font-face blocks are removed rather than renamed: rewriting the
family in one would leave a src pointing at a file this repo no longer ships.
@hanzo/font carries the binaries and declares the faces, so the local copies
go with the declaration that used them.
Comments naming a face we no longer use are deleted, not reworded.
The API base, the issuer and the client id were three literals in three
files, so pointing the app at a cloud on localhost meant editing all of
them — which is how one of them stays edited. config.ts states each once,
defaulting to production, and vite replaces them at build time.
A `define` rather than envPrefix and import.meta.env: this app builds for
native too, where that form is not reliable — the build already warns
about it. A define is textual, so it lands the same way in both, and an
unset variable leaves the production default standing.
The app stated its own base URL, its own routes and its own Authorization
header, which is a second copy of a contract the SDK already publishes —
and the copy is the one that goes stale. hanzoai carries the routes, the
models and the bearer header, so team.ts is now the four calls the screens
make and nothing else.
Billing moves with it, off the per-product billing.hanzo.ai host and onto
the one endpoint. Its balance reduction stays: that operation states its
route without a response schema, so the shape really is the caller's
problem and pretending otherwise would need a cast.
Every generated field is optional because the document marks none of them
required, so a room missing either half of its address is skipped rather
than linked to a URL that cannot resolve.
The OIDC fallbacks named three paths that answer 404, two of them under an
/api/ prefix IAM has not served in a long time. They are only read when
discovery is down — the one moment nothing else can cover for them.
hanzo.team was served by a Mattermost fork whose apex has been 502ing, and
the surface replacing it had login and a wallet but nothing to talk in —
so dropping the server would have left the product with no conversation at
all. The cloud team API has answered /rooms and /rooms/:id/messages the
whole time; this reads them.
vite.config named guiPlugin, which the plugin has never exported. Every
other app in the repo says hanzoguiPlugin. That typecheck error is why
this app built nowhere, and it is why hanzo.yml can now declare the site.
Two thousand and twenty-one packages carried more than one spec across this
estate — eslint alone in a hundred and four forms — and a package resolved twice
is two copies at run time, which is how react-hook-form came to report "two
different types with this name" from files nobody had edited. None do now.
The number lives in the catalog: a manifest names the package, the workspace
names the version. Where a manifest cannot reach a catalog it still carries the
one version, because the table is the source either way.
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.
These are genuinely our Zen — family and vendor tag both right — but nameID 0
named only Hanzo. OFL section 2 binds each copy of the Font Software to its
copyright notice, and a .woff2 served to a browser is a copy travelling alone,
so both holders belong in the face itself: the Geist Project Authors, whom Zen
derives from, and us. Replaced with the bytes @hanzo/font publishes, matched by
the family in the name table rather than by filename.
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.
@hanzogui/config/v5 starred both @hanzogui/themes/v5 and ./v5-base, and
v5-base re-exports a dozen names it takes from themes/v5 — createThemes,
tokens, the palette helpers, the theme types. ESM calls a doubly-starred name
ambiguous and omits it rather than picking one, so every shared name silently
left the module: `import { tokens } from '@hanzogui/config/v5'` compiled and
resolved to undefined.
It ships as a patch in at least one consumer, which is the wrong home for it —
a fix in a patch file is a fix exactly one app gets, and only until its
overrides drift. So v5 now names the nine things themes/v5 carries that
v5-base does not, and everything they share arrives through v5-base, which is
the module that already curates it.
8.3.1.