No, a key written into a vibe-coded app's client bundle is readable by anyone who opens it. This guide covers where it belongs and what to check first.

Step 1

Where Is a Safe Place to Store API Keys?

A safe API key lives on a server you control, injected as an environment variable, never written into code or anything the build ships to the browser. Supabase's docs draw the line vibe-coded apps need: a publishable key is safe only because Row Level Security bounds what it reaches.

What to do: Keep two classes of key straight from the first prompt. A publishable key is meant to travel to the browser, mobile app, or CLI, because Row Level Security decides what it can actually touch. A secret key bypasses that entirely and belongs only where you control the code: your server, an Edge Function, a cron job. Supabase's API keys guide states it plainly: "A secret key bypasses every Row Level Security policy you have. Never put one in a browser, a shipped application, or source control."

How to do it: Set the secret key as a server-only environment variable and read it with process.env inside a server route or Edge Function, never a client component. On Next.js, that means leaving the variable name unprefixed. The Next.js environment variables guide is specific about what the prefix does: "In order to make the value of an environment variable accessible in the browser, Next.js can 'inline' a value, at build time, into the js bundle that is delivered to the client." Add NEXT_PUBLIC_ and the build tool treats that as a publishing instruction, not a naming choice. Leave it off and the variable stays server-only.

Red flags: If you can grep a real secret key out of your deployed JavaScript bundle, or find one sitting in a .env file that's tracked by git, the key is already public even if the app looks fine in the demo. The default create-next-app template gitignores .env for exactly this reason - if your project's .gitignore doesn't list it, that's a sign the setup was hand-edited past the safe default. Builders who use Joylo skip most of this manual grep work, since the build's own React and Node structure keeps server-only variables out of the client bundle by default.

Checkpoint: You should now have a written list of every key your app uses, each one marked either "publishable, ships to the browser, Row Level Security bounds it" or "secret, server-only, never leaves your control." If a key doesn't clearly fit one label, treat it as secret until you confirm otherwise. Joylo's AI Confidence Score runs a security check on this exact split for every build, on every plan, flagging a secret-looking key before it reaches production.

Step 2

How Do You Make a Vibe-Coded App Secure Around That Key?

Move every privileged call behind a server route so the secret key never enters the bundle, switch on Row Level Security so a shipped public key stays bounded, then assume something has already leaked and set up scanning and rotation. Veracode puts the average model security pass rate at 56%.

What to do: Order matters, and each move closes a different door. First, any call that needs a secret key - billing, admin actions, anything touching another user's data - runs on your server, not the client, so the key stays out of the bundle by construction. Second, turn on server-side access rules for anything a public key can reach. This is the exact gap Wiz Research found in the Moltbook breach: "When properly configured with Row Level Security (RLS), the public API key is safe to expose - it acts like a project identifier," but "without RLS policies, this key grants full database access to anyone who has it." Third, assume a key will leak eventually and build for that: enable secret scanning and put every key on a rotation schedule.

How to do it: Write the RLS policy for every table a publishable key can reach before you ship, not after a launch spike makes you notice. OWASP's Secrets Management Cheat Sheet adds the two habits RLS alone doesn't cover: least privilege on who can even read the key, and rotation on a regular, automated schedule, because "you should regularly rotate secrets so that any stolen credentials will only work for a short time." A cadence that actually gets followed beats an aspirational one: rotate a routine third-party API key on a fixed calendar reminder, such as every 90 days, rotate immediately for anything that touches payments or billing regardless of schedule, and rotate the moment anyone with access to the key leaves the team or a contractor's engagement ends. Write the cadence into the same key inventory you built in Step 1, next to each key's label, so "rotate this" has an actual date attached instead of living as a vague intention.

Red flags: A public key that returns data for a table with no RLS policy attached is a live version of the Moltbook mistake, not a theoretical one. Test it directly - query the table anonymously, with no session, and see what comes back.

Checkpoint: You should now have RLS enabled and tested on every table your publishable key touches, every privileged action routed through a server endpoint, and a rotation cadence written down somewhere you'll actually see again. This isn't a one-model problem, either. Lovable, Replit, Bolt and Cursor all ship generated code through the same kind of client bundle, so the same access-rule discipline applies no matter which AI wrote the first draft. Joylo's five-domain AI Confidence Score runs a security audit on every build, on every plan, specifically to flag this class of gap before it ships.

Step 3

What Should You Check Before You Launch?

Run four checks before launch: search your built JavaScript for the secret key prefix, confirm access rules actually deny an unauthenticated read, confirm .env is gitignored with clean repo history, and confirm you can rotate a key without a manual redeploy. Skipping this list is how a normal-looking public key becomes full database access.

What to do: The clearest worked example of what happens when this checklist gets skipped is Moltbook, an AI social network built on a vibe-coded, Supabase-backed stack. Wiz Research identified a misconfigured database "allowing full read and write access to all platform data," exposing 1.5 million API authentication tokens and 35,000 email addresses. The cause wasn't an exotic exploit. The public key was reachable exactly as designed; Row Level Security, the one control that makes a shipped key survivable, had never been switched on. "In Moltbook's implementation, this critical line of defense was missing."

How to do it: Before you ship, work through the checklist in order. Search your production build's JavaScript for your secret key's prefix - if it's findable with a browser search, it's public. Open an incognito session with no login and try to read data through your public key directly; a correct RLS policy returns nothing. Confirm .env sits in .gitignore and that no earlier commit still carries a real key in its history, since deleting the line in your latest commit doesn't erase it from the log. Confirm every key can be swapped from your hosting dashboard without a manual code change and redeploy.

Red flags: Builders who skip this list tend to find out the hard way. Joylo's own Rescue Economy research, drawn from independent builder reports, found the same failure points recurring across threads: authentication, database and payment integrations breaking, security holes shipped to production, and apps that held up fine in a demo but failed at first real traffic. That pattern is exactly what an unchecked RLS policy or an exposed key produces once actual users, not a demo audience, start hitting the app.

Checkpoint: You should now have run all four checks against your live build, not your local one, and be able to state in one sentence what your public key can and cannot reach if someone else finds it.

Recommended reading6 Options for an App Security Audit Before LaunchYour AI-built app looks done. Here's who actually catches the vulnerabilities before real users do, and which of the six options fits before you launch.
Step 4

What Happens If a Key Leaks Anyway?

Assume it's already committed somewhere and check: GitHub's secret scanning reads your entire git history on all branches, runs automatically and free on public repositories, and alerts you the moment it finds a match. Rotate the key immediately once it's confirmed live, because deleting the line from your latest commit does not remove it from history.

What to do: GitHub's own documentation states the scope plainly: secret scanning "scans your entire Git history on all branches of your repository for hardcoded credentials, including API keys, passwords, tokens, and other known secret types," and "runs automatically for free" on public repositories. When it finds something, GitHub "generates an alert on your repository's Security and quality tab with details about the exposed credential." Treat that alert as a launch-blocking event, not a background notice.

How to do it: Rotate the leaked key at the source - the provider dashboard, not your codebase - then update the new value in your server-side environment variables and redeploy. Do this even if you've already deleted the line from your latest commit; the old value is still readable in git history until you rotate it out of use. GitGuardian's research on this is the reason rotation can't wait: retesting secrets it flagged as valid in 2022, it found the validity rate still above 64% in a January 2026 recheck, meaning most leaked keys are never revoked at all.

Red flags: A key you "meant to rotate later" is functionally a key you never rotated. If you're not sure whether a fix is complete - the RLS policy is written but untested, or you're not confident the bundle is clean - that's the moment to bring in a second set of eyes rather than guess. If your API key already leaked or your access rules feel unproven, check out Joylo's Expert Assist. See Expert Assist

Checkpoint: You should now have the leaked key rotated at the provider, the new value deployed, and secret scanning turned on for the repository going forward so the next leak is caught the same day, not discovered months later.

Recommended readingHow Do AI App Builders Handle Security Updates?The scan finds the vulnerable package in seconds. Who actually applies the patch and republishes the app is a different question, and the answer changes by builder.

What Common Mistakes Break API Key Security in Vibe-Coded Apps?

The same five mistakes account for most exposed-key incidents in vibe-coded apps, and each one traces back to a control that was skipped rather than a sophisticated attack. None require rewriting the app. Fixing all five is a short checklist, run once before launch and again before any major release.

  • Prefixing a secret with `NEXT_PUBLIC_` out of habit. The prefix exists to publish a value on purpose. Applied to a secret key, it does exactly what it's built to do - inline the value into the shipped bundle - which is the opposite of what the builder wanted.
  • Shipping a publishable key with no Row Level Security behind it. This is the Moltbook mistake exactly: the key itself was never the problem, the missing access rule was.
  • Treating `.env` as private because it isn't in the UI. If it's tracked by git and the repo is ever made public, or shared with a collaborator, the key travels with it. Confirm .gitignore covers it explicitly.
  • Never rotating a key after a scare. GitGuardian's 2026 report found AI-service secrets on public GitHub reached 1,275,105 in 2025, up 81% year over year - the volume keeps climbing because rotation keeps getting skipped.
  • Assuming a newer or "smarter" model writes safer code. Veracode's 2026 benchmark puts the average security pass rate across models at 56%, with even the best model at 68% - architecture decisions, not model choice, close this gap.

This is the exact list Joylo's engineers check on a rescue call, and the reason the AI Confidence Score audits security on every build rather than leaving it to a final read-through.

When Does This API Key Framework Need to Change?

This framework holds for a solo builder shipping a first app and for a small team scaling one, but three conditions change how it's applied. Knowing which one you're in keeps the checklist from becoming either overkill or not enough.

Scale changes it. A single publishable key with one RLS policy is enough for a small app with one data model. The threshold to watch is your second environment, not a headcount or revenue number: the moment you're running more than one - staging alongside production, or a customer-specific tenant - each one needs its own keys and its own tested policies, because a policy that's correct in staging isn't automatically correct once real customer data is involved.

Regulatory scope changes it. An app handling health, financial, or other regulated data needs key rotation and access logging built in from day one, not bolted on after the fact, because the cost of a missed check is no longer just a data exposure - it's a compliance failure. That's a different, heavier bar than the general checklist above covers.

The backend itself changes it. This guide leans on Supabase and Next.js because they're the stack most vibe-coded apps run on, but the same publishable-versus-secret split, and the same require-a-server-side-rule discipline, applies to any backend-as-a-service or serverless setup. Confirm the equivalent of Row Level Security exists and is switched on before assuming the pattern transfers directly. Joylo's Confidence Score security audit runs the same check regardless of which of these three conditions applies to your build.

What Do Real API Key Decisions Look Like Before Launch?

Picture three builders at the same decision point, a week or less from launch, running the four-point pre-launch checklist from Step 3 - a bundle grep for the secret key prefix, an anonymous-read test against the public key, a gitignore and history check, and a no-redeploy rotation test - against a real codebase instead of a demo. Each hits a different gap, and each fix is small once the gap is actually found rather than assumed away.

Scenario 1: The solo founder wiring up her first database. She's built a two-sided marketplace app with a Supabase backend and is a week from launch. Running the Step 3 checklist, she finds her publishable key can read every user's profile table with no session at all - RLS was never turned on for that one table. She writes and tests the policy, reruns the anonymous-read check until it returns nothing, and ships on schedule. The fix took an afternoon because she caught it before launch, not after.

Scenario 2: The team that already shipped and is scaling. A small team's app is live and taking on more traffic each week. A routine grep of their production bundle turns up a secret key that had been prefixed NEXT_PUBLIC_ by mistake early on and never caught. They rotate it at the provider immediately, move the dependent call behind a server route, and turn on GitHub secret scanning so the next slip is caught automatically rather than by hand.

Scenario 3: The builder who isn't sure the fix is complete. He's rotated a leaked key and rewritten what he believes is the right RLS policy, but he's not confident he's covered every table, and the app already has paying users. That's the situation Joylo's Expert Assist exists for - a named engineer, fixed price, reviewing the actual access rules rather than the builder guessing alone.