Probably not yet — and the three things most likely to be wrong take about fifteen minutes to check. Lovable builds on Supabase, and Supabase ships with settings that are safe for building and unsafe for launching. The app works perfectly either way, which is the whole problem: nothing tells you.
1. Row Level Security is probably off
Supabase gives every table a public API. What decides whether a stranger
can read your users table is a thing called Row Level
Security — a rule you write that says which rows each person may see.
If it is off, the table is readable by anyone who knows your project URL. Not "in theory". They open a browser and read it.
Check it: Supabase dashboard → Table Editor. Every table holding user data needs RLS enabled and at least one policy. A table with RLS on and no policy denies everyone, which is the safe direction to fail — an empty screen is a much better bug than a leaked database.
Test it properly: sign in as one account, then try to load another account's row by changing the id. If it works for you, it works for anyone.
2. The service_role key may be in your browser
Supabase gives you two keys. The anon key is designed to be
public and belongs in your front end. The service_role key
bypasses every RLS policy you just wrote and belongs only on a server.
If an assistant ever put the service_role key in front-end code to make an error go away, every visitor now downloads full access to your database.
Check it: open your deployed site, view source, and search the page
for the first six characters of your service_role key. Also search your
project for service_role and confirm every hit is server-side.
If it was ever exposed, rotate it. A key that was public is a key someone has.
3. Storage buckets default to public
Uploads are a separate system with separate rules, and people who carefully lock their tables routinely forget them. If your app stores anything users upload — profile pictures, documents, invoices — check the bucket is private and served through a signed URL.
Public bucket means every file has a permanent, guessable, no-login-required address.
The others worth ten minutes
Keys with VITE_ or NEXT_PUBLIC_ in front of
them are compiled into the JavaScript every visitor downloads. That prefix
means "publish this". An assistant will add it to silence a build error, the
app starts working, and nobody looks again. Only publishable keys belong
there.
Being logged in is not the same as being allowed. If a page loads a record by id from the URL, check it also confirms the record belongs to the person asking. Change the number in the address bar and see what happens.
You need a privacy policy from your first user. In the EU, the UK and California this applies from the first email address you store, and app stores reject submissions without one.
Questions people ask
Does Lovable do any of this for me? It generates working code. It does not decide what your risk tolerance is, and it cannot know that the table you just created holds real customer data.
Is my app fine because nobody knows the URL? No. Supabase project URLs are in your front-end bundle by design, and bots scan for them.
Do I need to understand security to fix these? No. All three are settings, not code.
Checking the rest
Those cover the failures specific to this stack. The wider list — deletion, spend limits, rate limiting, what happens under load — is in the pre-launch checklist.
npx launchprep checks the first two of these in your code
— the service_role key in front-end files, and RLS on tables your
migrations create. It reads files, so a setting you changed by clicking in
the Supabase dashboard is invisible to it: check those in the dashboard
yourself. The free tier is unlimited and runs entirely on your machine.