Booker and BookingForm take prefill, the name, email and notes the
details step starts with. hanzo.ai's sales page sends its visitor to
cal.hanzo.ai with the answers they gave, and nobody types them twice.
Claude-Session: https://claude.ai/code/session_01HuMDfgFssPUptYUzgZ6Cp8
A browser strips a tab out of a URL before it parses it, so /<tab>/host arrived
as //host: another site, drawn as this app's own section.
Co-authored-by: Hanzo Dev <[email protected]>
A section points at a path of the app or an https address on another host;
a protocol-relative, script or bare address is not drawn, and the home mark
falls back to the app's root. The scope renders in exactly one place, the bar
or the phone's sheet, so there is one selection and one set of reads. A
notification is marked read or archived only when its id is a single plain
segment, and a reason the server names is looked up in a Map. The scope's
keys are per workspace, not per person, and the README says the host clears
them when the person changes. `.auth/` is ignored.
Co-authored-by: Hanzo Dev <[email protected]>
hanzo.ai and the Hanzo App each drew their own copy of the workspace shell,
and the copies had drifted. The frame is here now, once: the rail of
sections, the sidebar with the workspace switcher at its top and the account
at its foot, the bar, the pane, and the column beside it that a room fills
through Beside.
The rail is the sidebar shut on a laptop (an explicit toggle kept per device,
never hover) and the tab bar on a phone. The far-left strip that stands beside
an open sidebar is opt-in through `strip`, off by default. The account menu is
Profile, Notifications, Appearance, Security, Sign out, and carries no
balance. Scope puts project and environment in the bar, kept per workspace
and never carried across one. Notifications reads the reader's own through
the host's call; the package holds no credential.
The frame follows the host's theme, so its inks are the host's own rungs
(FRAME in theme.ts). Its layout lives in shellStyles.ts beside the chrome's,
injected by an insertion effect so the grid is in place before first paint.
@hanzogui/shell 8.3.19
Co-authored-by: Hanzo Dev <[email protected]>
Every plane hangs inside the header, and the header carries backdrop-filter,
which makes it a backdrop root: a descendant's own blur samples only what the
bar paints, never the page. So the 72% glass plane showed the hero straight
through the menu in Chromium and WebKit alike. The plane is the opaque panel
now, the bar wears that same ground while a plane or the sheet hangs from it,
and the veil dims deep enough to recede without its blur. The scrolled bar is
still glass, where the blur is real. No API change.
@hanzogui/shell 8.3.18
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]>
@hanzo/event 0.3.39 and 0.3.40 carry a Hanzo key whose project no
longer exists, so the ingest door answers every beacon from gui with
403 ingest_key_unknown. 0.3.41 carries the current keys. The telemetry
package asks for it, and an override lifts the copy @hanzo/observe
pins to the same version.
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]>
The bar linked Privacy, Terms and Cookies. The Acceptable Use Policy, the
Data Processing Addendum and the subprocessor register — what a procurement
review asks for first — were reachable only from inside another document.
hanzo.ai/legal indexes all of them; the bar now names it.
Co-authored-by: Hanzo Dev <[email protected]>
workspace:, link: and file: resolve only inside the monorepo that
declares them, so any of the three in a published manifest is a
consumer install that dies. The rewrite handled workspace: alone, and
it trusted the manifest it had just written — but npm pack runs
prepack and prepare, which are free to rewrite package.json again.
Cover all three protocols and read the manifest back out of the
archive before pushing it. A version is immutable once it lands:
@hanzogui/[email protected] still carries eleven of these and no publish can
repair it.
Co-authored-by: Hanzo Dev <[email protected]>
The package goes out from the release script, not from here: this
file has never produced a run on either plane.
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]>
The forge reads .github/workflows natively and github.com reads nothing else,
so one directory serves both planes instead of two conventions that disagree
about which one is live. The reusable in hanzoai/ci already lives there, so a
caller naming that path now resolves to a file that exists.
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 first extraction in a test file esbuild-bundles the config and every
component package and then requires the result — seconds of real work,
once per worker, charged to whichever test asks first. Vitest's 5s
default was never a budget for that, so three static-tests failed by
timeout on an idle machine.
Co-authored-by: Hanzo Dev <[email protected]>
transformConfig deep-cloned the whole config and then replaced every
theme variable with its value, so the clone built roughly 300k objects
that were discarded in the same pass. Measured on the default config
(900 themes x 362 variables), the same transform: 3502/6722/5005ms
before, 202/241/29ms after, and the emitted hanzogui.config.json is
byte-identical. It was most of a cold compiler start.
Co-authored-by: Hanzo Dev <[email protected]>
hanzo-build-linux-amd64, lux-build-linux-amd64, zoo-build-linux-amd64 and
every other org-prefixed spelling all meant the same machine. Which org a
job belongs to does not change which host can build it, so the org bought
one pool name per org per arch and each could go stale on its own -- the
evo host alone answered to fourteen names for one label.
One vocabulary now: linux-amd64, linux-arm64, macos-arm64, win-amd64. The
generic labels every plain workflow uses (ubuntu-latest, self-hosted) are
untouched, so naive CI keeps working.
Co-authored-by: Hanzo Dev <[email protected]>
The hanzo-team prefix is written by hanzoai/hanzo.ai's deploy lane, which
roots that same export at team.html to serve hanzo.team. Two publishers
on one prefix means the host answers with whichever lane ran last, so
apps/team stays here as source and this repo ships gui.hanzo.ai alone.
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]>
hanzoai/ci keeps the reusable at .github/workflows/build.yml — the one path
both planes resolve, since github.com reads a reusable only from there and the
forge reads it too. The v1 tag moved with it, so a caller still naming
.hanzo/workflows/build.yml asks for a blob that is not in the tree:
InsertRun: read hanzoai/ci@v1:.hanzo/workflows/build.yml: object does not exist
The caller itself stays at .hanzo/workflows/cicd.yml on purpose: github.com has
no runner for these labels, so a caller placed there could never be scheduled.
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]>
A card is a design decision, so it lives in @hanzo/ui; the framework
package went with the tree that removed it, but the lockfile still
resolved @hanzogui/card at pkgs/ui/card, which no longer exists. A
frozen install reads the lockfile, not the tree.
The same install caught the shell up to the 8.3.17 its package.json
already declares.
Co-authored-by: Hanzo Dev <[email protected]>
Hovering a column lights it and steps the others back, and below the
rail's width the four sections are peers rather than one tall column
with three stubs under it.
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.
This repository is Tamagui, continued. Its git history runs unbroken through
tamagui/tamagui mainline, and every package in the workspace except ten is
upstream's work carried under the MIT license the LICENSE file already
preserves.
A NOTICE saying so was added in July (61758e3cbc, 51bc03d148) and removed in
August by 2bb4f45f1f, which also rewrote LICENSE and stripped the README of
any statement of descent. Nothing about the facts changed in between, so the
attribution comes back, deliberately and in the house form: NOTICE carries the
whole of it, exact rather than approximate, and names the ten packages written
at Hanzo; the README carries one line of lineage pointing at it.
Five packages published under the @hanzogui scope still listed Nate Wienert as
"author", which claims he wrote a Hanzo package rather than crediting him for
Tamagui. That is worse than no credit. Their author is now Hanzo AI and the
derived-work credit lives in NOTICE, where it can say what it actually means.
LICENSE is untouched.
Co-authored-by: Hanzo Dev <[email protected]>
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]>
Cloud and Team are what the platform does rather than products beside
it, so one name carries all three and one door opens the console.
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]>
The brand pill pads by 12 and handed all 12 back, which put the NAME itself
exactly on the page's column. That is right for body text and wrong for a
wordmark: set in bold beside the window's edge it reads as flush, and the
gutter looks like it was forgotten.
Four of the twelve are kept. The lit pill still grows outward into the
gutter, and the name now sits a hair inside the column instead of on it.
An open menu is a layer over the page: the plane wears GLASS, the grounded bar
wears the same, so from the top of the screen to the bottom of the menu there is
one ground, one blur and no edge.
App, Bot, CLI, Cloud, Dev, IDE, Platform, Team, each with the line its product
page says under the name. Chat and Base stay products and leave the estate
menu. Every console address is platform.hanzo.ai.
Every door that opened console.hanzo.ai opens platform.hanzo.ai — the same
console, simplified for the people who use it — and the menu row wears the
product's name, Hanzo Platform.
App, Bot, CLI, Dev, IDE, Platform, Team — then Cloud and Chat. CLI and Platform
become flagship products (hanzo.ai/cli and platform.hanzo.ai both serve), and
Team is released rather than beta, so a signed-out reader meets all seven.
The order is stated once, where the menu derives it, so the product table stays
a table of what exists and a new product sorts to the end until it is ranked.
The bottom bar reads left to right as the page does: whose it is, what
governs it, then the mark closing the column.
The brand wears the chevron every other trigger in the bar wears. It was
the one control that opens a menu and did not say so, so a reader looking
for the products read past it.
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.