Checked Landing Page1 tables · 1 policies · 7 checks

    Landing Page with Email Capture template for Lovable

    One offer, one action, an indexable copy body and an insert-only policy on the sign-up table. The kit is three files: a build prompt for Lovable, a Supabase schema with row-level security, and verification queries that run as the wrong user to prove each policy denies what it should. The prompt is free; the full SQL comes with the bundle.

    By Marco Kohns · Stack: React + Vite, TypeScript, Tailwind CSS, shadcn/ui, Supabase

    The trap

    What goes wrong without the Landing Page with Email Capture kit?

    A policy for all also grants select, so anyone holding the public key reads every email. The kit has one insert policy and no select policy, so reads return zero rows.

    The mistake

    A public form that exposes the whole list: the policy Lovable writes when nobody names the rule.

    The check that catches it

    verify.sql, check 2: Should return ZERO ROWS, not an error and not data. If this returns rows, your email list is publicly readable. Stop and fix the policy.

    The policies that prevent it are in the kit's schema.sql, which ships with the bundle; the hub shows one pattern per kit.

    verify.sql

    How do you prove the Landing Page with Email Capture policies work?

    Run every check as an ordinary signed-in user, never as service_role, which bypasses every policy and makes a broken schema look correct.

    The verification checks in the kit's verify.sql, as written in its comments
    #Expected result
    1Should SUCCEED. An anonymous visitor can join the list.
    2Should return ZERO ROWS, not an error and not data. If this returns rows, your email list is publicly readable. Stop and fix the policy.catches the trap
    3Should return zero rows. Counting is still reading.
    4Should FAIL. No update policy exists.
    5Should FAIL. No delete policy exists.
    6Should SUCCEED silently and create no second row.
    7Confirm RLS is on.
    Lovable's Security view with the Deep security scan and Quick security scan cards and a No issues found panel, beside the chat reporting a clean scan
    Lovable's free scans on my SaaS project, 26 September 2026. A clean scan says row-level security is switched on; verify.sql shows what the policies deny.

    What is in the kit?

    • A build prompt that starts from the traffic source, before any layout
    • A leads table with case-insensitive deduplication and UTM capture
    • An insert-only RLS policy for anonymous visitors, with no select policy at all
    • A capture function so a repeat submission confirms instead of erroring, without a read
    • Seven verification queries, one of which proves your list is not readable from the browser

    What the kit does not do

    • Not a pre-built app you clone and run. There is no repository and no node_modules.
    • Not a design file or a theme. Lovable generates the interface from the prompt.
    • Not a substitute for reading the SQL. You are running it against your own database.

    Setup

    In what order do you set up the kit?

    Schema before prompt, because the prompt references the table names the schema creates.

    1. 01

      Run schema.sql in the Supabase SQL editor

      The prompt writes through capture_lead(), which this file creates.

    2. 02

      Run verify.sql from the browser client as an anonymous visitor

      Query 2 is the one that matters. If a bare select on leads returns rows, stop and fix it before shipping.

    3. 03

      Paste prompt.md into Lovable

      Then replace the offer and the audience.

    4. 04

      Read your list from the dashboard or a server function

      Never from the browser. There is no read policy, deliberately.

    Things that catch people out

    • The single most damaging mistake in a generated landing page is granting select on the leads table to anon so that a debug view works. That makes every address downloadable by anyone holding your project's public key, which is published in your own frontend.
    • The prompt explicitly forbids inventing testimonials, logos or numbers. Lovable will otherwise generate plausible social proof, and fabricated proof on a live page is a liability; placeholders stay labelled.
    • A page that is only a hero and a form has almost nothing to rank with. The prompt asks for a copy body and FAQ structured data for that reason.

    The files

    What do the kit files contain?

    The build prompt in full, and the first 12 lines of each SQL file so you can judge the code before you run it anywhere.

    The build prompt

    # Context
    Build a pre-launch landing page whose one job is collecting emails for the launch list. Visitors arrive from one traffic source carrying UTM parameters, so the page has one offer and one action.
    
    ## Core Features (Priority Order)
    1. Hero with the offer and the email form visible without scrolling on a phone
    2. Email form calling capture_lead with the email, source, utm_source, utm_medium, utm_campaign and referrer
    3. Inline success state replacing the form without layout shift
    4. A repeat address shows the same success state, because capture_lead ignores duplicates
    5. A short body section, then three proof blocks as labelled placeholders
    
    ## Visual Style & Design
    - Minimal and focused: generous whitespace, one focal point, short body lines
    - Single column: hero first, sections stacked below
    - Fraunces for headings, Inter for body text
    - Colours: background #fafaf9, text #1c1917, muted #78716c, accent #ea580c on the submit button only
    - shadcn/ui Input and Button for the form, Card for proof blocks, Alert for the success state
    - Save these style keywords to the project knowledge.
    
    ## Page Copy
    - Headline: "Be first in line when [Product] launches"
    - Subtext: "Leave your email and we send one message on launch day, with your invite inside."
    - Button: "Join the waitlist"
    - Success: "You are on the list. Watch your inbox on launch day."
    - Proof: "[Placeholder: customer quote]", "[Placeholder: logo row]", "[Placeholder: one sourced number]"
    - No accounts: every visitor is signed out and sees the same page.
    
    ## States
    - Empty: an empty or malformed email shows an inline message under the field
    - Loading: the button shows a spinner and stays disabled while capture_lead runs
    - Error: a failure keeps the typed email and shows "Something went wrong. Try again." with retry
    
    ## Data & Access
    - The leads table, its row-level security policy and capture_lead already exist in the connected Supabase project from schema.sql. Never weaken, drop or bypass them or create tables; if something is missing, stop and ask me.
    - The form writes only through capture_lead. The browser never selects, counts, updates or deletes leads, and never gets a read policy.
    - Browser validation mirrors leads_email_shape. This build has no admin screen.
    
    ## Done When
    - Submitting a new address shows the success state and a row appears in leads with the utm_source from the URL
    - Submitting the same address in a different case shows the same success state and adds no second row
    - An anonymous select on leads from the browser returns no rows
    - An invalid email shows the inline error and never calls capture_lead
    
    ## Build Order
    The static page with final copy and meta tags, then the form wired to capture_lead, then UTM and referrer capture.
    
    ## Safe-Guard Instructions
    - One call to action: no second button, popup or navigation menu
    - No invented testimonials, logos, names or numbers
    - No browser read access to leads on later edits, and no service role key in client code
    
    ## Before Building
    Ask me any questions you need in order to fully understand what I want from this feature and how I envision it. Save my answers to the project knowledge so later prompts build on them.

    schema.sql

    Preview · full file in the bundle

    Leads table and capture function

    -- Landing page lead capture for Lovable + Supabase
    -- Reviewed row-level security. Read the comments before running this.
    --
    -- THE ONE THING THAT MATTERS HERE: a public form needs INSERT for anonymous visitors and
    -- must never grant SELECT. If you grant select to anon, your entire email list is
    -- downloadable by anyone with your project's public key. That is the single most common
    -- and most damaging mistake in a generated landing page.
    
    create table public.leads (
      id uuid primary key default gen_random_uuid(),
      email text not null,
      -- Case-insensitive uniqueness, so Foo@x.com and foo@x.com are one lead.
    The rest of schema.sql, every policy written and its denials verified, is in The Complete Lovable Bundle.Get the Bundle

    verify.sql

    Preview · full file in the bundle

    Policy verification queries

    -- Verification queries. Run these from the browser client, as an anonymous visitor.
    -- The second one is the important one.
    
    -- 1. Should SUCCEED. An anonymous visitor can join the list.
    select public.capture_lead('verify@example.com', 'verification');
    
    -- 2. Should return ZERO ROWS, not an error and not data.
    --    If this returns rows, your email list is publicly readable. Stop and fix the policy.
    select * from public.leads;
    
    -- 3. Should return zero rows. Counting is still reading.
    select count(*) from public.leads;
    The rest of verify.sql, every policy written and its denials verified, is in The Complete Lovable Bundle.Get the Bundle

    After the kit

    Which library prompts build on the Landing Page with Email Capture kit?

    Each extends the kit's tables with one feature, keeps its policies, and ends with Done When checks Lovable can verify.

    • Landing Page + Email Opt-In

      A single-purpose pre-launch page with one offer and one form, where the signups table accepts inserts and forbids every browser read, and UTMs are stored per signup.

    • Event Countdown Landing Page

      A dated event page whose countdown, calendar links and live and replay variants all run from one UTC timestamp, with an insert-only reminder signup table.

    • Landing Page A/B Variant Generator

      Two-variant testing on a live landing page: one changed block, cookie-stable assignment, per-variant conversion events and a results view that waits for 300 visitors per variant.

    • Basic Analytics for Landing Pages

      First-party landing page analytics posted to your own server function: pageviews, sources, device, one conversion and a four-step funnel, read on an admin dashboard.

    • Simple Sitemap & SEO Generator

      Sitemap, robots.txt, titles, canonicals and structured data generated from one route registry in code, with an admin page that fetches each route and flags mismatches.

    • Simple Press Kit Page

      A public /press page served from tables: dated facts, quotes shown only when marked cleared, downloadable assets with dimensions, a ZIP of everything and a press contact.

    The full SQL for all 4 kits

    The Complete Lovable Bundle: every schema.sql and verify.sql, every Pro prompt, unlimited generation. One payment. No subscription, no renewal, ever.

    Disclosure: if you create a Lovable account through links on this page, we may earn a commission. It costs you nothing and does not change what we recommend. Create a free Lovable account

    Frequently asked

    What does the Landing Page with Email Capture template for Lovable include?

    A build prompt that starts from the traffic source, before any layout. A leads table with case-insensitive deduplication and UTM capture. An insert-only RLS policy for anonymous visitors, with no select policy at all. A capture function so a repeat submission confirms instead of erroring, without a read. Seven verification queries, one of which proves your list is not readable from the browser.

    What mistake does the Landing Page with Email Capture kit prevent?

    A public form that exposes the whole list. A policy for all also grants select, so anyone holding the public key reads every email. The kit has one insert policy and no select policy, so reads return zero rows.

    How do I prove the Landing Page with Email Capture policies work?

    Run verify.sql after schema.sql, as an ordinary signed-in user and never as service_role, which bypasses every policy. Check 2 is the one that catches the trap: Should return ZERO ROWS, not an error and not data. If this returns rows, your email list is publicly readable. Stop and fix the policy.

    What we did not publish

    • A Lovable credit cost for this kit. The SQL was validated against Postgres 17; the kit was not built end to end in Lovable for this page.
    • The SQL in full; it is what the bundle sells.
    • The mistake SQL is an illustration written for this page; the kit SQL beside it is quoted from schema.sql.

    These templates are provided free and as-is, with no warranty of any kind. The SQL is intended to be run against your own Supabase project and will create and alter tables. Read it, run it on a development project first, and review every policy against your own requirements before going near production data. You remain responsible for the security and correctness of anything you ship. These schemas assume Supabase, which grants the anon and authenticated roles access to new tables in the public schema by default. Row-level security is what then restricts those roles. If you run this SQL on a plain Postgres instance instead, those grants do not exist, so the policies appear to work while the missing privileges are what blocks access, and a test there proves nothing about the policies.

    Other kits

    Checks parsed from the kit files; page checked 23 October 2026.

    Written by

    Marco Kohns

    Marco Kohns

    Founder of ProtoBites - Venture Growth Studio

    Growth PM at a Silicon Valley scale-up (a16z and General Catalyst backed), ex-Techstars where he consulted 13 early-stage startups, Reforge-trained. Every prompt on this site comes out of shipping ProtoBites' own portfolio products.