# Waitlist Landing Page with Referrals

> Collect early sign-ups before you build: a fast landing page, a private waitlist and "invite friends to move up" referrals.

- Category: SaaS
- Version: 1.0
- Source: https://wonly.dhfm.in/builder-4392ac/waitlist-with-referrals-lovable/

## Overview

Validate an idea before building it. This plan makes a landing page with a waitlist where every sign-up gets a personal invite link; each friend who joins moves them up the list.

The list is private by design: the browser can only call one database function that returns your own code and position, never anyone else's email.

Built in Lovable with its Supabase integration (Cursor or Claude Code work too). Before you start: a Lovable account and a Supabase project. About 40 minutes.

## Tech stack

- Lovable
- React
- Supabase
- Tailwind

## Build steps

### 1. Write your one-line pitch

Fill in PLAN.md: who it is for, what it does, what early members get. A clear promise matters more than design.

Prompt:

```text
Here is my PLAN.md. Rewrite my product sentence and launch promise into: a headline (max 8 words), a sub-headline (max 20 words), 3 benefit bullets and 4 FAQ items. Keep it plain and specific.
```

**Done when:** You have a headline, sub-headline, 3 benefits and 4 FAQs you like.

### 2. Generate the landing page

Start a new Lovable project and paste the copy from step 1.

Prompt:

```text
Build a fast, mobile-first landing page: hero with headline, sub-headline and an email field + "Join the waitlist" button; 3 benefit cards; a short "how it works"; FAQ accordion; footer. Brand colour from PLAN.md. No stock photos. Use only the copy I give you.
```

**Done when:** The preview shows a complete page that looks good on a phone.

### 3. Create the private waitlist

Connect Supabase in Lovable, then run waitlist-schema.sql in the Supabase SQL Editor. RLS is on with no policies, so nobody can read the list from the browser.

Prompt:

```text
Supabase is connected. The waitlist is only written through the database function join_waitlist(p_email, p_ref), which returns code, queue_position and referrals. Do not create other tables or policies. Show me the client code you will use to call it.
```

**Done when:** The waitlist table and join_waitlist function exist; the table has RLS enabled.

### 4. Join flow with your place in line

After joining, people see their position and their personal invite link.

Prompt:

```text
On submit: validate the email, read ?ref= from the URL, call rpc("join_waitlist", { p_email, p_ref }). Then replace the form with: "You're #{queue_position}", their invite link ({site}/?ref={code}) with a Copy button, share buttons for WhatsApp, X and LinkedIn, and "Each friend who joins moves you up 5 places." Joining again with the same email shows the same result.
```

**Done when:** Joining shows your position and link; joining twice gives the same result.

### 5. Test referrals

Use two browsers (or a private window) to check the invite logic.

Prompt:

```text
Explain how to test: join as A, open A's invite link in a private window, join as B, then join again as A and confirm A moved up 5 places and shows 1 referral. Also confirm an invalid ?ref= code is ignored without an error.
```

**Done when:** A moves up after B joins through A's link.

### 6. Stop junk sign-ups

Simple protection without CAPTCHAs.

Prompt:

```text
Add a hidden honeypot field (if filled, pretend success but do not call the function), lowercase and trim emails, disable the button while submitting, and show a friendly error if the request fails. Keep the page fast.
```

**Done when:** Filling the hidden field does not add a row.

### 7. Publish and share

Publish from Lovable, connect your domain if you have one, then share the link where your audience is.

Prompt:

```text
Prepare for launch: page title and meta description from my headline, an Open Graph image with the headline, a favicon, and a thank-you message in the share text. List the 3 places I should share it first based on PLAN.md.
```

**Done when:** The page is live and shows a proper preview when shared on WhatsApp or X.

## Assets

### PLAN.md — Fill in the blanks first; paste into Lovable as project knowledge.

```
# PLAN.md — Waitlist with referrals (Lovable)

Paste one prompt at a time into Lovable. Check the preview after each one.

Product: ______ (one sentence: who it is for and what it does)
Launch promise: ______ (e.g. "Early access in March, 3 months free")
Brand colour: ______

Rules for every prompt:
- Mobile first, fast, no stock photos.
- Never show other people's emails anywhere.
- The waitlist is only written through the `join_waitlist` database function.
```

### waitlist-schema.sql — Private table + join_waitlist function (the only way in).

```
-- Waitlist: run in Supabase → SQL Editor (or ask Lovable to run it).
create table public.waitlist (
  id bigint generated always as identity primary key,
  email text not null unique check (email ~* '^[^@\s]+@[^@\s]+\.[^@\s]+$'),
  referral_code text not null unique default substr(md5(random()::text), 1, 8),
  referred_by text references public.waitlist (referral_code),
  created_at timestamptz not null default now()
);

-- RLS on and no policies: the browser cannot read the list of emails.
alter table public.waitlist enable row level security;

-- The only way in: join (or look up yourself) and get your code and place.
create or replace function public.join_waitlist(p_email text, p_ref text default null)
returns table (code text, queue_position bigint, referrals bigint)
language plpgsql
security definer
set search_path = public
as $$
declare
  v_row public.waitlist%rowtype;
  v_ref text;
begin
  select w.referral_code into v_ref from public.waitlist w where w.referral_code = p_ref;

  insert into public.waitlist (email, referred_by)
  values (lower(trim(p_email)), v_ref)
  on conflict (email) do update set email = excluded.email
  returning * into v_row;

  return query
  select
    v_row.referral_code,
    greatest(
      1,
      (select count(*) from public.waitlist w where w.created_at <= v_row.created_at)
      - 5 * (select count(*) from public.waitlist w where w.referred_by = v_row.referral_code)
    ),
    (select count(*) from public.waitlist w where w.referred_by = v_row.referral_code);
end;
$$;

revoke all on function public.join_waitlist(text, text) from public;
grant execute on function public.join_waitlist(text, text) to anon, authenticated;
```

### Lovable docs

https://docs.lovable.dev/

### Supabase Row Level Security guide

https://supabase.com/docs/guides/database/postgres/row-level-security


## Build instructions by tool

### Claude Code

Open a terminal in an empty folder, run `claude`, then paste the prompt.

```text
Build the "Waitlist Landing Page with Referrals" app from the OwnlyPlans blueprint at https://wonly.dhfm.in/builder-4392ac/waitlist-with-referrals-lovable/.
Stack: Lovable, React, Supabase, Tailwind.
Follow the plan's steps in order: Write your one-line pitch → Generate the landing page → Create the private waitlist → Join flow with your place in line → Test referrals → Stop junk sign-ups → Publish and share.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Claude Code.)
```

### Cursor

Open an empty folder in Cursor, start an Agent chat, then paste the prompt.

```text
Build the "Waitlist Landing Page with Referrals" app from the OwnlyPlans blueprint at https://wonly.dhfm.in/builder-4392ac/waitlist-with-referrals-lovable/.
Stack: Lovable, React, Supabase, Tailwind.
Follow the plan's steps in order: Write your one-line pitch → Generate the landing page → Create the private waitlist → Join flow with your place in line → Test referrals → Stop junk sign-ups → Publish and share.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Cursor.)
```

### Lovable

Start a new Lovable project and paste the prompt as your first message.

```text
Build the "Waitlist Landing Page with Referrals" app from the OwnlyPlans blueprint at https://wonly.dhfm.in/builder-4392ac/waitlist-with-referrals-lovable/.
Stack: Lovable, React, Supabase, Tailwind.
Follow the plan's steps in order: Write your one-line pitch → Generate the landing page → Create the private waitlist → Join flow with your place in line → Test referrals → Stop junk sign-ups → Publish and share.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Lovable.)
```

## Definition of done

- Every build step is complete and the app runs locally.
- The main user flow works end to end.
- Share your build on OwnlyPlans with a demo link, build time and tool.
