An app built in Lovable, Bolt, Replit, or Cursor can look finished in the preview and still fail the first real user. Walk this list before sign-up, payments, or a public URL depend on that build.
Own the code first
Hardening starts from a repository you can clone without the builder account.
Lovable stores the project inside its platform until you export it. Git sync is available on all plans. It connects the project to a repository on GitHub, GitLab, or Bitbucket and keeps the two in sync both ways. A one-time .zip download of the codebase is available on paid plans. On Enterprise workspaces, admins can limit that download to workspace admins and owners. Lovable's guide to deploying outside Lovable states what both paths include: the application source, configuration, and the database migration files stored in the project. They leave out the records in the database and the files in storage. Export those separately before you treat the copy as complete.
Bolt can create a GitHub repository from the project. That repository starts private, on main, and Bolt syncs later changes. You can also download a zip from the project title menu, under Export, then Download.
Replit can connect the app to a GitHub repository from the Git pane and turn on auto-sync. Push the commits you intend to keep. Replit's copy guidance says GitHub receives only what you commit and push, and that secret values stay out of the repository.
If you built the app in Cursor, the files are already in the folder you opened. Confirm the Git remote is a repository your company controls, and that production deploys from a branch someone reviews.
- The repository sits on an account your company administers.
- A second person can clone it and open a pull request.
- You know where the database rows and uploaded files live, because the code export does not carry them.
Auth and row-level security
Browser apps that use Supabase are a normal setup when row-level security is on and the grants match the product. Supabase states the failure mode in its Row Level Security guide: a table in an exposed schema without RLS is readable and writable by any role that holds a grant on it. Enable RLS on every table in an exposed schema. On projects that still grant anon and authenticated by default, revoke those grants. Adding a policy leaves the grants in place.
After RLS is enabled, a request that uses the publishable key sees no rows until a policy allows them. A policy written to anon using (true) is a public read of every row that role can already reach. Reserve that pattern for data you intend to publish.
Keys and roles are a separate check. Supabase's API keys guide maps a publishable key to the anon role when nobody is signed in, and to authenticated when they are. Secret keys, and the legacy service_role key, use a role that bypasses RLS. The same guide notes that legacy keys are long-lived JWTs, and that a long key beginning with eyJ is one of those legacy keys. Securing your data says the publishable key can live in frontend code when RLS and least-privilege grants are in place, and that secret and service-role keys stay on the backend.
For each exposed table, follow the guide's order. Enable RLS, revoke the client grants, grant back only the operations that role needs, write a policy per operation, and run supabase test db so allow and deny are asserted for anon and authenticated. Put the grants and the RLS change in the same migration so the next environment gets both.
The October 30, 2026 default is a narrower change than a full access review. Walk the five-step exposure check in What Supabase's Oct 30 change does not fix on the project you are about to ship. That article covers tables that are already reachable, policies that return every row, and secret keys copied into the client.
Secrets in the bundle
Search the repository and the production JavaScript bundle for these strings:
sb_secret_,service_role, and long keys that start witheyJsk_live_,sk_test_,rk_live_,rk_test_, andwhsec_- A database connection string or a service password
Stripe draws the same line. Its API keys page marks the publishable key (pk_) as safe for front-end code, and marks secret keys (sk_) and restricted keys (rk_) as unsafe to expose. Best practices for secret API keys say to keep those keys out of source code, including private repositories, and to supply them from the host's secret store or from server environment variables. Sandbox keys and live keys are different pairs. A preview build that holds sk_live_ can act on the live Stripe account.
Treat any secret the browser bundle contains as public, then rotate it. A value that only the server should see belongs in the host environment for server code.
Validate every write on the server
The form in the browser can check a field and still be skipped by a direct request. The function that inserts or updates the row should check type, length, and allowed values again. RLS answers which role may touch which rows. It does not answer whether the amount, the email, or the file is one you meant to store. Reject the request with a specific error when the check fails, and write the row only after that.
Do the same for file uploads. Cap the size, allow the types the product actually uses, and store the object somewhere the browser cannot list by guessing a URL.
Logs you can search
After launch, a user will hit an error you cannot reproduce from the happy path. Send server errors to a log you can filter by time, route, and user id. Keep secrets, card numbers, and the raw webhook body out of that log. Show the user a short message. Keep the stack trace on the server.
If you move the frontend off Lovable hosting, Lovable's external-deployment guide says you take on logs, environment variables, and the deployment pipeline for that part of the app. Lovable cannot monitor infrastructure it does not run. Name the log tool and the person who reads it before you share the URL.
Payments and Stripe webhooks
A success screen in the browser is the start of checkout, not the record that money arrived. Stripe signs webhook events and sends the signature in the Stripe-Signature header. Verify that signature with the raw request body and the endpoint's signing secret before you grant access, fulfill an order, or mark an invoice paid. Changing the body before verification, including parsing it to JSON and serializing it again, makes the check fail. The signing secret belongs to one endpoint. Stripe notes that the same URL used with test keys and with live keys has a different secret for each.
Webhook deliveries can repeat. Stripe's guide says an endpoint might receive the same event more than once, and that you should log the event ids you have already processed and skip ids you have handled. Record the event id in the same write that marks the order paid, so a retry finds the id and stops. A second success should not grant the product twice.
Point the live endpoint at the live app, and the test endpoint at the test app. A test webhook that writes into the production database creates production rows from test events.
Backups and migrations
Supabase backs up Pro, Team, and Enterprise projects every day. Pro projects can restore from the last 7 days, Team from 14 days, and Enterprise from up to 30 days. Projects on those plans that need a tighter window can add Point-in-Time Recovery. Supabase documents a worst-case recovery point of two minutes for that add-on. Free-plan projects should export on a schedule with the Supabase CLI db dump command and store the dump outside the project. Deleting a Supabase project permanently deletes its backups as well.
Schema changes belong in migration files, applied in order. The RLS guide says to put enable row level security and the grants in that migration, rather than only in a SQL editor session. Lovable's export includes those migration files and leaves the live rows behind, so a new environment starts empty until you import data on purpose. Confirm you can restore one backup onto a project that is not production, and that sign-in still works against the restored users.
Separate the environments
Give production its own Supabase project and its own Stripe mode. Preview URLs and local runs use the other project and Stripe sandbox keys. Stripe's API keys page tells you to build and test with sandbox keys (pk_test_, sk_test_, rk_test_), then switch to live keys when you accept real payments.
Clone the repository and run the app on your own machine before an external host builds it. Lovable's external-deployment guide uses that local run to confirm dependencies and the environment variables the app reads. Set production variables on the host. Keep them out of the repository.
A deploy you can run again
Whether Lovable still hosts the app or you moved the frontend, you want a path you can repeat from the repository.
- A clean clone installs, builds, and starts.
- Production variables are present on the host.
- Confirm with the host that a failed build leaves the current version in place.
- You can return to the previous commit and deploy that.
When the frontend runs outside Lovable, the same guide says you own availability and preview environments for that frontend. Write down the host, the branch it deploys, and who can roll it back. That note is the deploy pipeline until a CI job replaces it. The job should build from the repository, not from a laptop upload.
Performance on the first real session
Load the heaviest screen on a phone-width window, signed in as a normal user. Look for a query that returns a whole table to the browser, an upload with no size cap, and a list with no page size. Bound each query to the rows that screen shows, and cap uploads at the file types and sizes you accept. Time that screen on the production project. The number that matters is the one you measured there.
Rate limits on public writes
Sign-up, sign-in, password reset, public forms, and any route that calls a paid API should reject bursts. Start with a small limit per IP and per signed-in user. Return a clear error when the limit trips, and log that status code so abuse is visible separately from product bugs. Apply the same idea to the webhook route: verification failures should not be allowed to hammer the database.
Rescue it, or rebuild it
Rescue the app when the flow a user takes is the product you want to launch, and the gaps are the items above: access rules, secrets, payments, backups, and a deploy you can repeat. That is the work described on Fix your MVP.
Rebuild when you cannot place the source in a repository you control, when the tables cannot represent the product after a migration, or when a small change breaks sign-in or checkout and you have no test that shows why. A replacement build is a different engagement. The 30-day MVP sprint covers one primary user, one core loop, one integration, and a deploy you can open.
If both descriptions fit parts of the app, split the list. Fix access, secrets, and payments in place. Replace the parts whose data model cannot express the product.
Run this before you share the URL
- The repository is on an account you control, and a second person can clone it.
- RLS is on for every exposed table, client grants were revoked and granted back on purpose, and a logged-out request with the publishable key returns only public rows.
- The client bundle contains no secret key, service-role key, or Stripe secret.
- Every write is validated again on the server.
- Errors land in a log you can search, with secrets left out of the payload.
- Stripe webhooks verify the raw-body signature, and a repeated event id does not grant access twice.
- Backups match the Supabase plan you pay for, and migrations include the RLS changes.
- Preview and production use different Supabase projects and different Stripe modes.
- A clean clone builds, and you know who rolls a bad deploy back.
- The heaviest screen limits its rows, and uploads have a size cap.
- Public write routes, including auth, have a rate limit.
- You have marked which items to fix in place and which require a rebuild.
Ask for the 5-day pass
The MVP Rescue Audit is a 5-day review of one existing MVP from Lovable, Bolt, Replit, Cursor, or a stalled build. You receive a written fix plan, a fixed quote for the build that follows the plan, and a walkthrough call. Hire us for that build within 30 days and the audit fee is credited against the work.
The three ways to start, including the audit, are on offers. To begin, open the MVP Rescue Audit or send the repository.

