Wire up NextAuth v5 with @auth/pg-adapter, JWT sessions (edge-friendly),
and a dev Credentials provider for local testing without Google OAuth.
Stack
- next-auth@5.0.0-beta.31, @auth/pg-adapter@1.11.2, @types/pg
- Google OAuth provider via GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET
(falls back to AUTH_GOOGLE_ID / AUTH_GOOGLE_SECRET)
- Postgres adapter wired to a single pg.Pool in src/lib/db.ts style —
reads DATABASE_URL with SUPABASE_DB_URL / POSTGRES_URL fallbacks
- JWT session strategy (edge-safe) so the proxy can verify sessions
without a DB round-trip
Files
- src/auth.config.ts edge-safe config (Google + authorized cb)
- src/lib/auth.ts server config (adapter + dev Credentials)
- src/proxy.ts Next.js 16 proxy (was middleware.ts)
- src/app/api/auth/[...nextauth]/route.ts
catch-all handler
- src/app/protected-example/page.tsx
demo page that renders auth() session
- src/actions/auth-signin.ts
signInWithGoogle, signInWithDev,
signOutAction server actions
- src/app/login/LoginClient.tsx
added "Sign in with Google" + dev form
- supabase/migrations/204_authjs_tables.sql
users / accounts / sessions /
verification_token schema (UUID-keyed)
- .env.example AUTH_SECRET, AUTH_URL, GOOGLE_CLIENT_*,
DATABASE_URL, ALLOW_DEV_LOGIN
Removed
- src/middleware.ts deleted; Next.js 16 only runs one proxy
(the new src/proxy.ts is canonical)
Routes
- /login, /admin, /admin/*, /protected-example
proxy matcher
- /api/auth/{providers,csrf,signin/<provider>,callback/<provider>,
session,signout}
standard Auth.js endpoints
Local dev
- npm run dev (now runs on port 4000)
- push migration 204 then visit /login
- dev signin works with any non-empty username/password
(hidden when ALLOW_DEV_LOGIN=false)
- Google signin requires real GOOGLE_CLIENT_ID + redirect URI
http://localhost:4000/api/auth/callback/google
Verified
- tsc --noEmit clean
- /admin, /admin/orders, /protected-example → 307 to /login
when unauthenticated
- /api/auth/session returns user after signin
- /protected-example renders session info
- /api/auth/providers returns google + dev-login
Docs
- CLAUDE.md and MEMORY.md updated to reflect the Supabase → Postgres
+ Auth.js v5 pivot
Gradual migration in progress
- src/lib/admin-permissions.ts still uses dev_session / rc_auth_uid;
the admin shell will show 'Access Denied' for Auth.js-only
sessions until each page is flipped over
- @supabase/* packages remain in package.json for the same reason
- production deployment (AUTH_URL=https://, __Secure- cookies) is
out of scope for this pass
- Update supabase/push-migrations.js:
- Detect modern Supabase CLI link state (supabase/.temp/project-ref)
- Prefer `supabase db query --linked --file` (works in this env where direct postgres connections fail with ENOTFOUND/network unreachable)
- Updated docs/comments for `supabase login` + `supabase link --project-ref wnzkhezyhnfzhkhiflrp` workflow
- Add MEMORY.md capturing the Supabase login/link session, tooling changes, migration patches applied, and gotchas
- Patch migrations for current remote schema (column drift, syntax, idempotency, pre-existing tables):
- 091_brand_plan_tier.sql: fix extra paren in get_brand_plan_info
- 145_create_product_images_bucket.sql: allowed_mime_types + DROP POLICY IF EXISTS + safer bucket insert
- 148_public_stops_rpc.sql: quote reserved "time" column in RETURNS TABLE + SELECT
- 200_production_features.sql: add ALTER TABLE for user_activity_logs (originated in 036) so policies/indexes validate
- 201_seed_data.sql: trim demo seeds with outdated column lists (products/stops/etc.); keep only compatible brands insert
- Include 202_fix_admin_create_stop.sql and related stop creation updates (src/actions/stops/create-stop.ts, 147_admin_create_stop_rpcs.sql, ADMIN_CREATE_STOP_FIX.sql)
- Update CLAUDE.md with pointer to MEMORY.md for recent migration work
Applied via the new flow (after supabase login + link): 084, 091, 142–148, 200–202 etc.
Refs: Supabase CLI now linked; use `node supabase/push-migrations.js <prefix>` or `npm run migrate:one NNN`