v0 builds Next.js apps and publishes them to Vercel in one click. That's genuinely great. It also means the gap between "it works in the preview" and "strangers are using it" can be about ten seconds.
Vercel has written about what it sees go wrong in v0 apps. The most common problems it names are exposed API keys, misused NEXT_PUBLIC_ variables, and API routes anyone can call. This checklist starts there, then covers the rest of what I'd check before posting the link.
Keys and secrets
No secret in a `NEXT_PUBLIC_` variable. In Next.js, any environment variable starting with NEXT_PUBLIC_ gets copied into the JavaScript every visitor downloads. That's what the prefix is for. It's right for public values like your Supabase URL and publishable key. It's wrong for anything secret.
Open your project's environment variables (in v0's project settings or in Vercel under Settings → Environment Variables) and read through the list. Anything with the public prefix should be something you'd be fine posting publicly.
Vercel says v0 blocked more than 17,000 deployments in a single month because of exposed secrets. That's a good safety net. It's still worth knowing which of your keys are secret, so you don't work around the block.
Prompt for v0:
List every NEXT_PUBLIC_ environment variable. Move any secret (OpenAI or other AI keys, the Supabase secret key, database URLs, Stripe secret keys) to a server-only variable and use it only in server code or route handlers.
Public keys are locked to your domain. Some keys are meant to be in the page, like Google Maps, reCAPTCHA, EmailJS, or analytics keys. Vercel lists these among the keys v0 apps most often nearly leaked. An unrestricted one can be used by anyone, on your bill. In each provider's dashboard, restrict the key to your live domain.
API routes
Every route that touches user data checks who's asking. v0 apps often have route handlers or server actions that read and write data. A route with no login check lets anyone call it directly. That's how one user reads another user's data, or how a stranger runs up your AI bill.
Prompt for v0:
Go through every route handler and server action. Each one that reads or changes user data must check the signed-in user on the server and only return that user's data. Don't trust user ids sent from the browser. Add a rate limit to routes that call AI models or send email.
Paid APIs have a spending limit. Set a monthly budget or usage limit in your AI provider's dashboard before launch. If something goes wrong, it caps the damage.
Database
Supabase tables have row level security on. If you added Supabase through the Vercel Marketplace, your project has a public publishable key and a server-only secret key. The publishable key is fine in the browser. What protects your data is row level security, so every table needs it on, with policies that limit each user to their own rows. The walkthrough is in Supabase row level security for beginners.
The secret key stays on the server. Never use the Supabase secret key in a client component to make an error go away. It skips every rule you set.
Preview links and your real link
Previews stay private. Vercel can create preview deployments, each with its own URL, for test versions of your app. Those can show half-built features or test data. Check who can open them under Settings → Deployment Protection in Vercel.
Your production link is the one you share. Publishing gives you a production URL, usually ending in vercel.app. If you have a custom domain, connect it under Settings → Domains before you announce, so the link people save is the one you'll keep.
Make it look finished
These aren't security problems, but they're what people notice first.
- Link previews. Text your link to yourself. If it shows a blank card or a generic title, ask v0 to add a page title, meta description, and an Open Graph image (1200×630).
- Findable by Google. Visit
/robots.txtand/sitemap.xmlon your live site. If they're missing, ask v0 to add both. More on this in Why isn't my vibe-coded app showing up on Google? - Works on a phone. Open it on your own phone and tap through the main flow.
- A way to reach you. A contact email or form, so early users tell you about bugs instead of posting about them.
Security headers
Headers like Content-Security-Policy and Strict-Transport-Security tell the browser to block common attacks, such as other sites framing yours. Next.js doesn't add them by default.
Prompt for v0:
Add security headers in next.config for every route: Content-Security-Policy with frame-ancestors 'none', Strict-Transport-Security, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and Permissions-Policy. Make sure the app's scripts and images still load.
The final five minutes
- Open the production link in a private window.
- Sign up as a second person and try to see the first account's data.
- Log out and open a page that should need a login.
- Search the page's JavaScript in your browser's developer tools for
sk_,sk-, andsecret. - Share the link with one friend before you share it with everyone.
The short version
- No secret behind
NEXT_PUBLIC_, and public keys restricted to your domain. - Every route checks the signed-in user, and paid APIs have a limit.
- Row level security on for every Supabase table.
- Previews protected, custom domain connected, link preview looks right.
v0 and Vercel check your code before it deploys. The free Throttle Bird scan checks the live result from the outside: what's in the page a visitor downloads, your headers, HTTPS, link previews, and, once you prove you own the app, whether your database answers the public key. There's a v0-specific checklist too.
Sources: Vercel: v0 and vibe coding securely, v0: Deployments, Next.js: Environment variables, Vercel: Deployment Protection, Supabase: Vercel Marketplace.