mirror of
https://github.com/hanzo-apps/shop-storefront.git
synced 2026-10-30 19:05:08 +00:00
MONO — a monochrome shop of design objects: storefront grid, product detail, and cart over @hanzo/gui (UI) + @hanzo/iam (PKCE auth) + @hanzo/base (org-scoped data). Forked from hanzo-starter with an identical provider stack, vite config, auth, and deploy contract. - schema.sql: products + cart_items collections, org-scoped - generated monochrome studio imagery from the design system (no asset deps) - checkout stub clears the cart (wire to Hanzo Commerce for real orders)
3.5 KiB
3.5 KiB
shop-storefront — agent notes
A minimal editorial product storefront on the canonical Hanzo stack — the
hanzo-starter provider spine (Vite + React 19 + @hanzo/gui + @hanzo/iam +
@hanzo/base) applied to a real shop. Keep it minimal and REAL — every surface
must build and run, no fabricated UI.
The app
MONO — a monochrome shop of design objects. Three views over two Base collections:
- Storefront grid (
src/views/storefront.tsx) — the catalogue; a fresh org is empty and can seed the demo collection into Base. - Product detail (
src/views/product.tsx) — studio image, editorial spec, a stock-bounded quantity stepper, add-to-cart. - Cart (
src/views/cart.tsx) — lines, order summary, and a checkout stub that clears the cart (wire it to Hanzo Commerce for real orders).
src/views/home.tsx is the signed-in shell: it owns the products + cart_items
queries and the mutations, and routes shop → product → cart. src/views/signed-out.tsx
is the public landing (hero + faithful preview of the same cards).
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. - Domain is one place (
src/lib/shop.ts) — row types, the demo catalogue, price/index formatting, the deterministic monochrome art picks, and cart math. - Env is one place (
src/env.ts), read fromimport.meta.env.VITE_*. - UI is one system —
@hanzo/guiprimitives only (no second kit, no Tailwind). Product imagery is generated (src/views/product-image.tsx): a paper ground + one ink mark + the editorial index, derived from the product name, so an image-less catalogue still looks art-directed. A realproducts.imageURL wins when present.
Gotchas (do not regress)
@hanzo/guiunder Vite needs three things invite.config.ts(it is the Tamagui line; the in-browser builder runtime can't do this, which is the whole reason this ships as a real repo): (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 — the optimizer is a perf pass, not a correctness one.@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.ButtonusesonPress;Inputusesvalue/onChangeText;Imageusessrc.- PKCE storage is
localStorage(not sessionStorage) so the verifier/state survive the round-trip to hanzo.id. schema.sqlis the data contract. It is thedatabaseSchemaDDL the deploy translates into Base collections (provisionBaseFromDDL). Keep it in lockstep withsrc/lib/shop.tsand the three views.
Deploy contract (Hanzo Cloud)
- Static SPA:
npm run build→dist/, served at<slug>.hanzo.appfrom object storage (the*.hanzo.apppublished-sites edge). No server process. - Identity is ambient IAM (hanzo.id PKCE);
VITE_HANZO_CLIENT_ID's IAM client must allow this origin's/auth/callback. Data is org-scoped Hanzo Base.