Uh oh!
There was an error while loading. Please reload this page.
feat(dev): local Supabase dev environment + Google-only local auth - #372
Conversation
Deploying with |
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs | frontend-staging | 6765f49 | Commit Preview URL Branch Preview URL | Jul 22 2026, 04:09 AM |
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (7)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughThe PR adds a local Supabase development stack, makes migrations replay-safe, adds catalog synchronization and local setup scripts, enables local OAuth approval, and removes frontend mock local mode in favor of real backend and Supabase integrations. ChangesLocal Supabase development
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Browser
participant Next.js
participant Backend
participant Supabase
Browser->>Next.js: Request API or sign-in route
Next.js->>Backend: Proxy API request
Backend->>Supabase: Read or update application data
Supabase-->>Backend: Return data or auth state
Backend-->>Next.js: Return response
Next.js-->>Browser: Render real backend result
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
AndresL230
commented
Jul 21, 2026
🖥️ Running this locallyThis PR lets you run the whole app against a local Supabase (rootless Podman) instead of the live staging DB. Full guide: One-time setup# 1. Podman + its rootless API socket (Arch/CachyOS shown; use your distro's pkg mgr)
sudo pacman -S --needed podman
systemctl --user enable --now podman.socket
set -Ux DOCKER_HOST "unix:///run/user/"(id -u)"/podman/podman.sock"# fish (bash/zsh: export in your rc)# 2. Supabase CLI (AUR here; also: brew install supabase/tap/supabase, scoop, etc.)
paru -S supabase-bin
# 3. Env — fixed local-only keys are prefilled; just add your Gemini key
cp backend/.env.local.example backend/.env # then fill GEMINI_API_KEY
cp frontend/.env.local.example frontend/.env.localBring the stack upsupabase start # Postgres + PostgREST + Storage + Studio, in Podman
scripts/local-up.sh # apply migrations → create storage buckets → seed demo data (idempotent)# optional: load the real ~8k-course catalog (read-only pull from staging)cd backend && python -m db.seed_local_catalogRun it + sign incd backend && python main.py # :5000cd frontend && npm run dev # :3000Open http://localhost:3000 and sign in with Google — the first local sign-in is auto-approved (no Handy
|
…l auth Run the full app against a containerized Supabase (rootless Podman) instead of the live staging DB, and let teammates reproduce it with one script. - supabase/config.toml — local stack; analytics/edge-runtime disabled, auto_expose_new_tables=true (required so migration-created tables are reachable by the Data API roles, matching hosted Supabase). - scripts/local-up.sh (idempotent bring-up) + scripts/local-db-reset.sh (clean slate): migrate -> reload PostgREST schema -> seed. - backend/.env.local.example + frontend/.env.local.example — turnkey local env with fixed, local-only keys (safe to commit); un-ignored via !.env.local.example. - backend/db/seed_local_catalog.py — pull the real ~8k-course catalog from a remote Supabase over its REST API (read-only source; unencrypted catalog only). - docs/local-supabase.md — setup, run loop, sign-in, troubleshooting. - migrations 0021_gradebook / 0021_gradebook_curve / 0027_gradescope — IF NOT EXISTS and user_courses->enrollments retarget guards so the chain replays cleanly from an empty DB. These are no-ops on already-migrated databases (staging/prod unaffected). - routes/auth.py — IS_LOCAL auto-approve so a first local Google sign-in skips the /pending wall. Strictly APP_ENV-gated; staging/prod keep the real approval gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The app now runs against a real local Supabase backend, so the mock-data path (lib/localData.ts + all IS_LOCAL_MODE branches) is dead weight and a footgun — having two ways to "run locally" masked real backend behavior. Deletes src/lib/localData.ts and removes every IS_LOCAL_MODE branch across api.ts, UserContext, SignInModal (the local-user-001 dev shortcut), Admin/Social/Learn, ReportIssueFlow, useAchievementUnlockWatcher, and the middleware short-circuit + its test stub. The real backend-fetch path is now the sole behavior. tsc --noEmit clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- SignInModal: drop the `if (!API_URL)` guard so an empty (same-origin) NEXT_PUBLIC_API_URL no longer aborts local Google sign-in as "not configured" — this was silently blocking the PR's whole point. - Storage buckets: create cosmetic-assets / issues-media-files / avatars + a permissive local RLS policy in the bring-up scripts, so cosmetic and issue uploads work in local dev after the mock removal (buckets weren't created locally). - 0027_gradescope: guard the gradescope_course_links DROP on the old `user_id` shape and make the CREATE `IF NOT EXISTS`, so it can't CASCADE-delete data on a ledger-less replay; 0021_gradebook_curve: document the intentional redundant CHECK. - seed_local_catalog: paginate until an empty page (robust to source max-rows caps) and route local writes through db.connection.table() instead of a raw httpx client (httpx kept only for the unavoidable cross-project source read). - auth.py: fold is_approved into the new-user insert (drops the redundant UPDATE). - Extract the duplicated migrate -> reload -> seed block into scripts/lib/local-common.sh. - Docs: remove stale NEXT_PUBLIC_LOCAL_MODE references from frontend/README.md and frontend/.env.example, and the dead /api/auth/dev-login comment in .env.local.example. Verified: fresh replay still "Applied 33 migration(s)", buckets created, seed + catalog pull succeed, decryption + Google redirect healthy, tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
e2d9666 to
73e989bCompare- auth.py: gate the local auto-approve on APP_ENV=="local" instead of the broader IS_LOCAL (which includes APP_ENV=test) — it was auto-approving new users under the test suite and failing the #285 approval-gate regression. All 7 auth-stub tests pass. - 0027_gradescope: add IF NOT EXISTS to idx_gradescope_links_enrollment, and make the old-shape gradescope_course_links DROP RAISE loudly if the table holds rows rather than silently CASCADE-deleting them (the fresh-replay path is empty, so still lossless). - 0021_gradebook: make gradebook_categories (+ its index) and the assignments indexes idempotent (IF NOT EXISTS) so a ledger-less re-run doesn't abort mid-chain. - scripts/lib/local-common.sh: fail fast with a clear message if backend/venv is missing. - Setup docs/messaging: document creating backend/venv, and clarify that Google OAuth creds are required to sign in locally (optional only to bring the stack up) — local-up.sh banner, .env.local.example, docs/local-supabase.md. Re-verified: Applied 34 migration(s) from empty, storage buckets + seed + catalog pull, decryption, and the Google redirect all healthy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The build-command config for the frontend-staging Worker was fixed (npm run cf:build restored; the broken 'wrangler deploy --env staging' skipped the OpenNext build). Empty commit to re-run CI with the fix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
What
A one-command local Supabase dev environment (rootless Podman) so the app runs full-stack against a local DB instead of the live staging DB — and teammates can reproduce it.
Contents
supabase/config.toml— local stack; analytics/edge-runtime disabled,auto_expose_new_tables=true(so migration-created tables are reachable by the Data API roles, matching hosted Supabase).scripts/local-up.sh(idempotent bring-up) +scripts/local-db-reset.sh(clean slate): migrate → reload PostgREST → seed.backend/.env.local.example+frontend/.env.local.example— turnkey local env with fixed, local-only keys (safe to commit).backend/db/seed_local_catalog.py— pulls the real ~8k-course catalog from a remote Supabase over its REST API (read-only source; unencrypted catalog only).docs/local-supabase.md— setup, run loop, sign-in, troubleshooting.0021_gradebook,0021_gradebook_curve,0027_gradescope) —IF NOT EXISTS/user_courses→enrollmentsretargets so the chain replays cleanly from an empty DB. No-ops on already-migrated databases (staging/prod unaffected).routes/auth.pyIS_LOCALauto-approve — a first local Google sign-in skips the/pendingwall. StrictlyAPP_ENV-gated; prod keeps the real approval gate.lib/localData.ts+ everyIS_LOCAL_MODEbranch (single source of truth;tscclean).Teammate setup
Full guide:
docs/local-supabase.md.Notes
main(was originally cut fromfeat/streaming-tutor). The frontend mock removal and theauth.pyauto-approve were re-resolved against main's versions during the rebase; conflicts were only inapi.ts(re-stripped) andlocalData.ts(deleted).Applied 34 migration(s)including main's0031, then storage buckets + seed + catalog pull, decryption, and the Google redirect all healthy;tscclean.Issues
IS_LOCALauto-approve + empty email allowlist).🤖 Generated with Claude Code
Summary by CodeRabbit