NEXT_PUBLIC_GARY_SKIP_AUTH flag bypasses Supabase login for dev/demo

foolish-bandit added a build-time flag that lets the frontend run as a fake demo user without a real Supabase session. Set `NEXT_PUBLIC_GARY_SKIP_AUTH=true` at build time and `AuthContext` skips the auth flow entirely, seeding a fixed demo identity. An amber banner at the top of the protected layout makes the mode visible.

chat-uiinfrastructure

The implementation is clean for what it is. AuthContext uses lazy useState initializers so the bypass doesn't require a setState inside the effect - the demo user (id: "00000000-0000-0000-0000-000000000000", email demo@gary.local) and authLoading: false are the initial values when SKIP_AUTH is true. The Supabase auth-state-change subscription short-circuits after a one-time console.warn. signOut becomes a no-op. The context exposes isAuthBypassed: boolean so downstream components can react.

The banner - an amber strip reading "Dev auth bypass enabled" rendered by DevAuthBanner - is on by default whenever the flag is active. It uses role="status" and aria-live="polite".

Backend calls still 401 while the bypass is on. There's no Supabase JWT, so any request that requires one will fail. foolish-bandit documents this explicitly in the console warning and in .env.local.example. The intended use is UI inspection, not end-to-end testing.

One thing to watch: NEXT_PUBLIC_* is baked into the client bundle at OpenNext build time. The flag cannot be flipped at runtime on a deployed Worker. foolish-bandit calls this out directly - this should live in a separate preview Worker, not the production deployment. But the gating is a single env-var string comparison, with no NODE_ENV !== "production" guard. Anyone deploying this to production with a misconfigured build pipeline would get an open frontend with no auth challenge.

So what Useful as a local development convenience or for a demo Worker. Before importing, add a `NODE_ENV !== "production"` guard so the bypass cannot be accidentally enabled in a production bundle. The banner and `isAuthBypassed` context flag are good ideas regardless.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

1 commit from foolish-bandit/gary, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
0b9ad4db Add NEXT_PUBLIC_GARY_SKIP_AUTH dev/demo bypass Claude 2026-05-07 ↗ GitHub
commit body
Lets us inspect the app without going through Supabase login during
development and on demo deploys. Frontend-only.

When NEXT_PUBLIC_GARY_SKIP_AUTH=true:
- AuthContext initializes with a fake demo user
  ({ id: "00000000-...-000", email: "demo@gary.local" }) via lazy
  useState, so isAuthenticated is true immediately.
- The Supabase session check + auth-state-change subscription are
  skipped (the useEffect bails out after a one-time console.warn).
- signOut becomes a no-op so the demo session stays stable.
- A slim amber "Dev auth bypass enabled" banner renders at the top
  of the (pages) layout via the new DevAuthBanner component.
- The flag is exposed as `isAuthBypassed` on the auth context so
  any consumer can branch on it later.

When the flag is unset or "false":
- useState initializers return null/true, identical to today.
- The effect's bypass branch is dead and the original Supabase
  logic runs unchanged. Login/signup, signOut, and the redirect
  gate in (pages)/layout.tsx are untouched.

Documents the variable in frontend/.env.local.example as
commented-out so normal setups stay on real auth.

No backend changes, no schema changes, no auth contract changes.
Backend calls made while the bypass is on will 401 because no
real Supabase session exists - that's intentional and noted in
the console warning.

https://claude.ai/code/session_019pRkhcGDRKQWHjzAnV5yCL

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-269.md from inside the repo you want the changes in.

⬇ Download capture-thread-269.md