mirror of
https://github.com/hanzo-apps/waitlist-launchpad.git
synced 2026-10-30 19:00:50 +00:00
4.4 KiB
4.4 KiB
waitlist-launchpad — agent notes
A launch landing page on the canonical Hanzo app stack (forked from
hanzo-apps/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, no fabricated metrics.
What this app is
- Landing (signed out,
views/landing.tsx) — dark, motion-rich hero: a drifting aurora, a live countdown toLAUNCH_AT, an easing signup counter, and ONE call to action (email + button). Submitting stashes the email (stashPending) and starts Hanzo PKCE. - Admin (signed in,
views/admin.tsx) — running total (easing counter) + countdown, folds in the claimed email viatakePending(read-and-clear, so it creates exactly one row under StrictMode), then lists / filters / removes the org-scopedsignups. - Motion is real, not a driver. The v5 config ships no animation driver, so
motion is: a 1s
setInterval(countdown),requestAnimationFrame(counter count-up), and CSS keyframes inindex.htmlapplied via theclassNameprop (aurora drift, entrance, CTA glow).prefers-reduced-motiondisables them.
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. - Env is one place (
src/env.ts), read fromimport.meta.env.VITE_*(addsLAUNCH_AT). - Domain logic is one place (
src/lib/waitlist.ts) — pure, no React/gui: copy,emailValid, countdown math (splitDuration/pad2), the pending-email handoff,formatJoined, and theSignuprecord type. - UI is one system —
@hanzo/guiprimitives only (no second kit, no Tailwind). Landing + admin are the two views.
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. Do NOT add@hanzogui/vite-plugin— 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.classNameis the one web escape hatch for effects Tamagui props don't cover (blur, keyframe motion). It typechecks on gui primitives and is how the motion classes attach. Keep the keyframes inindex.html.- 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), org-scoped by@request.auth.org_id = org. Keep it in lockstep with the 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_HANZO_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).
Proven
npm run typecheck clean · npm run build (tsc + vite) → dist/. Renders under
Vite; the landing countdown ticks and the CTA runs a real PKCE S256 redirect to
hanzo.id.
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).