Lovable.dev: how to review AI-generated app code when everything looks finished

2026-04-27 · 5 min read · ZenCode

Lovable.dev takes a text prompt and builds a complete web application — React frontend, Supabase backend, styled components, routing, auth flows, and a deployed preview URL. By the time the generation finishes, you have something that looks like a finished product. That is the design goal, and it works. It is also where the review problems begin.

Lovable occupies a different position in the AI coding tool landscape than inline completion tools like GitHub Copilot or Windsurf. Those tools generate code you are already editing. Lovable generates an entire application before you open an editor. The review surface is not a function or a diff — it is an entire codebase that materialized from a description. Three specific traps follow from that position.

The three traps

1. The deployed-preview completeness trap

The moment Lovable finishes generating, you have a live URL. The app is running. You can click through the flows, fill in a form, see data appear in a table. It looks and behaves like a working product. That visual and functional completeness fires a “this is done” signal that is unusually strong compared to other AI tools.

With a code completion tool, you see code. You know code needs review. With Lovable, you see a running application. The mental category it activates is “product,” not “code to review.” The happy-path demo works because Lovable optimizes for happy-path correctness — the user story you described in your prompt. Error states, empty states, concurrent-edit edge cases, and authorization gaps in non-primary flows are invisible in a working demo of the primary flow.

The compounding version: if you show the preview to a stakeholder who says “this looks great,” that social approval creates a second closure signal on top of the first. Two “done” signals, both arriving before the code has been opened, create stronger completion pressure than either creates alone. The GitHub sync step — when Lovable pushes the code to your repo — then looks like a handoff rather than the beginning of a review process.

2. The spec-origin ownership trap

You wrote the prompt. Lovable implemented it. The code is “yours” in the sense that it came from your specification. This ownership attribution creates a subtle but consistent bias: you are less likely to rigorously review code that feels like it already reflects your decisions than code handed to you by a colleague.

The bias appears in how you read the generated code. When a colleague writes a function differently than you would, you notice the gap between your mental model and theirs and investigate. When Lovable writes a function from your prompt, it matches your mental model at the feature level (you asked for it, it was generated), which suppresses the gap-detection reflex that normally drives code review.

This is the same trap as the Devin AI spec-approval problem but with an important difference: Devin works from an issue or task that existed independently of you. Lovable works from your own words. The ownership signal is stronger, and the review resistance it creates is correspondingly higher. The code feels reviewed because it matches what you said you wanted — which says nothing about whether the implementation is correct.

3. The Supabase RLS false-security trap

Lovable integrates tightly with Supabase and generates database schema, Row Level Security policies, and auth configuration as part of the application. These artifacts arrive alongside the UI code, formatted correctly, referencing the right table names, with policies that compile without errors. They look like the security layer has been set up.

RLS policies have a property that makes generated ones particularly risky: a missing policy is indistinguishable from a correct policy when you look at the table from a logged-in user’s session. If Lovable generates SELECT and INSERT policies for a table but omits UPDATE and DELETE, the happy-path flows still work. The gap only appears when a user with the wrong permissions attempts an update or delete — which does not happen in a demo.

The parallel trap is service-role usage. Lovable sometimes generates backend functions that call Supabase using the service role key (bypassing RLS entirely) when the user’s session key would be the correct choice. This works in every test scenario because the service role has full access, but it means RLS policies that were generated and look correct are not actually enforced on those code paths. The security layer is present but bypassed — invisible in a working demo, invisible in a quick code scan unless you specifically check the key used in each Supabase call.

Three fixes

Open the diff before you open the preview. Reverse the default review order. When Lovable finishes generating, go to the GitHub sync first — or clone the repo and read the code — before loading the preview URL. The demo creates a strong completeness signal; reading the code first means your evaluation starts from what the code actually does, not from what the demo looks like. After reviewing the code, the preview is useful for validating behavior. Run in that order, not the other.

Read the prompt back against the code at the boundary, not the center. Your prompt described the primary flow. Lovable implemented it. Check one layer outside that: what happens when a user who is not supposed to reach a screen navigates directly to its URL? What happens when a form is submitted with no data? What happens when the Supabase query returns zero rows versus null? These boundary behaviors are systematically outside what your prompt specified, which means they are systematically outside what Lovable optimized for. The feature-center of the generated code will match your prompt; the boundary is where the gaps live.

Audit every Supabase call for which key it uses, then audit every RLS policy for which operations it covers. This is a mechanical two-pass check. Pass one: grep for supabaseAdmin, SUPABASE_SERVICE_ROLE_KEY, or equivalent service-role identifiers. Any call using the service role bypasses RLS — decide if that is intentional. Pass two: for each table in your schema, list the RLS policies and confirm SELECT, INSERT, UPDATE, and DELETE policies are all present or explicitly omitted by design. A missing DELETE policy on a user-data table is a gap, not a default-deny — in Supabase, RLS tables with no matching policy deny by default only if RLS is enabled; if a table was generated without enabling RLS, all operations are unrestricted. Check that RLS is enabled on each table, not just that policies exist.

Lovable versus Bolt.new

The review problems in Lovable are structurally similar to those in Bolt.new — both generate complete applications from prompts and both create completeness-impression traps. The difference is backend depth. Bolt.new typically generates frontend-only or uses simulated backends; Lovable generates real Supabase schema, real RLS policies, and real auth flows. The security surface on a Lovable-generated app is larger and more consequential than a Bolt.new-generated app, which means the cost of skipping review is higher.

Both tools share the spec-origin ownership trap: you wrote the prompt, so the code feels like your decision, not someone else’s work to evaluate. In both cases, the fix is the same — open the code before you open the demo, and read at the boundary of what you specified, not the center.

The honest assessment

Lovable produces working applications faster than any other tool in this series. That speed is real and the quality of the happy-path implementation is consistently high. The review risks it creates are proportional to that speed: the faster the gap between “I wrote a prompt” and “I have a deployed app,” the more naturally the review step gets compressed or skipped. The three traps — deployed-preview completeness, spec-origin ownership, and Supabase RLS gaps — are all forms of the same underlying problem: the output looks so finished that the evaluation step does not feel necessary. It is. The mechanical checks for RLS coverage and service-role usage take ten minutes on a new Lovable project and surface the kind of gap that a live demo cannot.

ZenCode — stay in review mode during AI generation gaps

A VS Code extension that surfaces a 10-second breathing pause during AI generation gaps — keeping you in active review mode instead of passive waiting mode when the output lands.

Get ZenCode free

Try it in the browser · see the real numbers