Create a high-converting lead generation tool with Lovable using step-by-step guides, templates and tips to capture more qualified leads for teams

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
The quickest, safest path in Lovable is to build a small single-page form that posts leads directly to Supabase's REST API using Lovable Cloud Secrets for the Supabase URL and anon key. You can do this entirely inside Lovable Chat Mode (no terminal). Create the UI files, a tiny client-side submit helper that reads secrets injected at runtime, preview to test, and then Publish. If you need server-only keys or advanced transforms, export to GitHub (outside Lovable) and run server builds there.
A simple lead-capture SPA inside your Lovable project: a form (name, email, message) that submits to a Supabase table called leads via the Supabase REST endpoint. Secrets (SUPABASE_URL and SUPABASE_ANON\_KEY) will be configured in Lovable Cloud Secrets so keys aren’t hard-coded. No terminal required.
Paste each of the prompts below into Lovable chat in sequence. Each is explicit about file changes and acceptance criteria.
Prompt 1 — Create the lead form page and client submit logic
if (!SUPABASE_URL || !SUPABASE_ANON_KEY) {
throw new Error('Missing Supabase secrets');
}
const res = await fetch(${SUPABASE_URL}/rest/v1/leads, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': SUPABASE_ANON_KEY,
'Authorization': Bearer ${SUPABASE_ANON_KEY},
'Prefer': 'return=representation'
},
body: JSON.stringify({ name, email, message })
});
if (!res.ok) {
const text = await res.text();
throw new Error(Supabase error: ${res.status} ${text});
}
return res.json();
}
// src/pages/LeadCapture.jsx
import React, { useState } from 'react';
import { submitLead } from '../lib/supabaseClient';
export default function LeadCapture() {
const [form, setForm] = useState({ name: '', email: '', message: '' });
const [status, setStatus] = useState(null);
async function handleSubmit(e) {
e.preventDefault();
setStatus('sending');
try {
await submitLead(form);
setStatus('sent');
setForm({ name: '', email: '', message: '' });
} catch (err) {
setStatus('error: ' + err.message);
}
}
return (
<div style={{maxWidth:480, margin:'0 auto', padding:20}}>
</li>
<li><b>Acceptance criteria</b>:
<ul>
<li>Files exist at the specified paths.</li>
<li>The page renders in Preview and shows the form and status messages.</li>
</ul>
</li>
<li><b>Secrets / integration setup</b>:
<ul>
<li>Do NOT put keys in files. Add SUPABASE_URL and SUPABASE_ANON\_KEY in Lovable Cloud Secrets (instructions in next prompt).</li>
<li>Ensure a Supabase table named <b>leads</b> exists with at least columns: <b>name text, email text, message text, created\_at timestamp default now()</b>. Create this in the Supabase dashboard (outside Lovable).</li>
</ul>
</li>
</ul>
<p><b>Prompt 2 — Configure runtime secret exposure helper and route the page into app</b></p>
<ul>
<li><b>Goal</b>: Ensure secrets are available to browser entry and add LeadCapture to app routes or main page.</li>
<li><b>Files to modify</b>:
<ul>
<li>modify your app root (example paths: <b>src/App.jsx</b> or <b>src/main.jsx</b> depending on project). If a different structure exists, update the root that mounts React.</li>
<li>create or modify <b>public/expose-secrets.js</b> to expose Lovable secrets at runtime (Lovable injects secrets into process.env at build; some runtimes need window exposure).</li>
</ul>
</li>
<li><b>Code examples to add (tell Lovable to patch these files)</b>:
// public/expose-secrets.js
// This file will be included in index.html to make secrets available at runtime.
// Lovable will substitute process.env.* at build or you can map them here.
window.__LOVABLE_SECRETS = {
// Lovable will replace these during build with actual secret values if supported
SUPABASE_URL: process.env.SUPABASE_URL,
SUPABASE_ANON_KEY: process.env.SUPABASE_ANON_KEY
};
// src/App.jsx
import React from 'react';
import LeadCapture from './pages/LeadCapture';
export default function App() {
return
}
</li>
<li><b>Acceptance criteria</b>:
<ul>
<li>App shows LeadCapture UI on root route in Preview.</li>
<li>window.\__LOVABLE_SECRETS contains the SUPABASE\_\* values in the browser (inspect in Preview devtools).</li>
</ul>
</li>
<li><b>Secrets needed</b>: SUPABASE_URL, SUPABASE_ANON\_KEY in Lovable Cloud Secrets UI (see next prompt for steps).</li>
</ul>
<p><b>Prompt 3 — Add Secrets in Lovable Cloud and test</b></p>
<ul>
<li><b>Goal</b>: Add the two secrets to Lovable Cloud and run Preview to test form submission.</li>
<li><b>Steps to do in Lovable UI (not code)</b>:
<ul>
<li>Open Lovable Cloud → Secrets (or Environment) UI.</li>
<li>Create secret <b>SUPABASE\_URL</b> with value e.g. https://xyzcompany.supabase.co</li>
<li>Create secret <b>SUPABASE_ANON_KEY</b> with your project anon key from Supabase dashboard.</li>
<li>Save and then open Preview. (No terminal needed.)</li>
</ul>
</li>
<li><b>Acceptance criteria</b>:
<ul>
<li>Preview loads and window.\__LOVABLE_SECRETS shows non-empty SUPABASE_URL and SUPABASE_ANON\_KEY.</li>
<li>Submitting the form returns status "sent" and the new row appears in the Supabase table (verify in Supabase dashboard).</li>
</ul>
</li>
</ul>
<h3>How to verify in Lovable Preview</h3>
<ul>
<li>Open Preview, navigate to the app, fill form and submit. You should see status "sending" then "sent".</li>
<li>Confirm by checking the <b>leads</b> table in Supabase dashboard — a new record should appear with submitted values.</li>
<li>If error, open browser devtools in Preview to inspect network request and response.</li>
</ul>
<h3>How to Publish / re-publish (if applicable)</h3>
<ul>
<li>Use Lovable's Publish button (top-right). Publishing picks up updated files and current Secrets from Lovable Cloud.</li>
<li>If you change Secrets later, re-Publish so builds include them.</li>
</ul>
<h3>Common pitfalls in Lovable (and how to avoid them)</h3>
<ul>
<li><b>Secrets not set</b>: Preview shows missing-secret error. Fix in Lovable Secrets UI and re-preview.</li>
<li><b>CORS / incorrect headers</b>: Ensure you send both apikey and Authorization: Bearer headers; Supabase requires them for REST inserts.</li>
<li><b>Wrong table schema/name</b>: Create the <b>leads</b> table and columns in Supabase dashboard before testing.</li>
<li><b>Exposing service-role key</b>: Never put a Supabase service\_role key in client-side secrets. Use the anon key for client inserts or move to server via GitHub export if you need elevated permissions.</li>
<li><b>Need server-only logic</b>: Labelled “outside Lovable (terminal required)” — export to GitHub and implement serverless endpoints there.</li>
</ul>
<h3>Validity bar</h3>
<ul>
<li>This plan uses only Lovable Chat Mode file edits, Lovable Preview, Lovable Cloud Secrets UI, and Publish. It avoids any fake Lovable features. Anything requiring CLI/build beyond Lovable should be done via GitHub export/sync and is explicitly called out above.</li>
</ul>
This prompt helps an AI assistant understand your setup and guide to build the feature
This prompt helps an AI assistant understand your setup and guide to build the feature
This prompt helps an AI assistant understand your setup and guide to build the feature

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
The shortest practical answer: build a small backend that captures leads, deduplicates and validates input, calls an AI generation endpoint (OpenAI) to create personalized outreach, stores the result and metadata in a database (Supabase), and present a human-review UI. In Lovable, implement this using Chat Mode edits + file diffs, store secrets with the Secrets UI, use Preview to test UI flows, and export/sync to GitHub for production deploy (Vercel/Netlify) so you can run serverless API routes. Prioritize consent/PII handling, rate limits, prompt safety, and human-in-the-loop review.
Use Lovable to edit files and iterate in Chat Mode, set environment values in the Secrets UI, test with Preview, and when you need real server functions or CI/CD, sync/export to GitHub and deploy (Vercel/Netlify).
// pages/api/createLead.js
import { createClient } from '@supabase/supabase-js';
// create Supabase client from env (set these in Lovable Secrets)
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_KEY);
export default async function handler(req, res) {
// only POST
if (req.method !== 'POST') return res.status(405).end();
const { email, name, company } = req.body;
if (!email) return res.status(400).json({ error: 'Missing email' });
// dedupe
const { data: existing } = await supabase.from('leads').select('id').eq('email', email).limit(1);
if (existing?.length) return res.status(200).json({ ok: true, id: existing[0].id });
// store lead
const { data, error } = await supabase.from('leads').insert([{ email, name, company, status: 'new' }]).select().single();
if (error) return res.status(500).json({ error: error.message });
return res.status(200).json({ ok: true, lead: data });
}
// server/genMessage.js
export async function generateMessage(lead) {
// build a compact prompt for personalization
const prompt = `Write a short 3-sentence outreach email to ${lead.name || 'a contact'} at ${lead.company || 'their company'}. Be friendly and include a one-line value proposition.`;
const r = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
max_tokens: 200,
}),
});
const json = await r.json();
// basic safety: ensure text exists
return json.choices?.[0]?.message?.content?.trim() || '';
}
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.