mirror of
https://github.com/hanzo-apps/meetup.git
synced 2026-10-30 19:11:14 +00:00
Real Hanzo app forked from hanzo-starter. Vite + React 19 + @hanzo/gui + @hanzo/iam (PKCE) + @hanzo/base. Three views: public event landing, Discover (RSVP + attendee list), Host dashboard. events + rsvps Base collections (org-scoped). tsc + vite build green.
4.0 KiB
4.0 KiB
meetup-gather — agent notes
Meetup Gather: warm community meetup pages with RSVPs. 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 builds and runs, no fabricated UI.
What it is
Three views, one static SPA:
- Event landing (
views/landing.tsx) — public, pre-auth. A featured meetup page (host, details, a live "who's coming" avatar wall) + nearby meetups. Every CTA callslogin(). - Discover (
views/discover.tsx) — signed in, RSVP + attendee list. Reads everyevents+rsvpsrow in your org, shows who's going, writes your own going/maybe/cant (one RSVP row per person per event: update if it exists, else create). - Host (
views/host.tsx) — signed in, dashboard. Publishes an event (stamped with you ashost) and rolls up its RSVPs.
views/home.tsx is the signed-in shell that tab-switches Discover/Host and
threads me (your display name) down. app.tsx gates: /auth/callback →
Callback, signed-out → Landing, signed-in → Home.
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 makes everyuseQuery/useMutationorg-scoped to the signed-in user. Gather fixes the light theme for its warm look. - Env is one place (
src/env.ts); color is one place (src/theme.ts); the data shape is one place (src/lib/model.ts, lockstep withschema.sql). - UI is one system —
@hanzo/guiprimitives only (no second kit, no Tailwind). Shared presentational parts live inviews/parts.tsx.
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:alignItems/justifyContent/backgroundColor/padding/alignSelf/borderRadius/textAlign— NOT theitems/justify/bg/p/self/rounded/textshorthands. Shorthands pass at runtime but FAILtsc.Buttonis a styled stack, not a text element. It takes stack props (backgroundColor/borderRadius/padding/hoverStyle) but NOTcolor/fontWeight/fontSize— those failtsc. Style the label with a nested<Text>. This is decomplected into the singleTextButtoninparts.tsx; route every button through it.Inputusesvalue/onChangeTextand itsplaceholderTextColorwants aColorTokens, not a hex — so it is left default.- PKCE storage is
localStorage(not sessionStorage) so the verifier/state survive the round-trip to hanzo.id. schema.sqlis the data contract.when/whereare SQL keywords, quoted as identifiers in the DDL; the app reads them as plain fields. Keep it in lockstep withsrc/lib/model.ts.
Deploy contract (Hanzo Cloud)
- Static SPA:
npm run build→dist/, served at<slug>.hanzo.appfrom object storage. No server process. - On publish,
schema.sql→provisionBaseFromDDLcreates theevents+rsvpscollections (org-scoped, 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(https://*.hanzo.app/auth/callbackwildcard, or a per-apphanzo-meetup-gatherclient).
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).