Guide Lovable · Bolt

Where do I put the Supabase service role key vs the anon key in Lovable or Bolt?

Short answer

The public anon or publishable key may live in the browser app. The service role or secret key belongs only on a server you control (for example a Supabase Edge Function or secret store), because that secret key bypasses row rules (RLS). If the secret key is in frontend code, env vars that ship to the browser, or a public repo, treat that as a leak path and rotate (see the related secret-key guide).

Plain map: which key where

Pick the key by where the code runs:

  • Browser, Lovable client, or Bolt client code: use the anon key or the publishable key (sb_publishable_…). Anyone can read it; what it can open depends on your access rules (RLS).
  • Edge Function, webhook, cron, or paid admin job on a server you control: use the secret key (sb_secret_…) or the legacy service_role key. That elevated key bypasses row rules (RLS), so it stays server-side.
  • Stripe sk_live and similar payment secrets follow the same "server only" rule: they belong in a secret store or backend function, not in client bundles.

Legacy names still show up in older tutorials: anon maps to publishable; service_role maps to secret. The placement rule is the same.

How Lovable and Bolt hold secrets

On Lovable with your own Supabase project, secrets for external APIs are stored in the Supabase project secret store for Edge Functions. Lovable's docs say those secrets "never appear in your app's code or repository."

Bolt's project security audit checks that private keys and passwords are not stored in your project's code or sent to visitors' browsers. Lovable's Deep scan also looks for leaked secrets and credentials as a supporting check.

You should not paste a service_role or secret key into a VITE_, NEXT_PUBLIC_, or client .env value that the builder bundles for the browser. Those prefixes are how frameworks ship values to the client.

Two-minute self-check (no SQL)

  1. Open the live site.
  2. View source or the site's JavaScript files.
  3. Search for service_role, sb_secret_, and long eyJ JWT-looking blobs next to elevated-key names.

Finding the public anon or publishable key alone is expected. Finding service_role or sb_secret_ in client code is not. Related guides explain why the public anon key in the browser is fine to leave public, and what to do when a secret key is already exposed.

If you find a secret in the client

Stop. Rotate per My Supabase secret key is in my frontend. What now?, redeploy, then re-check the live site. Do not only delete the line and keep the old key live. The old value still works until you retire it in the Supabase dashboard.

After keys look right

A correct key map does not prove row access rules are tight. Still run signed-out and two-account checks (see Is my Lovable or Bolt app leaking data? and How to test your Lovable or Bolt app before real users). User B should not see user A's private rows even when only the public key is in the browser.

What you can DIY vs when to get a second look

You can map which key belongs in the client, keep secrets in Edge Function or server stores, search the live page source, and rotate if a secret slipped into the frontend.

Stop guessing if you cannot tell whether a value in your builder secrets is the public anon key or the elevated secret key, or you still worry private tables are open after a key cleanup. That is the natural handoff to a read-only second look.

Want a second pair of eyes?

If you cannot tell whether a key in your builder secrets is the public anon key or the elevated secret key, or you still worry private tables are open after a key cleanup, the $49 Database Check is a read-only second look: you run our script and send the results. No passwords, no keys, no login to your account. We change nothing. AI agents run the checks and a human engineer reviews and approves every report. Not a penetration test, a security guarantee or a compliance certification.

See plans and prices

Sources