TL;DR
The one-paragraph version before you dive in.
Paste the starter prompt into Lovable Build mode and get a working CRM scaffold with contacts, companies, a five-stage Kanban deal pipeline, and per-user RLS so each rep sees only their own pipeline. Full build with follow-ups runs ~150-250 credits on a Pro plan in 1-2 days.
Setup checklist
Complete these steps in Lovable before pasting the starter prompt — takes about 5 minutes.
Cloud tab settings
Database
Stores contacts, companies, deals, and activities — the four core CRM entities.
- 1Click the + button next to Preview in the top toolbar to open the Cloud tab
- 2Click Database — you'll see an empty Table Editor
- 3Leave it empty for now — the starter prompt creates the migration with all four tables
Auth
Email+password login for sales reps. Optional Google OAuth for one-click sign-in.
- 1Cloud tab → Users & Auth
- 2Confirm Email sign-in is enabled (it is by default)
- 3To enable Google OAuth later: Cloud tab → Users & Auth → Social providers → Google, paste your Google Cloud Console client ID and secret
- 4Set Site URL to your custom domain BEFORE deploying — Google OAuth redirect will fail if Site URL still points to the preview domain
Edge Functions
Handles outbound email via Resend so the API key never touches the client bundle.
- 1Cloud tab → Edge Functions (you don't need to create anything manually — the starter prompt scaffold generates the function file)
- 2After the starter prompt runs, click the Deploy button on the Edge Functions panel to deploy the send-email-to-contact function
Secrets (Cloud tab → Secrets)
RESEND_API_KEYPurpose: Allows the send-email-to-contact Edge Function to send outbound emails from your domain and log them to the activity timeline.
Where to get it: resend.com → API Keys → Create API Key. Free tier covers 3,000 emails/month.
Preflight checklist
- You're in a fresh Lovable project (Vite + React + TypeScript + Tailwind + shadcn/ui already scaffolded — that's the default)
- You're on Pro $25/mo — the full CRM chain runs ~150-250 credits and Free plan caps at ~30/mo
- Decide now: personal CRM (just you, per-user owner_id RLS) or multi-rep shared pipeline (org_id RLS via a members table). The starter prompt defaults to per-user — multi-tenant is follow-up #5 and costs an extra ~120 credits
The starter prompt — paste this first
Copy this. Paste it into Lovable Build mode (the default chat at the bottom-left of the editor). Hit send.
Build a CRM system. Stack assumptions: React + Vite + TypeScript + Tailwind + shadcn/ui (already scaffolded by Lovable), React Router v6 for routes, Supabase JS client against Lovable Cloud, dnd-kit for Kanban drag-drop.
## Database schema (create one migration)
Create four tables in the public schema:
1. `contacts` — id (uuid pk default gen_random_uuid()), owner_id (uuid not null references auth.users(id) on delete cascade), full_name (text not null), email (text), phone (text), company_id (uuid references companies(id)), status (text default 'new' check in ('new','contacted','qualified','disqualified')), notes (text), created_at (timestamptz default now()).
2. `companies` — id (uuid pk default gen_random_uuid()), owner_id (uuid references auth.users(id) on delete cascade), name (text not null), domain (text), industry (text), size_band (text), created_at (timestamptz default now()).
3. `deals` — id (uuid pk default gen_random_uuid()), owner_id (uuid references auth.users(id) on delete cascade), contact_id (uuid references contacts(id)), title (text not null), stage (text not null default 'lead' check in ('lead','qualified','proposal','won','lost')), value_cents (int default 0), expected_close_date (date), position (int default 0), created_at (timestamptz default now()), closed_at (timestamptz).
4. `activities` — id (uuid pk default gen_random_uuid()), deal_id (uuid references deals(id)), contact_id (uuid references contacts(id)), actor_id (uuid references auth.users(id) on delete cascade), type (text check in ('note','call','email','meeting')), body (text), occurred_at (timestamptz default now()).
Enable RLS on all four tables. Add per-user policies: SELECT/INSERT/UPDATE/DELETE on contacts, companies, deals all use `owner_id = auth.uid()`. For activities, create a SECURITY DEFINER plpgsql function `can_see_activity(p_activity_id uuid)` that runs as the function owner and returns true when `actor_id = auth.uid()`. Use it in the activities SELECT policy. Do NOT write the function in SQL language — use `LANGUAGE plpgsql` so it is not inlined.
## Layout
Create `src/layouts/AppLayout.tsx` — a two-column shell with a fixed left sidebar (240px) and scrollable main area. Sidebar has: logo, nav links (Dashboard, Contacts, Companies, Deals, Activities, Settings), bottom user avatar dropdown (Sign out). Create `src/components/AuthGuard.tsx` — calls `supabase.auth.getUser()`, shows a centered spinner while in flight, redirects to /login if no session.
## Pages and routes
- /login — email+password sign-in with shadcn form
- /dashboard — 3 KPI cards (deals by stage count, contacts added this week, revenue closed this month) + recent activities feed
- /contacts — searchable/filterable table (debounced 300ms), paginated 25/page, Add button opens a right Sheet. Columns: name, email, company, status badge, created date
- /contacts/:id — contact detail page with ContactDrawer showing full form + ActivityTimeline below it
- /companies — same table pattern, Add button opens Sheet
- /deals — Kanban board with five columns (Lead / Qualified / Proposal / Won / Lost) using dnd-kit. Each DealCard shows title, value (formatted dollars), contact name, expected close date. Drag a card to reorder within a column (update position) or move to a new stage (update stage + reset position). Also add a list-view toggle button
- /activities — chronological feed grouped by day, most-recent first
- /settings — placeholder card with current user email + Sign out
## Key components
- `KanbanBoard` — dnd-kit DndContext + SortableContext per column. onDragEnd updates deal.stage and deal.position. Position rebalancing: new_position = (prev_position + next_position) / 2. Optimistic update then await Supabase UPDATE
- `DealCard` — shadcn Card with drag handle icon, title, value badge, contact chip
- `ContactDrawer` — shadcn Sheet (right side) with react-hook-form form for all contact fields
- `ActivityTimeline` — vertical list of activity rows grouped by day (date as section header), each with type icon, actor name, body, time
- `AppTable` — reusable table wrapper with debounced search input, pagination (25/page), empty state illustration, loading skeleton rows
## Styling
Light + dark mode via shadcn ThemeProvider. Primary color: emerald-600. Kanban columns color-coded by stage: Lead (gray), Qualified (blue), Proposal (amber), Won (green), Lost (red). Table rows 36px compact density so reps can scan fast.
Generate migration first, then AppLayout + AuthGuard, then each page in the order above.What this prompt generates
- Creates a SQL migration with 4 tables (contacts, companies, deals, activities), per-user RLS policies, and a SECURITY DEFINER can_see_activity function
- Scaffolds AppLayout.tsx with sidebar nav, dark-mode toggle, and AuthGuard wrapper
- Generates /contacts, /companies, and /deals pages with the AppTable pattern and a working Kanban board using dnd-kit
- Builds DealCard, ContactDrawer, ActivityTimeline, and AppTable as reusable components
- Wires sign-in → AuthGuard → /dashboard → /deals Kanban flow you can test immediately in preview
Paste into: Lovable Build mode (the default chat at the bottom-left of the editor)
Expected output
What Lovable will generate after the starter prompt runs successfully.
Files
supabase/migrations/0001_crm_schema.sql4 tables + per-user RLS policies + can_see_activity SECURITY DEFINER function
src/layouts/AppLayout.tsxSidebar shell with nav, dark-mode toggle, user dropdown
src/components/AuthGuard.tsxSession check with loading spinner, redirects to /login if no session
src/components/KanbanBoard.tsxdnd-kit Kanban with 5 stages, drag-to-reorder + drag-to-stage-change
src/components/DealCard.tsxCompact deal card with drag handle, value badge, contact chip
src/components/ContactDrawer.tsxRight Sheet with react-hook-form for contact CRUD
src/components/ActivityTimeline.tsxDay-grouped vertical activity feed
src/components/AppTable.tsxReusable table wrapper with search, pagination, empty + loading states
src/pages/Dashboard.tsx3 KPI cards + recent activities feed
src/pages/Contacts.tsxContacts list + add drawer
src/pages/ContactDetail.tsxContact detail with form + ActivityTimeline
src/pages/Companies.tsxCompanies list + add drawer
src/pages/Deals.tsxKanban board + list-view toggle
src/pages/Login.tsxEmail+password sign-in form
supabase/functions/send-email-to-contact/index.tsDeno Edge Function that posts to Resend API and writes an activity row
Routes
Email+password sign-in
KPI cards and recent activity feed
Contacts list with search, filter, add drawer
Contact detail with full form and activity timeline
Companies list with add drawer
Kanban pipeline with drag-drop stage changes and list-view toggle
Chronological activity feed grouped by day
Current user info and sign-out
DB Tables
contacts| Column | Type |
|---|---|
| id | uuid primary key default gen_random_uuid() |
| owner_id | uuid not null references auth.users(id) on delete cascade |
| full_name | text not null |
| text | |
| phone | text |
| company_id | uuid references companies(id) |
| status | text default 'new' |
| notes | text |
| created_at | timestamptz default now() |
RLS: Per-user: SELECT/INSERT/UPDATE/DELETE using owner_id = auth.uid()
companies| Column | Type |
|---|---|
| id | uuid primary key default gen_random_uuid() |
| owner_id | uuid references auth.users(id) on delete cascade |
| name | text not null |
| domain | text |
| industry | text |
| size_band | text |
| created_at | timestamptz default now() |
RLS: Per-user: owner_id = auth.uid() for all operations
deals| Column | Type |
|---|---|
| id | uuid primary key default gen_random_uuid() |
| owner_id | uuid references auth.users(id) on delete cascade |
| contact_id | uuid references contacts(id) |
| title | text not null |
| stage | text not null default 'lead' |
| value_cents | int default 0 |
| expected_close_date | date |
| position | int default 0 |
| created_at | timestamptz default now() |
| closed_at | timestamptz |
RLS: Per-user: owner_id = auth.uid() for all operations
activities| Column | Type |
|---|---|
| id | uuid primary key default gen_random_uuid() |
| deal_id | uuid references deals(id) |
| contact_id | uuid references contacts(id) |
| actor_id | uuid references auth.users(id) on delete cascade |
| type | text check in ('note','call','email','meeting') |
| body | text |
| occurred_at | timestamptz default now() |
RLS: SELECT via SECURITY DEFINER function can_see_activity(p_activity_id). INSERT: actor_id = auth.uid()
Components
KanbanBoarddnd-kit board with 5 stage columns, drag-to-reorder and drag-to-change-stage
DealCardCompact card with drag handle, title, value, and contact chip
ContactDrawerRight-side Sheet with react-hook-form for contact create/edit
ActivityTimelineVertical day-grouped activity log
AppTableReusable table with search debounce, pagination, and skeleton loading
Follow-up prompts
Paste these into Agent Mode one by one, in order, after the starter prompt finishes.
Add activity timeline to contact and deal detail pages
Activity timeline + composer on contact and deal detail pages, grouped by day
Add an activity timeline to the ContactDetail page and to a new DealDetail page.
On ContactDetail:
- At the top of the page, show the contact form (already built).
- Below it, add an ActivityTimeline component. It fetches activities WHERE contact_id = {contactId} ordered by occurred_at DESC.
- Above the timeline, add an activity composer: a type dropdown (note / call / email / meeting) + textarea for body + Submit button. On submit, INSERT into activities with actor_id = auth.uid(), contact_id = contactId, occurred_at = now().
On DealDetail (new page at /deals/:id):
- Show a summary card (title, stage badge, value, expected close date, contact chip linking to ContactDetail).
- Below it, same ActivityTimeline + composer pattern but filtered by deal_id.
Group timeline entries by calendar day using a date section header (e.g., 'Today', 'Yesterday', 'Jun 23'). Each entry shows: type icon (Phone, Mail, MessageSquare, Calendar from lucide-react), actor full name (from profiles), body text, and relative time ('2 hours ago').
Route: add /deals/:id to App.tsx.When to use: Once the contacts and deals list pages render correctly
Wire Resend for outbound email logging
Outbound Resend email from contact detail page, logged automatically to activity timeline
Add outbound email capability so reps can send emails directly from the CRM and have them logged in the activity timeline.
1. Add RESEND_API_KEY to Cloud tab → Secrets (I've already done this).
2. Create Edge Function at supabase/functions/send-email-to-contact/index.ts. The function should:
- Accept POST with JSON body: { contact_id, subject, body_html, sender_name }
- Verify the caller is authenticated (check Authorization header via supabase.auth.getUser)
- POST to https://api.resend.com/emails with the RESEND_API_KEY from Deno.env.get('RESEND_API_KEY')
- On success, INSERT one row into activities: { actor_id: caller uid, contact_id, type: 'email', body: `Sent: ${subject}\n\n${body_text_version}` }
- Return { success: true } or a 4xx error with message
3. On ContactDetail, add a 'Send email' button that opens a Dialog with: Subject input, Body textarea, Send button. On send, call supabase.functions.invoke('send-email-to-contact', { body: {...} }) and refresh the ActivityTimeline after success.When to use: When you want every sent email logged to the timeline without using a separate email client
Add Google OAuth login
Google OAuth one-click sign-in with correct redirect URL configuration
Enable Google OAuth sign-in alongside the existing email+password flow.
1. In Google Cloud Console, create an OAuth 2.0 Client ID (type: Web application). Add these authorized redirect URIs:
- https://[your-lovable-preview-subdomain].lovable.app/auth/v1/callback
- https://[your-custom-domain.com]/auth/v1/callback
2. In Cloud tab → Users & Auth → Social providers → enable Google. Paste the client ID and client secret.
3. In Cloud tab → Users & Auth → URL Configuration: set Site URL to your production domain. Add both the preview domain and the production domain to Redirect URLs.
4. On the Login page, add a 'Continue with Google' Button that calls `supabase.auth.signInWithOAuth({ provider: 'google', options: { redirectTo: window.location.origin + '/dashboard' } })`. Place it above the email/password form with an 'or' divider.
5. Confirm AuthGuard handles the OAuth callback correctly — after redirect, supabase.auth.getSession() should return the user automatically.When to use: When you want one-click sign-in for reps instead of email+password
Add pipeline value forecast on the dashboard
Stage-weighted pipeline value forecast rendered as a recharts stacked bar chart
Add a pipeline forecast widget to the /dashboard page.
1. Create a Postgres RPC function `pipeline_forecast()` that returns:
SELECT stage, COUNT(*) as deal_count, SUM(value_cents) as total_cents
FROM deals
WHERE owner_id = auth.uid() AND stage NOT IN ('won','lost')
GROUP BY stage
2. Apply weighted win-rates: lead=10%, qualified=30%, proposal=60%, won=100%. Compute weighted_value_cents = total_cents * win_rate per stage.
3. On the Dashboard, call this RPC via supabase.rpc('pipeline_forecast'). Render the result as a stacked horizontal bar chart using recharts. Show each stage as a colored segment matching the Kanban column colors (gray/blue/amber). Include a legend and a 'Weighted value' total below the chart.
4. Refresh the chart every 60 seconds via a setInterval inside a useEffect. Show a skeleton placeholder while loading.When to use: When you have 20+ deals across stages and want to see forecasted revenue
Convert to multi-tenant orgs (advanced)
Multi-tenant org-scoped RLS so multiple reps share one pipeline
Convert the CRM from per-user ownership to multi-tenant org-scoped ownership so multiple reps can share the same pipeline.
1. Create two new tables:
- `orgs` — id (uuid pk), name (text not null), created_at (timestamptz)
- `members` — id (uuid pk), org_id (uuid references orgs(id)), user_id (uuid references auth.users(id)), role (text default 'member' check in ('owner','member')), joined_at (timestamptz default now()). UNIQUE(org_id, user_id).
2. Add org_id (uuid references orgs(id)) to contacts, companies, deals, activities. Backfill with a placeholder org for the current user.
3. Create a SECURITY DEFINER plpgsql function `is_org_member(p_org_id uuid)` that returns true when auth.uid() appears in members for that org. Use LANGUAGE plpgsql (not SQL) to prevent inlining.
4. Rewrite RLS on contacts, companies, deals, activities to use: `is_org_member(org_id)` for SELECT and `is_org_member(org_id) AND EXISTS(SELECT 1 FROM members WHERE org_id = t.org_id AND user_id = auth.uid())` for INSERT/UPDATE/DELETE.
5. Add an org switcher dropdown to the AppLayout sidebar — reads orgs the user belongs to from members join, writes active_org_id to React context. All queries use the active org_id from context.When to use: When you onboard a second user who needs to see and edit the shared pipeline
Lead-score contacts with Lovable AI
Gemini 3 Flash lead scoring badge on every contact with a 1-10 score and reasoning
Add AI-powered lead scoring to the /contacts page.
1. Create Edge Function `score-contact` at supabase/functions/score-contact/index.ts. It should:
- Accept POST with { contact_id }
- Fetch the contact row and their last 5 activities from Lovable Cloud
- Call the Lovable AI panel (Gemini 3 Flash — the default model in Cloud tab → AI) with a prompt: 'Given this contact data and recent activities, rate the lead quality from 1 to 10 and give a 1-sentence reason. Return JSON: {score: number, reason: string}'
- Parse the JSON response
- UPDATE contacts SET ai_score = score, ai_score_reason = reason, ai_scored_at = now() WHERE id = contact_id
- Return { score, reason }
2. Add two columns to contacts: ai_score (int), ai_score_reason (text), ai_scored_at (timestamptz).
3. On the Contacts list table, add an 'AI Score' column showing a colored badge (1-4 red, 5-7 amber, 8-10 green) or a 'Score' button if ai_score is null. Clicking Score calls the Edge Function for that contact.
4. Add a 'Score all unscored' button at the top of the Contacts page that iterates through contacts where ai_score IS NULL and calls score-contact for each, with a 1-second delay between calls to avoid rate limits.When to use: When you have 50+ contacts and want to triage which leads to call first
Common errors
Real error strings you'll see. Find yours, paste the fix prompt.
infinite recursion detected in policy for relation "deals"Your activities RLS policy joins back to deals to check ownership, and deals RLS in turn queries activities — a circular policy reference that Postgres detects and kills.
Create a SECURITY DEFINER plpgsql function can_see_activity(p_activity_id uuid) that runs as the function owner (bypassing RLS) and returns boolean by checking actor_id = auth.uid() directly on activities. Use LANGUAGE plpgsql — NOT LANGUAGE sql, because SQL functions get inlined and still recurse. Drop the old activities SELECT policy and replace it with one that calls can_see_activity(activities.id).
redirect_uri_mismatchSite URL in Supabase Auth is still set to your Lovable preview domain; when you deploy to your production domain Google's OAuth client rejects the redirect_uri because it was only registered for the preview URL.
Cloud tab → Users & Auth → URL Configuration: set Site URL to your production custom domain. Add BOTH the preview domain and the production domain to the Redirect URLs list. Then in Google Cloud Console → OAuth 2.0 Client → Authorized redirect URIs, add both domains. Sign out everywhere and try again.
column contacts.org_id does not existYou ran the multi-tenant migration (follow-up #5) but the page components still query contacts with the old per-user filter on owner_id instead of org_id — Lovable partially applied the refactor.
Search the codebase for all .from('contacts') calls. Update every query that filters by owner_id to filter by org_id instead. Confirm the AppLayout sidebar has an org switcher that writes the current org_id to React context, and that all queries read org_id from that context rather than hardcoding auth.uid().Drag reorders correctly in UI but reloading the page restores old orderThe Kanban onDragEnd handler updated local React state but never persisted the new position value to the database, or the gap-rebalancing math produced a duplicate position integer.
In KanbanBoard's onDragEnd callback, after computing new_position = (prev_position + next_position) / 2, run: await supabase.from('deals').update({ stage: newStage, position: newPosition }).eq('id', draggedDealId). Await the Supabase call before clearing the optimistic update flag so a network error doesn't silently revert.LinkedIn API rate limit exceeded / 429 on contact-enrichment featureLinkedIn's official API is locked down with strict scopes and hard daily limits even for partner apps — this is exactly where published Lovable CRM builders have hit walls in production.
Do not integrate LinkedIn directly. Use a third-party enrichment API (Hunter.io, Apollo.io, or Clearbit) via an Edge Function with the API key in Cloud tab → Secrets. Test the API call with curl manually before prompting Lovable to wire it up — saves 30+ credits on failed scaffolding.
Cost reality
What this build actually costs — no surprises on your card.
Recommended Lovable plan
Pro $25/mo recommended — the full CRM chain runs ~150-250 credits, above Pro's 100-credit monthly allowance, so plan on one $15 top-up (50 extra credits). If you do multi-tenant in follow-up #5, budget a second top-up.
Monthly run cost breakdown
~150-250 credits (starter ~50-80, six follow-ups ~280 if all done; most readers stop at 3 follow-ups for ~150 total) total| Item | Cost |
|---|---|
| Lovable Pro Drop to Free after build — the app runs on Lovable Cloud even while you're on Free | $25/mo |
| Lovable Cloud (Supabase) Free tier: 500MB DB easily holds 50K+ contacts, 50K MAU, 500K Edge invocations/mo | $0/mo at MVP |
| Supabase Pro (when you need it) Needed at ~10K email bodies stored in activities (500MB DB fills fast with large text) | $25/mo |
| Resend $20/mo for 50K — most CRMs stay under 3K/mo at early scale | $0/mo up to 3K emails |
| Custom domain Cloudflare or Porkbun | ~$10-15/yr |
Scaling notes: 500MB DB holds ~50K-200K contacts depending on note size. If you log every full email body in activities.body you'll hit 500MB at ~10K emails — either truncate to 500 chars or bump to Supabase Pro $25/mo at 8GB. Google OAuth is free forever regardless of users.
Production checklist
Steps to take before you share the URL with real users.
Domain & SSL
Connect custom domain before enabling Google OAuth
Lovable top-right → Publish → Custom domain → enter your domain → copy the CNAME record → add it in Cloudflare/Porkbun DNS. Then go Cloud tab → Users & Auth → URL Configuration and set Site URL to the custom domain BEFORE adding it to your Google OAuth client's redirect list.
Verify a sending domain in Resend so emails don't land in spam
resend.com → Domains → Add domain → copy the 3 DNS records (SPF, DKIM, DMARC) → add them in your DNS provider. Verification takes 5-30 minutes. Then update the Edge Function 'from' address to use your verified domain.
Backups
Enable Supabase point-in-time recovery before you have real customer data
Lovable Cloud runs on the Supabase Free tier which includes daily backups but no point-in-time recovery. If you migrate to your own Supabase project (Pro $25/mo), enable PITR in Supabase Dashboard → Settings → Backups.
Monitoring
Check Edge Function logs weekly when email sending is live
Cloud tab → Edge Functions → send-email-to-contact → Logs. Any 4xx or 5xx from Resend shows here. Set up a Resend webhook (resend.com → Webhooks) to receive bounce and complaint events and write them to an email_events table.
Frequently asked questions
Can I really build a CRM in Lovable as a single non-technical founder?
Yes, if you scope it to a personal CRM (just you) or a small team of 1-3 reps. The per-user RLS pattern in the starter prompt is designed for exactly this. Where Lovable struggles is multi-tenant orgs with fine-grained permissions across 10+ users — that's follow-up #5 and it costs an extra 120 credits and another day of iteration.
How is this different from just using HubSpot's free tier?
HubSpot Free is genuinely good for standard CRM (contacts, deals, pipeline, basic email tracking) and you should buy it if your workflow fits. Build in Lovable when you need a vertical-specific data model HubSpot literally cannot represent — for example, contact-per-property in real estate, contact-per-loan in lending, or contact-per-enrolled-patient in healthcare. You also get zero per-seat cost after the initial build, which matters once you have 5+ reps.
Multi-tenant from day one or single-tenant first?
Single-tenant first, always. The per-user owner_id RLS in the starter prompt is simpler, faster to build, and easier to debug. Convert to multi-tenant via follow-up #5 only when a second rep actually needs shared pipeline access. The refactor costs ~120 credits and one day — cheaper than building multi-tenant upfront and debugging org isolation under deadline pressure.
How do I avoid the LinkedIn API trap that other CRM builders have hit?
Do not integrate LinkedIn directly. LinkedIn's official API is locked down with hard daily limits even for approved partners. If contact enrichment is important to you, use a third-party enrichment service (Hunter.io, Apollo.io, or Clearbit) via an Edge Function with the API key in Cloud tab → Secrets. Always test the API with a manual curl call before prompting Lovable to build the integration — discovering a tier limitation 60 credits into the build is painful.
Can I import my existing HubSpot or Pipedrive data?
Yes, via CSV export/import. Export your contacts and companies from HubSpot or Pipedrive as CSV. Once your Lovable CRM is built, go to Cloud tab → Database → Table Editor → your contacts table → Import data, and upload the CSV. You'll need to map column names if they differ. For deals with activity history, you'll need a manual SQL import via the SQL Editor — paste a series of INSERT statements generated from the export file.
What's the realistic credit cost if I loop on retries?
The estimates (150-250 credits total) assume clean runs. In practice, expect 20-30% more credits for the first time you hit the can_see_activity recursion error, the Google OAuth redirect mismatch, or a missed RLS policy. Budget for one Pro plan top-up ($15 for 50 credits) and use the Try-to-fix button (free, no credits) as your first response to any error before re-prompting.
When should I export to GitHub and finish in Cursor instead of staying in Lovable?
Export when you need to make the same code change in 10+ files at once (e.g., renaming owner_id to org_id across all queries in the multi-tenant migration), when you want to add a library Lovable doesn't handle well (real-time Pusher channels, complex recharts configurations), or when you're debugging an error that Lovable's Try-to-fix has attempted 3+ times without success. Exporting to GitHub is one click in Lovable's top-right GitHub icon — then open in Cursor and finish the specific piece there.
Need a production-grade version?
RapidDev builds production-grade Lovable apps at $13K–$25K. Book a free 30-minute consultation.
Book a free consultation30-min call. No commitment.