Skip to content

feat(#754 auth-accounts): unit #9 — auth + accounts + onboarding on TanStack - #771

Merged
hellno merged 2 commits into
mainfrom
hellno/cambridge
Jun 21, 2026
Merged

feat(#754 auth-accounts): unit #9 — auth + accounts + onboarding on TanStack#771
hellno merged 2 commits into
mainfrom
hellno/cambridge

Conversation

@hellno

@hellno hellno commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator

Unit #9 — auth + accounts + onboarding (OAuth write)

Track B of epic #754 (Next.js → TanStack Start on Cloudflare Workers). The critical-path surface-tier unit: it alone unblocks #11#12#13 (cutover). Spec: docs/migration/phase-2-auth-accounts.md.

What it does

Ports the real authentication + accounts + onboarding surfaces onto the TanStack route tree, reusing every shared component verbatim (C1/C3 surgical changes only — next/navigation@/web/lib/navigation, next/link@/web/components/link, drop 'use client'), and wires the worker's OAuth WRITE through the existing phase-1 302 callback (no new auth-write path).

Route Source Placement
/login app/(auth)/login replaces the unit-#5 placeholder; outside _app
/accounts app/(app)/accounts child of the _app shell
/welcome/{new,connect,success} app/(auth)/welcome/* under a faithful _auth pathless layout (= port of app/(auth)/layout.tsx)
/auth/auth-code-error app/auth/auth-code-error the 302 callback's error landing

The hard part — G1 (worker-init crash)

The auth/accounts routes are the first eager, ungated importers of @farcaster/hub-web's module-scope test factory (Factory.build()@noble/hashes randomBytes). Rollup hoisted that factory into the eager worker-entry chunk, so every route 500'd at init with Disallowed operation called within global scope … generating random values (even /api/health). Earlier units only reached it through SSR-gated routes (feeds hydrate gate) or lazily-chunked components, where it stays in a lazy chunk and only runs in the browser.

Fix: stub the two client-only route pages (AccountsPage, WelcomeConnectPage — both SSR-gated) in the workerd ssr env via ssrClientOnlyModules, and mount /welcome/new's CreateAccountPage via dynamic(ssr:false). This confines the factory to lazy chunks (random-gen is fine in the browser). Root-caused via bundle bisection; rationale documented in vite.config.mts + the spec's G1.

The one allowed shared-file edit

src/common/helpers/rainbowkit.tsx ALCHEMY key made host-agnostic:
(import.meta as any).env?.VITE_ALCHEMY_API_KEY ?? process.env.NEXT_PUBLIC_ALCHEMY_API_KEY — Vite inlines VITE_* (RPC works); the ?. keeps the Next/webpack runtime (no import.meta.env) from throwing; as any keeps the root-tsconfig typecheck green. + define/​.env.local.example entries. (Clears the strategy.md deferred item.)

Green / verified

  • pnpm web:build 0 · pnpm web:typecheck 0 · live pnpm typecheck 0 · pnpm test 150/150
  • web:deploy:dry-run worker bundle 2317.73 KiB gzip (< 3 MB; +24 KiB over Add support for user reactions to posts #6)
  • Canary (real workerd, wrangler dev): /login, /accounts, /welcome/{new,connect,success}, /auth/auth-code-error, /api/health, /feeds all SSR 200 with zero Disallowed operation throws — both with and without secrets (forkability bar met).
  • No client-bundle secret leak (NEYNAR key name absent; secrets define-pinned to undefined).
  • Tier-1 review: adversarial multi-dimension workflow (ssr-bundle / parity / conventions / correctness / auth-write), 0 confirmed findings.

Not verified here (needs real secrets)

The OAuth WRITE round-trip (login through the worker → 302 sets chunked sb-* cookies → getUserFn returns a real UUID) and wallet RPC success need real Supabase secrets + a configured OAuth provider + VITE_ALCHEMY_API_KEY at build — see the canary DoD in the spec.

Boundaries honored

No changes to app/, pages/, next.config.mjs, vercel.json, src/globals.css, or any shared src/ file except rainbowkit.tsx. The live Next/Vercel app is untouched.

Do not merge — leave for review. (Tier-2 codex integration review runs at the surface-tier boundary after #6#9 all land.)

…anStack

Port the real authentication, accounts-management, and onboarding surfaces onto
the TanStack route tree (reusing every shared component verbatim — C1/C3 surgical
changes only), and wire the worker's OAuth WRITE through the existing phase-1 302
callback (no new auth-write path).

Surfaces: /login (replaces #5 placeholder), /accounts (inside the _app shell),
/welcome/{new,connect,success} + /auth/auth-code-error (under a faithful _auth
pathless layout).

G1 (load-bearing): the auth/accounts routes are the first eager, ungated importers
of @farcaster/hub-web's module-scope test factory (Factory.build()->randomBytes),
which Rollup hoisted into the eager worker-entry chunk -> 'Disallowed operation in
global scope' crashed worker init for EVERY route. Fixed by stubbing the two
client-only route pages (AccountsPage/WelcomeConnectPage) in the ssr env and
mounting /welcome/new's CreateAccountPage via dynamic(ssr:false), confining the
factory to lazy chunks that only run in the browser.

Shared-file edit (the one allowed): rainbowkit.tsx ALCHEMY key made host-agnostic
((import.meta as any).env?.VITE_ALCHEMY_API_KEY ?? process.env.NEXT_PUBLIC_*) so
Vite RPC works while the Next build stays green; + define/.env.local.example entry.

Green: web:build 0, web:typecheck 0, live typecheck 0, test 150/150, worker bundle
2317.73 KiB gzip (<3MB). Canary: all 6 routes + /api/health + /feeds SSR 200 on
workerd with zero global-scope throws, with and without secrets.
@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
herocast Ready Ready Preview Jun 21, 2026 11:40am

@hellno
hellno merged commit 17d51ad into main Jun 21, 2026
2 checks passed
@hellno
hellno deleted the hellno/cambridge branch June 21, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant