mirror of
https://github.com/hanzo-apps/band-setlist.git
synced 2026-10-30 19:25:28 +00:00
Gig-poster-brutalist band gig log: browse upcoming/past shows, open a show to read its ordered setlist, and sign in to log shows + build sets. - UI: 100% @hanzo/gui primitives (Tamagui longhand), no Tailwind - Auth: @hanzo/iam PKCE against hanzo.id (VITE_IAM_CLIENT_ID) - Data: @hanzo/base org-scoped shows / songs / setlist from schema.sql - Forked from hanzo-starter; identical provider stack, vite.config, deploy contract
4.0 KiB
4.0 KiB
band-setlist — agent notes
A real Hanzo app: a band's public show & setlist tracker. 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.
The app
- Design — gig-poster brutalism: black-on-acid, oversized all-caps venue
names, torn-ticket dividers, chunky monospaced dates/numerals. Colors are
literal (
src/theme.tsx), not theme tokens, so the flyer look is exact. - Views (
src/views/):shows.tsx— the gig board, upcoming vs. played, ticket-stub cards.setlist.tsx— one show's ordered stage sheet + encore + total runtime.log.tsx— log a show, keep the song book, build/order a set.signed-out.tsx— the public pre-auth landing (the honest thumbnail).
- Data (
schema.sql→ Base collections):shows(venue, city, date, is_upcoming),songs(title, duration),setlist(show_id, song_id, position, encore).position(not the reserved wordorder) sequences a set.
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 band. - Env is one place (
src/env.ts), read fromimport.meta.env.VITE_*. The IAM client id isimport.meta.env.VITE_IAM_CLIENT_ID(fallbackhanzo-app). - UI is one system —
@hanzo/guiprimitives only (no second kit, no Tailwind). Every button is the onePosterButtoninsrc/theme.tsx.
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.Buttontakes no top-levelcolor. Put the label in aTextchild and color that (this is exactly whyPosterButtonexists).ButtonusesonPress;Inputusesvalue/onChangeTextand wants atheme(we settheme="light") rather than a rawplaceholderTextColorhex.- 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/model.ts+src/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. - On publish,
schema.sql→provisionBaseFromDDLcreates the collections (org-scoped, IAM-native). Runtime read/write is browser →VITE_HANZO_BASE_URLwith the IAM token. - IAM redirect registration is the one external requirement: the IAM client
(
VITE_IAM_CLIENT_ID, defaulthanzo-app) must allow this origin's/auth/callback. Production needs ahttps://*.hanzo.app/auth/callbackwildcard on the shared client (or a per-apphanzo-<app>client).
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).