All posts
No-Code & Tools

Lovable Environment Variables vs Secrets: What Goes Where Before Production?

A production-minded guide to separating public configuration from real secrets in Lovable apps before API keys, payments or customer data go live.

Elvis Onunwa17 September 20266 min readLast updated: 17 September 2026
Lovable Environment Variables vs Secrets: What Goes Where Before Production?

TL;DR

  • A variable being stored in an environment file does not automatically make it secret; browser-bundled values are visible to users.
  • Authenticated third-party API credentials should stay server-side and be accessed through an Edge Function or equivalent backend boundary.
  • Preview, staging and production are separate environments; verify required values in the environment that actually serves users.
  • If a real secret has already reached client code or Git history, remove it, rotate it at the provider and redeploy.
On this page⌄

A Lovable app can work perfectly in preview and still be unsafe or broken in production because environment variables and secrets solve different problems.

The practical rule is simple: if the browser needs a value to run, assume a visitor can see it. If possession of a value would let somebody spend money, access private data, impersonate your backend or bypass normal permissions, it belongs behind a server boundary.

That distinction matters before you connect payments, email, AI APIs, storage or customer data to an AI-built product.

The decision: public configuration or secret?

Use this test before deciding where a value belongs.

Value Browser-safe? Where it belongs
Public app URL Usually Client configuration
Supabase project URL Yes Client configuration
Supabase publishable/anon key with correct RLS Yes Client configuration
Feature flag with no security authority Usually Client configuration
OpenAI or other paid API key No Server-side secret
Resend/email provider API key No Server-side secret
Payment secret key or webhook signing secret No Server-side secret
Supabase secret/service-role credential No Server-side secret

The important question is not whether a value is written in .env. It is where that value is consumed.

A frontend build eventually has to send browser-required values to the browser. Renaming a secret or hiding it behind an environment-variable name does not change that boundary.

How Lovable handles authenticated APIs

Lovable’s current integration documentation says authenticated external APIs should use Lovable Cloud secrets and an Edge Function so credentials are not exposed to the client.

That architecture is worth understanding rather than treating it as platform magic:

browser → your server/Edge Function → third-party API

The browser sends the user’s request to code you control. The server-side function reads the credential, calls the external service and returns only the response the user is allowed to receive.

The dangerous version is:

browser + private API key → third-party API

Anyone who can inspect the browser’s JavaScript or network requests may be able to recover that credential.

Supabase keys are a useful example

Not every visible key is a leaked secret.

Supabase’s current environment-variable documentation distinguishes publishable keys from secret keys. Publishable keys are designed for public clients when Row Level Security and authorization policies are correctly configured. Secret keys are backend credentials and can bypass Row Level Security, so they must not be shipped to the browser.

This is why searching a production bundle for the word key and panicking is not enough. You need to classify what authority each credential carries.

A public Supabase key plus weak RLS can still create a serious data problem. The key being public is expected; the missing authorization boundary is the failure.

If you are unsure about that distinction, read Is the Supabase anon key safe to expose?.

Preview working does not prove production is configured

One of the easiest mistakes in AI-assisted development is treating preview as production evidence.

Your preview may have the right secret, test credential, callback URL or connected backend while the published environment does not. The opposite can happen too.

Before launch, make a small configuration inventory:

Check Preview Production
Backend/project ID Verify Verify
Public app URL Verify Verify
Auth redirect URLs Verify Verify
Server secrets Verify names Verify names
Payment mode Test Live when ready
Webhook destination Test endpoint Production endpoint
Email sender/domain Test Verified production sender

Do not copy every development value into production blindly. The goal is parity of required configuration, not necessarily identical credentials.

Supabase also documents that secrets can be environment-specific and, in branching workflows, values set for one branch are not automatically available in another. That is the right mental model for production generally: deployment environments should be explicit, not assumed.

Search the code before adding more secrets

When a production feature says a variable is missing, adding values at random can make the system harder to understand.

First search the repository for how configuration is actually referenced. Look for patterns such as import.meta.env, process.env, Deno.env.get, API client initialization and hard-coded provider keys.

Then classify every referenced value:

  1. Does browser code need it?
  2. Does it grant privileged authority?
  3. Which environment supplies it?
  4. Is the variable name identical in code and configuration?
  5. Does changing it require a new build or only a runtime secret update?

That inventory usually reveals whether the problem is a missing variable, wrong name, wrong environment or wrong trust boundary.

What if the secret is already in GitHub or the browser?

Treat an exposed real secret as compromised.

Deleting the current line is not enough if the credential has already been published, committed or shared. Rotate or revoke it at the provider, replace it in the server-side secret store and redeploy the application.

Then verify the old credential no longer works.

Also check Git history and build output where appropriate. Moving the current copy out of a React component does not retroactively invalidate an API key that was committed yesterday.

Test the live boundary, not just the interface

A production verification should prove more than “the page loaded.”

For a feature that calls an authenticated API, test the actual live journey:

  1. Open the production URL in a clean browser session.
  2. Trigger the feature as a normal user.
  3. Confirm the browser does not receive the private credential.
  4. Confirm the server function receives the request.
  5. Confirm the external provider accepts the server-side credential.
  6. Confirm failure states do not leak sensitive values.
  7. Confirm the resulting business state is correct.

For payments, email, authentication and database writes, also verify the downstream result. A success toast is not proof that money was recorded, mail was delivered or data was saved correctly.

This is one reason my AI-built app production checklist treats production readiness as a system problem rather than a UI milestone.

A safer prompt for AI builders

Instead of asking an AI builder to “add this API key,” give it the security boundary explicitly:

Integrate this authenticated API. Store the credential only in the server-side secret store. Do not expose it through client environment variables, frontend source, network responses or Git. Route authenticated calls through a server/Edge Function and tell me which production secret name I must configure.

That prompt does not replace review, but it gives the builder a much better constraint than simply pasting a credential into chat and hoping it chooses the correct architecture.

Before you launch

Your production configuration is ready when you can answer four questions clearly:

  • Which values are intentionally public?
  • Which credentials are privileged secrets?
  • Which runtime consumes each value?
  • Where is each production value configured and rotated?

If those answers are fuzzy, adding more features makes the eventual debugging harder.

For a small prototype, fixing the boundary may take minutes. For an app with authentication, payments, webhooks and several integrations, it is worth auditing configuration before real users arrive.

If your AI-built product has reached the point where preview works but production configuration, permissions and integrations are becoming difficult to reason about, see my MVP development service or contact me. I can help separate what needs a small configuration fix from what actually needs architectural work.

Frequently asked questions

Questions, answered.

Are VITE_ environment variables secret in a Lovable app?

No. Values intentionally exposed to the browser bundle should be treated as public configuration, not as a place for private API keys or privileged credentials.

Where should API keys go in Lovable?

Authenticated API credentials should normally be stored as server-side secrets and used from an Edge Function or another server-side boundary rather than browser code.

Why can a Lovable feature work in preview but fail after publishing?

Preview and production can differ in secrets, configuration, domains and external-service settings. Verify the live environment instead of assuming preview configuration carried over.

What should I do if a secret was exposed in frontend code?

Remove the exposure, rotate or revoke the credential at its provider, update the server-side secret store, redeploy and verify the old credential no longer works.

NEED HELP WITH THE BUILD?

Turn what you learned here into a clearer website or MVP.

Share the goal, current stage, and constraints. I’ll help you identify the smallest responsible next step.

Continue reading

Related notes.