Skip to main content
RapidDev - Software Development Agency

How to Build Lead generation tool with V0

Build a multi-step lead capture tool with V0 using Next.js, Supabase, and shadcn/ui. Features conditional form logic, automatic lead scoring, a Kanban pipeline board, and embeddable form pages — all with server-side scoring to keep your rules private. Takes about 1-2 hours.

What you'll build

  • Multi-step lead capture form with conditional logic and progress indicators
  • Server-side lead scoring engine that assigns hot/warm/cold tiers based on configurable rules
  • Kanban-style pipeline board with drag-and-drop lead stage management
  • Embeddable public form pages with UTM parameter tracking and source attribution
  • Lead detail sidebar with full response history, score breakdown, and stage timeline
  • Form builder interface for creating and editing multi-step capture forms
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate11 min read1-2 hoursV0 Premium or higherApril 2026RapidDev Engineering Team
TL;DR

Build a multi-step lead capture tool with V0 using Next.js, Supabase, and shadcn/ui. Features conditional form logic, automatic lead scoring, a Kanban pipeline board, and embeddable form pages — all with server-side scoring to keep your rules private. Takes about 1-2 hours.

What you're building

Marketing teams spend thousands on lead generation tools like HubSpot and Typeform. A custom-built lead capture system gives you full control over the form experience, scoring logic, and pipeline management without per-seat pricing.

V0 generates the multi-step form UI, pipeline Kanban board, and scoring API from prompts. Connect Supabase via the Connect panel for the database, and use Server Components for the pipeline dashboard. The form builder and Kanban board use client components for interactivity.

The architecture uses public form pages generated with generateStaticParams for fast loading, an API route for lead submission and scoring, Supabase for data storage, and a Kanban pipeline dashboard for managing leads through stages.

Final result

A complete lead generation tool with multi-step capture forms, automatic scoring, a Kanban pipeline board, and UTM parameter tracking.

Tech stack

V0AI Code Generator
Next.jsFull-Stack Framework
Tailwind CSSStyling
shadcn/uiComponent Library
SupabaseDatabase

Prerequisites

  • A V0 account (Premium or higher recommended)
  • A Supabase project (free tier works — connect via V0's Connect panel)
  • Your lead qualification criteria (what makes a lead hot, warm, or cold)
  • Form fields you want to capture (company size, budget, timeline, etc.)

Build steps

1

Set up the database schema for forms, leads, and pipeline

Create the Supabase schema with tables for form definitions, lead submissions, pipeline stages, and lead-stage assignments. The forms table stores step definitions and scoring rules as JSONB.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Build a lead generation tool. Create a Supabase schema:
3// 1. forms: id (uuid PK), name (text), slug (text UNIQUE), steps (jsonb), scoring_rules (jsonb), redirect_url (text), owner_id (uuid FK to auth.users)
4// 2. leads: id (uuid PK), form_id (uuid FK to forms), email (text), name (text), company (text), responses (jsonb), score (int DEFAULT 0), status (text DEFAULT 'new'), source (text), utm_params (jsonb), created_at (timestamptz)
5// 3. pipeline_stages: id (uuid PK), name (text), position (int), color (text)
6// 4. lead_stage: lead_id (uuid FK to leads), stage_id (uuid FK to pipeline_stages), moved_at (timestamptz), moved_by (uuid FK to auth.users)
7// Add RLS policies. Seed pipeline_stages with: New, Contacted, Qualified, Proposal, Won, Lost.
8// Generate SQL and TypeScript types.

Pro tip: Store scoring_rules as JSONB in the forms table — this lets you configure different scoring logic per form without changing code.

Expected result: Supabase is connected with all tables created, pipeline stages seeded, and RLS policies active.

2

Build the multi-step lead capture form

Create the public-facing form page that walks visitors through multiple steps with conditional logic. Each step shows different fields based on previous answers. UTM parameters from the URL are captured automatically.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Create a multi-step lead form at app/f/[slug]/page.tsx.
3// Requirements:
4// - Fetch the form definition by slug from Supabase (static generation with generateStaticParams)
5// - Parse the steps jsonb to render each step's fields dynamically
6// - Use shadcn/ui Input, Select, RadioGroup based on field type from the steps config
7// - Show a Progress bar at the top showing step X of Y
8// - Navigation: 'Next' Button advances, 'Back' Button goes back
9// - On final step, show a 'Submit' Button that POSTs to /api/leads with all responses + UTM params from URL searchParams
10// - After submit, redirect to the form's redirect_url or show a thank-you Card
11// - Capture utm_source, utm_medium, utm_campaign, utm_content from the page URL automatically
12// - Make it responsive and mobile-friendly with max-w-lg centered layout

Expected result: The public form page renders dynamic multi-step forms with progress tracking, field validation, and UTM parameter capture.

3

Create the server-side lead scoring engine

Build the API route that receives lead submissions, calculates a score based on the form's scoring rules, assigns a tier (hot/warm/cold), and stores the lead. Scoring logic runs server-side so it never leaks to visitors.

app/api/leads/route.ts
1import { createClient } from '@supabase/supabase-js'
2import { NextRequest, NextResponse } from 'next/server'
3
4const supabase = createClient(
5 process.env.SUPABASE_URL!,
6 process.env.SUPABASE_SERVICE_ROLE_KEY!
7)
8
9function calculateScore(
10 responses: Record<string, string>,
11 rules: { field: string; value: string; points: number }[]
12): number {
13 let score = 0
14 for (const rule of rules) {
15 if (responses[rule.field] === rule.value) {
16 score += rule.points
17 }
18 }
19 return score
20}
21
22function getTier(score: number): string {
23 if (score >= 80) return 'hot'
24 if (score >= 40) return 'warm'
25 return 'cold'
26}
27
28export async function POST(req: NextRequest) {
29 const { form_id, email, name, company, responses, source, utm_params } =
30 await req.json()
31
32 const { data: form } = await supabase
33 .from('forms')
34 .select('scoring_rules')
35 .eq('id', form_id)
36 .single()
37
38 const score = form?.scoring_rules
39 ? calculateScore(responses, form.scoring_rules)
40 : 0
41
42 const { data: lead, error } = await supabase
43 .from('leads')
44 .insert({
45 form_id,
46 email,
47 name,
48 company,
49 responses,
50 score,
51 status: getTier(score),
52 source: source || 'direct',
53 utm_params: utm_params || {},
54 })
55 .select()
56 .single()
57
58 if (error) {
59 return NextResponse.json({ error: error.message }, { status: 500 })
60 }
61
62 // Assign to 'New' pipeline stage
63 const { data: newStage } = await supabase
64 .from('pipeline_stages')
65 .select('id')
66 .eq('name', 'New')
67 .single()
68
69 if (newStage) {
70 await supabase.from('lead_stage').insert({
71 lead_id: lead.id,
72 stage_id: newStage.id,
73 moved_at: new Date().toISOString(),
74 })
75 }
76
77 return NextResponse.json({ success: true, lead_id: lead.id })
78}

Expected result: Lead submissions are scored server-side based on configurable rules and automatically assigned to the 'New' pipeline stage.

4

Build the Kanban pipeline dashboard

Create the pipeline management page showing leads organized by stage in a Kanban board. Each lead card shows name, company, score badge, and source. Leads can be moved between stages via a Server Action.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Create a pipeline Kanban board at app/leads/page.tsx.
3// Requirements:
4// - Fetch all pipeline_stages ordered by position, with leads in each stage
5// - Display as horizontal columns (one per stage) with the stage name and count as header
6// - Each lead shows as a shadcn/ui Card: name, company, email, score Badge (hot=red, warm=yellow, cold=blue), source, created_at
7// - Clicking a lead Card opens a Sheet sidebar with full details: all form responses, score breakdown, stage history timeline, and notes
8// - Add a Select dropdown on each lead to move it to a different pipeline stage (Server Action updates lead_stage)
9// - Add filters at the top: search Input, score tier Select (hot/warm/cold), source Select, date range
10// - Show total lead counts and conversion rate (Won / total) in summary Cards above the board
11// - Mobile layout: stack columns vertically with collapsible sections

Pro tip: Use V0's Vars tab to store webhook URLs for pushing leads to external CRMs like HubSpot or Salesforce. Add the webhook call in the lead submission API route after scoring.

Expected result: The pipeline page shows a Kanban board with leads organized by stage, score badges, and a detail Sheet sidebar.

5

Add the form builder and deploy

Create an interface for building and editing lead capture forms with step configuration, field types, and scoring rules. Then deploy to production.

prompt.txt
1// Paste this prompt into V0's AI chat:
2// Create a form builder at app/forms/[id]/edit/page.tsx.
3// Requirements:
4// - Fetch the form by ID, show current steps and fields
5// - Each step is a Card with: step title Input, list of fields below
6// - Each field has: label Input, type Select (text/email/select/radio/number), options Textarea (for select/radio, comma-separated), required Switch
7// - Add Field Button appends a new field to the current step
8// - Add Step Button appends a new step
9// - Scoring Rules section: for each select/radio field, show a Table where you assign points to each option value
10// - Save Button uses a Server Action to update the form's steps and scoring_rules jsonb
11// - Preview Button opens the form in a new tab at /f/[slug]
12// - Use shadcn/ui Accordion for collapsible steps, Switch for required toggle, and Separator between sections

Expected result: The form builder lets you configure multi-step forms with field types, scoring rules, and a live preview link. The app is deployed to Vercel.

Complete code

app/api/leads/route.ts
1import { createClient } from '@supabase/supabase-js'
2import { NextRequest, NextResponse } from 'next/server'
3
4const supabase = createClient(
5 process.env.SUPABASE_URL!,
6 process.env.SUPABASE_SERVICE_ROLE_KEY!
7)
8
9interface ScoringRule {
10 field: string
11 value: string
12 points: number
13}
14
15function calculateScore(
16 responses: Record<string, string>,
17 rules: ScoringRule[]
18): number {
19 let score = 0
20 for (const rule of rules) {
21 if (responses[rule.field] === rule.value) {
22 score += rule.points
23 }
24 }
25 return score
26}
27
28export async function POST(req: NextRequest) {
29 const body = await req.json()
30 const { form_id, email, name, company, responses, utm_params } = body
31
32 if (!form_id || !email) {
33 return NextResponse.json({ error: 'Missing fields' }, { status: 400 })
34 }
35
36 const { data: form } = await supabase
37 .from('forms')
38 .select('scoring_rules')
39 .eq('id', form_id)
40 .single()
41
42 const score = form?.scoring_rules
43 ? calculateScore(responses, form.scoring_rules)
44 : 0
45
46 const tier = score >= 80 ? 'hot' : score >= 40 ? 'warm' : 'cold'
47
48 const { data: lead, error } = await supabase
49 .from('leads')
50 .insert({
51 form_id, email, name, company,
52 responses, score, status: tier,
53 source: utm_params?.utm_source || 'direct',
54 utm_params: utm_params || {},
55 })
56 .select('id')
57 .single()
58
59 if (error) {
60 return NextResponse.json({ error: error.message }, { status: 500 })
61 }
62
63 return NextResponse.json({ success: true, lead_id: lead.id, score, tier })
64}

Customization ideas

CRM webhook integration

Add a webhook call in the lead submission API that sends new leads to HubSpot, Salesforce, or any CRM via their REST API. Store webhook URLs in the Vars tab.

Email notification on hot leads

Send an instant email alert via Resend when a lead scores as 'hot', including the lead's name, company, score, and a link to the pipeline dashboard.

A/B testing for form variants

Create multiple form variants with different step orders or questions and randomly assign visitors to measure which version generates higher-scoring leads.

Lead enrichment via Clearbit

After capturing a lead's email, call the Clearbit API to auto-populate company name, industry, employee count, and revenue data.

Common pitfalls

Pitfall: Running the scoring engine on the client side

How to avoid: Run the scoring logic in the API route (server-side). The client only submits responses; the server fetches rules from the database, calculates the score, and stores the result.

Pitfall: Not capturing UTM parameters from the form URL

How to avoid: Extract utm_source, utm_medium, utm_campaign from the page URL searchParams and include them in the lead submission payload. Store them in the utm_params jsonb column.

Pitfall: Making the public form page a client component unnecessarily

How to avoid: Use generateStaticParams to statically generate form pages by slug. Only the interactive step navigation and form submission need 'use client' — extract them as a child component.

Pitfall: Using NEXT_PUBLIC_ prefix for the service role key

How to avoid: Store SUPABASE_SERVICE_ROLE_KEY in V0's Vars tab without any prefix. Only use it in API routes.

Best practices

  • Run lead scoring server-side to keep your qualification criteria private — never expose scoring rules to visitors
  • Use generateStaticParams for public form pages so they load instantly from the CDN edge
  • Store scoring rules as JSONB in the forms table so you can configure different scoring per form without code changes
  • Capture UTM parameters automatically from the form URL for accurate source attribution
  • Use V0's Vars tab to store webhook URLs for CRM integrations — this keeps credentials out of your code
  • Use Server Components for the pipeline dashboard and client components only for the interactive Kanban board and form steps
  • Add a unique index on (lead_id, stage_id) in lead_stage to prevent duplicate stage assignments
  • Use V0's Design Mode (Option+D) to adjust the form styling, Kanban card layout, and Badge colors without spending credits

AI prompts to try

Copy these prompts to build this project faster.

ChatGPT Prompt

I'm building a lead generation tool with Next.js App Router and Supabase. I need a server-side lead scoring engine. The scoring rules are stored as JSONB in the forms table: an array of {field, value, points} objects. When a lead submits their responses, I need to match their answers against the rules, sum the points, and assign a tier (hot >= 80, warm >= 40, cold < 40). Please write the TypeScript function and the API route at app/api/leads/route.ts.

Build Prompt

Create a Kanban pipeline board component for managing leads. It should have horizontal columns (one per pipeline stage), each with a header showing stage name, color indicator, and lead count. Lead cards show name, company, score Badge, and source. Clicking a card opens a Sheet with full details. Each card has a Select dropdown to move to a different stage via a Server Action. Make the pipeline responsive — stack vertically on mobile.

Frequently asked questions

How does the lead scoring work?

Each form has scoring_rules stored as JSONB — an array of {field, value, points} objects. When a lead submits, the API route matches their responses against the rules, sums the points, and assigns a tier: hot (80+), warm (40-79), or cold (below 40). The scoring logic runs server-side so it is never visible to form visitors.

Can I embed the form on my existing website?

Yes. The form page at /f/[slug] is a standalone page that works in an iframe. Add an iframe tag pointing to your deployed URL with the form slug. UTM parameters pass through the URL for source tracking.

Do I need a paid V0 plan?

Premium ($20/month) is recommended. The lead generation tool has multiple complex pages (multi-step form, Kanban board, form builder) that require several prompts to build.

Can I push leads to my existing CRM?

Yes. Add a webhook call in the lead submission API route that sends the lead data to HubSpot, Salesforce, or any CRM with a REST API. Store the webhook URL in V0's Vars tab to keep it out of your code.

How do I track which marketing channel generates the best leads?

The form automatically captures UTM parameters (utm_source, utm_medium, utm_campaign) from the URL. You can filter leads by source in the pipeline dashboard and compare average scores across channels.

How do I deploy the lead generation tool?

Click Share in V0, then Publish to Production. The public form pages are statically generated for fast loading. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY in the Vars tab before deploying.

Can RapidDev help build a custom lead generation tool?

Yes. RapidDev has built over 600 apps including lead capture systems with advanced scoring, CRM integrations, and marketing automation workflows. Book a free consultation to discuss your requirements.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help building your app?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.