mirror of
https://github.com/hanzo-apps/gear.git
synced 2026-10-30 19:15:41 +00:00
Assign and track company assets — who holds each one and its status. Forked from the canonical hanzo-starter: identical provider stack, vite.config, PKCE auth against hanzo.id, and static-SPA deploy contract. Three views built on @hanzo/gui primitives (longhand props): asset list, asset detail (with assignment timeline), and a global assignments timeline. schema.sql provisions org-scoped Base collections assets + assignments. tsc --noEmit clean; vite build green; renders with zero console errors.
3.8 KiB
3.8 KiB
gear-locker — agent notes
Gear Locker: assign and track company equipment. A real Hanzo app forked from
the canonical hanzo-starter — Vite + React 19 + @hanzo/gui (UI) +
@hanzo/iam (auth) + @hanzo/base (data). Keep it minimal and REAL — every
surface must build and run, no fabricated UI.
One way, decomplected
- Providers (
src/providers.tsx) mount in the canonical order every Hanzo surface ships:GuiProvider→IamProvider→BaseProvider.BaseProvidergets aBaseClientcarrying the IAM access token; it is rebuilt when the token changes (src/lib/base.tsbaseAs). That single seam is what makes everyuseQuery/useMutationorg-scoped to the signed-in user. This stack is IDENTICAL to the starter — do not touch it. - Env is one place (
src/env.ts), read fromimport.meta.env.VITE_*. - Domain is one place (
src/lib/model.ts): theAsset/Assignmenttypes, the status vocabulary + colors, and pure helpers. Keep it in lockstep withschema.sql. - Design is one place (
src/lib/theme.tspalette +src/ui/atoms.tsxreusable compositions). UI is@hanzo/guiprimitives only — no second kit, no Tailwind. - Home owns the data.
src/views/home.tsxruns the two Base queries and the summary counts, and passes onereload()down;assets.tsx(list + detail) andassignments.tsx(timeline) are pure views over that snapshot.
Gotchas (do not regress)
@hanzo/guiunder Vite needs three things invite.config.ts(it is the Tamagui line): (1) aliasreact-native→react-native-web, (2)defineprocess.env.TAMAGUI_TARGET/NODE_ENV/__DEV__, (3)dedupereact/react-dom/react-native-web. No Tamagui compiler, noone, no Expo.@hanzo/guiprops are Tamagui LONGHAND with this v5 config:alignItems/justifyContent/backgroundColor/padding/alignSelf/borderRadius/textAlign— NOT theitems/justify/bg/p/self/rounded/textshorthands. Shorthands pass at runtime but FAILtsc.- No
animationprop — this config registers no animation driver, soanimation=failstsc. UsehoverStyle/pressStylefor interaction (they apply instantly). Buttonomits textcolor/fontWeightin this config. The app's colored actions go through the ONEBtnatom (src/ui/atoms.tsx) — XStack + Text, still 100% gui primitives. Don't reintroduce styled<Button color=…>.InputplaceholderTextColoronly accepts ColorTokens, not hex strings — leave it unset (the theme default is already muted).color/backgroundColor/borderColorDO accept hex.- PKCE storage is
localStorage(not sessionStorage) so the verifier/state survive the round-trip to hanzo.id. schema.sqlis the data contract.assets+assignmentsare thedatabaseSchemaDDL the deploy translates into Base collections (provisionBaseFromDDL). Keep it in lockstep withsrc/lib/model.ts.
Deploy contract (Hanzo Cloud) — IDENTICAL to the starter
- Static SPA:
npm run build→dist/, served at<slug>.hanzo.appfrom object storage. No server process. - On publish,
schema.sql→provisionBaseFromDDLcreates the collections (org-scoped, IAM-native, rule@request.auth.org_id = org). Runtime read/write is browser →VITE_HANZO_BASE_URLwith the IAM token. - IAM redirect registration is the one external requirement: the IAM client
(
VITE_HANZO_CLIENT_ID, defaulthanzo-app) must allow this origin's/auth/callback(ahttps://*.hanzo.app/auth/callbackwildcard, or a dedicatedgear-lockerclient).
Build
CI (.github/workflows/ci.yml) runs npm ci && npm run typecheck && npm run build — build-verification only, NEVER a container image (Hanzo Cloud owns
deploys; do not build images locally).