Skip to content

Decide on Supabase publishable key env var naming (publishable vs anon) #573

@BjornMelin

Description

@BjornMelin

Context

Supabase updated their Next.js SSR setup docs to prefer the publishable key and the env var name NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY (in addition to the legacy anon / service_role keys).

This repo currently standardizes on NEXT_PUBLIC_SUPABASE_ANON_KEY (required in the Zod env schema and referenced across code/docs/CI). We need to decide whether to:

  1. Keep the legacy env var name (and document that the value may be a publishable key), or
  2. Rename the env var to match Supabase’s current docs, or
  3. Support both names temporarily and deprecate one.

This is a decision + migration issue: it affects developer onboarding, CI stubs, docs/runbooks, and deployment configuration.

External references (primary)

Internal references

  • Phase 1 remediation: docs/review/2025-12-15/implementation-guide.md (AI-001 context / Supabase SSR alignment)
  • Review log: docs/review/2025-12-15/review-log.md (AI-001 and doc drift note)

Current repo state (evidence)

The repo requires NEXT_PUBLIC_SUPABASE_ANON_KEY today:

  • Schema: src/domain/schemas/env.tsNEXT_PUBLIC_SUPABASE_ANON_KEY is required.
  • Client env reader: src/lib/env/client.ts reads/validates NEXT_PUBLIC_SUPABASE_ANON_KEY.
  • Supabase browser client: src/lib/supabase/client.ts uses getClientEnvVar("NEXT_PUBLIC_SUPABASE_ANON_KEY").
  • CI build stubs: .github/workflows/ci.yml sets NEXT_PUBLIC_SUPABASE_ANON_KEY for pnpm build.

Docs/runbooks also refer to anon key naming:

  • README.md
  • docs/development/core/env-setup.md
  • docs/development/core/quick-start.md
  • docs/operations/deployment-guide.md
  • docs/operations/operators-reference.md
  • docs/operations/runbooks/database-ops.md
  • docs/specs/active/0021-spec-supabase-webhooks-vercel-consolidation.md

Automation/config references:

  • playwright.config.ts
  • scripts/ops.ts
  • Makefile uses SUPABASE_ANON_KEY (non-Next var) for certain local tasks.

You can re-audit quickly with:

rg -n "NEXT_PUBLIC_SUPABASE_(ANON_KEY|PUBLISHABLE_KEY)" -S .

Decision options

Option A — Keep NEXT_PUBLIC_SUPABASE_ANON_KEY (status quo naming)

Keep the existing env var name and update docs to clarify:

  • The value can be either a legacy anon key or the new sb_publishable_… key, depending on what Supabase provides.

Pros:

  • No breaking env var rename for existing deployments/local env.
  • Minimal code churn.

Cons:

  • Diverges from upstream Supabase docs and Supabase “Connect” dialog env blocks.
  • Onboarding friction: new contributors will likely paste NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY and hit env validation failures.

Option B — Adopt NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY (rename everywhere)

Update schemas, code, docs, CI, and runbooks to use NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY.

Pros:

  • Matches current Supabase docs and Supabase “Connect” dialog.
  • Reduces onboarding confusion.

Cons:

  • Breaking change for env var naming; requires coordinated migration across:
    • local .env*
    • Vercel/GitHub Actions secrets
    • any external deploy tooling

Option C — Support both names temporarily, then remove legacy

Implement a compatibility layer:

  • prefer NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
  • fall back to NEXT_PUBLIC_SUPABASE_ANON_KEY
  • log/telemetry warning when legacy is used (server-only)
  • update docs to prefer publishable key
  • remove legacy after an agreed window

Pros:

  • Smooth migration path; reduces breakage.

Cons:

  • Adds temporary complexity and deprecation cleanup work.
  • Needs careful handling because NEXT_PUBLIC_* values are inlined at build time.

Research checklist (what to confirm)

  • Confirm the Supabase “Creating a client” docs currently recommend NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY for Next.js, and capture the relevant snippet/semantics (is it required vs recommended?).
  • Confirm whether publishable key replaces anon key 1:1 for client-side access (privileges/behavior), and whether any tooling still expects “anon”.
  • Confirm how Supabase recommends handling server-only privileged operations (service role / secret keys) during the transition.
  • Confirm whether Supabase “Connect” dialog for Next.js emits env vars using publishable key naming.
  • Confirm whether any of our internal tooling assumes the key string format (e.g., regex/length validation) — currently it’s a min(1) check.

If anything is unclear, mark findings as UNVERIFIED and link the primary source.

Proposed implementation tasks (after decision)

  • Update env schema(s): src/domain/schemas/env.ts (+ tests under src/lib/env/__tests__/*).
  • Update client env reader: src/lib/env/client.ts.
  • Update Supabase client creation: src/lib/supabase/client.ts and any server factories that read the key.
  • Update build/test stubs:
    • .github/workflows/ci.yml (build env stub)
    • playwright.config.ts
    • src/test/helpers/env.ts, src/test/setup-node.ts
  • Update operator docs + runbooks:
    • README.md, docs/development/core/*, docs/operations/*, docs/specs/active/0021-*
  • Update any scripts/ops + Makefile references:
    • scripts/ops.ts
    • Makefile (if applicable / align naming)
  • Update any .env.example / onboarding docs if present.
  • Verify:
    • pnpm biome:fix
    • pnpm type-check
    • pnpm test:affected
    • pnpm build (with safe stubs)

Acceptance criteria

  • A clear decision is recorded (issue conclusion + any required doc/ADR updates).
  • Fresh setup instructions match Supabase’s current docs (or explicitly explain why we differ).
  • CI builds succeed with the chosen env var naming.
  • No secrets are introduced into client bundles beyond NEXT_PUBLIC_*.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions