Back to blog
InsightsJul 4, 202616 min read

AI-Native Development: How We Actually Build with Lovable, Replit, and Cursor

The exact multi-agent workflow we use to build features in 2-4 hours. Includes a worked example with real code from a notification system built with Lovable + Replit + Cursor.

AI-Native DevelopmentLovableReplitCursorWorkflow

Published

Jul 4, 2026

Updated

Jul 4, 2026

Category

Insights

Author

Bilal Mehmood

Relevant lane

Review the Integration Foundation Sprint

AI-Native Development: How We Actually Build with Lovable, Replit, and Cursor

On this page

AI-Native Development: How We Actually Build with Lovable, Replit, and Cursor

Last updated: July 2026. This guide reflects our actual workflow at TkTurners. No affiliate links.


What This Guide Covers

  • The exact multi-agent workflow we use to build features in 2-4 hours (not 2-4 days)
  • A worked example: building a real-time notification system using Lovable + Replit + Cursor, with the actual code and decisions
  • The 4 failure modes we've hit when combining AI tools (and how we avoid them now)
  • When to use which tool: our decision tree based on 50+ projects
  • The human checkpoints that catch what AI misses

Who this is for: Technical founders and senior developers who want to 3x their output without shipping broken code. If you're non-technical looking for a magic button, this isn't it — AI still requires technical oversight.

Who this is not for: Teams with heavy compliance requirements (SOC 2, HIPAA) where every line needs audit trails. Use AI for prototyping, not production, in those environments.

The Hard Truth: AI Tools Don't Talk to Each Other

Lovable builds a beautiful frontend. Replit Agent spins up a working backend. Cursor refactors code intelligently. But none of them know the others exist.

What this means in practice:

Last month, we were building a client dashboard. Lovable generated a gorgeous React component with a "Mark as Complete" button. Replit Agent built an API endpoint at /api/tasks/complete. But the button was calling /api/tasks/:id/complete (different URL). The feature looked perfect in the UI. Clicked the button. Nothing happened. 20 minutes of debugging to find a one-character URL mismatch.

This is the AI-native development problem: Each tool optimizes for its own output, not for integration. The human's job is no longer writing code. It's orchestrating agents and catching integration failures.

In our experience: A solo developer using AI tools thoughtfully ships 3x faster than a senior engineer writing everything manually. But a developer who blindly accepts AI output ships 2x slower because of the debugging debt.

Our Multi-Agent Workflow (The Real One)

We don't use one AI tool. We orchestrate three, with human checkpoints between each. Here's the actual workflow:

Step 1: Design in v0 (15-30 minutes)

What we do: Describe the UI component we need. v0 generates React + Tailwind code.

Example prompt we used last week:

"A notification dropdown for a SaaS dashboard. Shows unread count badge. Click opens dropdown with notification list. Each notification has: icon, title, message, timestamp. Mark as read button. Empty state when no notifications. Dark mode. Responsive."

What v0 gave us:

// v0 generated this in 45 seconds
export function NotificationDropdown() {
  const [notifications, setNotifications] = useState([]);
  const [unreadCount, setUnreadCount] = useState(0);
  const [isOpen, setIsOpen] = useState(false);

  // ... component code
}

Human checkpoint: Does the component match our design system? v0 uses its own color palette. We need to swap to our Tailwind config (slate-900 background, indigo-500 accents).

Time saved: 2 hours of manual component writing. Time spent fixing: 10 minutes (color swaps, icon imports).

Step 2: Build Backend in Replit Agent (20-40 minutes)

What we do: Describe the API we need. Replit Agent generates the full backend.

Example prompt:

"Express API for notifications. GET /api/notifications returns user's notifications. POST /api/notifications/:id/read marks as read. Use Supabase for database. Include auth middleware."

What Replit gave us:

// Replit generated this in 3 minutes
app.get('/api/notifications', async (req, res) => {
  const { data, error } = await supabase
    .from('notifications')
    .select('*')
    .eq('user_id', req.user.id)
    .order('created_at', { ascending: false });
    
  if (error) return res.status(500).json({ error: error.message });
  res.json(data);
});

Human checkpoint: Check the auth middleware. Replit used req.user.id but our auth system uses req.user.sub (Clerk convention). One-line fix, but without checking, the API returns 401 for every request.

Time saved: 3 hours of API boilerplate. Time spent fixing: 15 minutes (auth convention mismatch, adding RLS policies).

Step 3: Integrate in Cursor (30-60 minutes)

What we do: Open the Lovable frontend and Replit backend in Cursor. Use AI chat to wire them together and fix integration issues.

Real conversation we had with Cursor last week:

Us: "The notification dropdown from v0 is calling /api/notifications but the Replit backend is at localhost:3001. The frontend is at localhost:3000. Fix the API client setup."

Cursor: "I'll create an API client with the correct base URL and auth headers..."

[Cursor generates api.ts with axios instance, baseURL from env var, auth header interceptor]

But then:

Us: "The notifications aren't updating in real-time. When a new notification is created, the dropdown still shows old count."

Cursor: "You'll need WebSocket or polling. For simplicity, I'll add React Query with 30-second refetch..."

Us: "No, use Supabase realtime subscriptions. We already have Supabase client."

Cursor: "Got it. Here's the realtime subscription setup..."

What Cursor produced:

// Cursor-generated realtime subscription
useEffect(() => {
  const subscription = supabase
    .channel('notifications')
    .on('postgres_changes', 
      { event: 'INSERT', schema: 'public', table: 'notifications' },
      (payload) => {
        setNotifications(prev => [payload.new, ...prev]);
        setUnreadCount(prev => prev + 1);
      }
    )
    .subscribe();
    
  return () => subscription.unsubscribe();
}, []);

Human checkpoint: Test the realtime subscription. Supabase realtime has a 200 concurrent connections limit on free tier. For a dashboard with 1000 users, this breaks. We need to switch to polling or upgrade.

Decision: For this client (50 users), realtime is fine. Document the limitation for future scaling.

Time saved: 4 hours of integration work. Time spent fixing: 45 minutes (URL mismatch, auth headers, realtime limit check).

Worked Example: Building a Real-Time Notification System

Client: SaaS dashboard for marketing agencies Feature: Real-time notification system (new lead assigned, campaign completed, etc.) Timeline: 3 hours Tools: v0 (UI) + Replit (API) + Cursor (integration)

Hour 0: v0 — Design the Component

Prompt: "Notification bell icon with badge count. Dropdown panel showing notification list. Each item: colored icon, title, message preview, relative time. Mark as read on click. Empty state. Dark mode."

v0 output: Complete React component with Tailwind styling.

Fixes needed:

  1. Swap v0's default colors to our design system
  2. Add loading skeleton state (v0 didn't include)
  3. Add error state (v0 didn't include)

Result:

// After our fixes
export function NotificationBell() {
  const { notifications, unreadCount, markAsRead } = useNotifications();
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="relative">
      <button onClick={() => setIsOpen(!isOpen)}>
        <BellIcon className="w-6 h-6 text-slate-400" />
        {unreadCount > 0 && (
          <span className="absolute -top-1 -right-1 bg-indigo-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center">
            {unreadCount}
          </span>
        )}
      </button>
      
      {isOpen && (
        <NotificationPanel 
          notifications={notifications}
          onMarkAsRead={markAsRead}
        />
      )}
    </div>
  );
}

Hour 1: Replit — Build the API

Prompt: "Express API: GET /api/notifications (list, paginated), POST /api/notifications/:id/read, POST /api/notifications/mark-all-read. Supabase database. Auth required. Include created_at, read_at timestamps."

Replit output: Full CRUD API with auth middleware.

Fixes needed:

  1. Auth middleware used wrong user ID field (fixed in 5 minutes)
  2. Missing pagination (added limit/offset)
  3. Missing RLS policies on notifications table

Database schema we added:

CREATE TABLE notifications (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id UUID REFERENCES auth.users(id),
  type VARCHAR(50) NOT NULL, -- 'lead_assigned', 'campaign_completed', etc.
  title VARCHAR(255) NOT NULL,
  message TEXT,
  read_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW(),
  metadata JSONB -- flexible extra data
);

-- RLS: Users can only see their own notifications
ALTER TABLE notifications ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can read own notifications"
  ON notifications FOR SELECT
  USING (auth.uid() = user_id);

CREATE POLICY "Users can update own notifications"
  ON notifications FOR UPDATE
  USING (auth.uid() = user_id);

Hour 2: Cursor — Integration + Realtime

The integration work:

  1. API client setup

    • Base URL from env var
    • Auth header from Clerk session
    • Error handling with retry
  2. React Query for server state

    • Cache notifications for 30 seconds
    • Background refetch on window focus
    • Optimistic update on mark-as-read
  3. Supabase Realtime for live updates

    • Subscribe to INSERT on notifications table
    • Update local state on new notification
    • Play subtle sound (user preference)

The bug we hit:

Cursor's first attempt at realtime subscription missed the filter. It subscribed to ALL notifications table changes, not just the current user's. This means User A would see User B's notifications in real-time.

Fix:

// WRONG: Subscribes to all notifications
const subscription = supabase
  .channel('notifications')
  .on('postgres_changes', 
    { event: 'INSERT', schema: 'public', table: 'notifications' },
    callback
  )

// RIGHT: Filtered to current user only
const subscription = supabase
  .channel('notifications')
  .on('postgres_changes', 
    { 
      event: 'INSERT', 
      schema: 'public', 
      table: 'notifications',
      filter: `user_id=eq.${userId}`  // Critical filter!
    },
    callback
  )

This is why human review matters. AI generated code that worked functionally but leaked data between users.

Hour 3: Testing + Polish

Tests we wrote:

// Critical path test
describe('Notification System', () => {
  test('user sees only their notifications', async () => {
    const user1 = await createTestUser();
    const user2 = await createTestUser();
    
    await createNotification(user1.id, 'Test');
    await createNotification(user2.id, 'Test');
    
    const user1Notifs = await getNotifications(user1.token);
    expect(user1Notifs).toHaveLength(1);
    expect(user1Notifs[0].user_id).toBe(user1.id);
  });

  test('mark as read updates unread count', async () => {
    const user = await createTestUser();
    const notif = await createNotification(user.id, 'Test');
    
    await markAsRead(user.token, notif.id);
    
    const count = await getUnreadCount(user.token);
    expect(count).toBe(0);
  });

  test('realtime subscription receives new notification', async () => {
    const user = await createTestUser();
    const received = await waitForNotification(user.id, () => {
      createNotification(user.id, 'Realtime test');
    });
    expect(received.title).toBe('Realtime test');
  });
});

Polish we added:

  • Sound notification (toggle in settings)
  • Keyboard shortcut (N key opens dropdown)
  • Mobile responsive (full-screen overlay on small screens)
  • Loading skeleton while fetching

The 4 Failure Modes (And How We Avoid Them)

After 50+ projects, here are the patterns that break AI-native workflows:

Failure 1: The URL Mismatch

What happens: Frontend calls /api/notifications, backend serves /api/v1/notifications. Feature looks perfect. Nothing works.

How we avoid it now:

  1. Define API contract BEFORE generating code
  2. Use OpenAPI spec or simple markdown table
  3. Feed the spec to both frontend and backend AI tools

Our API contract template:

## Notifications API

| Method | Path | Request | Response | Auth |
|--------|------|---------|----------|------|
| GET | /api/notifications | Query: ?limit=20&offset=0 | Notification[] | Required |
| POST | /api/notifications/:id/read | - | { success: true } | Required |
| POST | /api/notifications/mark-all-read | - | { updated: number } | Required |

## Notification Object

| Field | Type | Required |
|-------|------|----------|
| id | UUID | Yes |
| type | string | Yes |
| title | string | Yes |
| message | string | No |
| read_at | timestamp | No |
| created_at | timestamp | Yes |

Time investment: 5 minutes writing spec. Time saved: 20-60 minutes debugging mismatches.

Failure 2: The Auth Assumption

What happens: Each AI tool assumes a different auth system. Lovable uses Supabase Auth. Replit uses JWT. Cursor assumes Clerk. They don't interoperate.

How we avoid it now:

  1. Pick ONE auth system per project
  2. Document the auth convention in a AUTH.md file
  3. Include auth requirements in EVERY AI prompt

Our auth prompt template:

"Use Clerk for auth. User ID is in req.auth.userId. Token is in req.headers.authorization. Always check auth before returning data."

Time investment: 2 minutes per prompt. Time saved: 15-30 minutes per auth mismatch.

Failure 3: The Database Leak

What happens: AI generates queries without RLS. User A sees User B's data. Security vulnerability.

How we avoid it now:

  1. Enable RLS on every table (non-negotiable)
  2. Test with two users before shipping
  3. Use row-level security policies, not application-level filtering

Our RLS checklist:

  • RLS enabled on all tables
  • Policies restrict to authenticated users
  • Policies filter by user_id
  • Tested with User A and User B accounts
  • No admin bypass unless explicitly required

Failure 4: The Scaling Surprise

What happens: AI uses the simplest solution. Works for 10 users. Breaks at 100.

Example: AI generates SELECT * FROM notifications and filters in memory. Fine for 50 rows. Crashes at 10,000.

How we avoid it now:

  1. Add pagination to EVERY list endpoint (default limit: 20)
  2. Add database indexes on query fields
  3. Document known limits ("Realtime works for < 200 concurrent users")

Our pagination standard:

// Every list endpoint
const DEFAULT_LIMIT = 20;
const MAX_LIMIT = 100;

app.get('/api/notifications', async (req, res) => {
  const limit = Math.min(
    parseInt(req.query.limit) || DEFAULT_LIMIT,
    MAX_LIMIT
  );
  const offset = parseInt(req.query.offset) || 0;
  
  const { data, error, count } = await supabase
    .from('notifications')
    .select('*', { count: 'exact' })
    .eq('user_id', req.user.id)
    .order('created_at', { ascending: false })
    .range(offset, offset + limit - 1);
    
  res.json({
    data,
    pagination: {
      total: count,
      limit,
      offset,
      hasMore: offset + limit < count
    }
  });
});

Decision Tree: Which Tool When

We don't use every tool for every project. Here's how we decide:

For New Features (Greenfield)

StepToolTimeWhen to Skip
1. UI Designv015-30 minSkip if using existing component library
2. Backend APIReplit Agent20-40 minSkip if API already exists
3. IntegrationCursor30-60 minNever skip — this is where bugs hide
4. TestingManual + Jest30-60 minNever skip — AI doesn't test edge cases
Total2-3 hoursvs. 1-2 days manually

For Bug Fixes (Brownfield)

SituationToolWhy
UI bugCursorContext of existing codebase
Logic errorCursorCan see full call stack
Performance issueManualAI often makes performance worse
Security fixManualNever trust AI with security

Rule: For bug fixes, use Cursor (not v0 or Replit) because it has full codebase context.

For Refactoring

Refactor TypeToolApproach
Extract componentCursorSelect code, ask to extract
Rename across codebaseCursorGlobal find/replace with AI
Upgrade dependenciesManualAI doesn't understand breaking changes
Architecture changeManualAI optimizes locally, breaks globally

FAQ

Q: How much faster is AI-native development really?

In our experience, 2-3x faster for greenfield features, 1.5x faster for bug fixes, and no faster (sometimes slower) for complex refactoring. The 3x speedup comes from AI handling boilerplate (CRUD APIs, form components, auth flows). The human still does architecture, security, and integration.

Example: The notification system above took 3 hours with AI. Our estimate for manual development: 8-10 hours. But the integration debugging (hour 2) still required senior-level knowledge.

Q: Do I need to be a senior developer to use AI tools effectively?

No, but you need to know what to check. Junior developers can ship faster with AI, but they miss security issues and integration bugs that seniors catch. Our recommendation: pair junior developers with AI tools and require senior review before shipping.

The minimum knowledge you need:

  • How auth works (JWT, sessions, cookies)
  • How databases work (SQL, RLS, indexing)
  • How HTTP works (status codes, headers, CORS)
  • Basic security (XSS, SQL injection, CSRF)

Without this foundation, you'll ship broken code faster.

Q: Which AI tool should I start with?

Start with Cursor. It's the most versatile — works with existing code, understands context, and has the best debugging experience. Add v0 when you need UI components and Replit when you need quick backend prototypes.

Our starter stack:

  1. Cursor (daily driver)
  2. v0 (UI components, 2-3x/week)
  3. Replit (backend prototypes, 1-2x/week)
  4. Lovable (full-stack experiments, occasional)

Q: What's the biggest mistake teams make with AI tools?

Treating AI output as production-ready without review. We see teams skip code review because "AI wrote it." That's how you get auth bypasses, data leaks, and performance disasters.

Our rule: AI-generated code goes through the same review process as human-written code. No exceptions.

Q: How do you handle AI tool costs?

ToolMonthly CostValue
Cursor Pro$20Essential
v0Free (Vercel)High
Replit Core$7Medium
ChatGPT Plus$20High
Total~$50/month

For a developer billing $150/hour, these tools pay for themselves in the first hour of saved time each month.

The Decision Checklist

Before adopting AI-native development, answer these:

  • My team has at least one senior developer who can review AI output
  • We have code review processes (AI doesn't replace review)
  • We have testing infrastructure (unit tests, integration tests)
  • We understand our auth system (JWT, sessions, or OAuth)
  • We have database RLS enabled (or plan to add it)
  • We're building greenfield features (not maintaining legacy code)
  • We can tolerate occasional AI hallucinations (wrong code that looks right)

If you can't check at least 5 of these, fix the gaps first. AI tools amplify your existing processes — good or bad.

What We Do at TkTurners

We build production software using AI-native workflows. Not experiments — actual client projects with real users and revenue.

AI-Native Development Sprint:

  • Week 1: Architecture design + AI tool setup
  • Week 2: Core features (AI-generated, human-reviewed)
  • Week 3: Integration, security, performance
  • Week 4: Testing, deployment, monitoring

Who it's for: Technical teams who want to ship 3x faster without sacrificing quality. Who it's not for: Teams looking for a no-code solution (AI still requires technical expertise) or teams with strict compliance requirements (use AI for prototyping, manual code for production).

Contact us if you want to discuss AI-native development for your team. We'll audit your current workflow and show you exactly where AI can help.


B

Bilal Mehmood

Co-founder

Bilal Mehmood is a TkTurners co-founder focused on AI automation, systems integration, and practical operational infrastructure for growing businesses.

Relevant service

Review the Integration Foundation Sprint

Explore the service lane
Need help applying this?

Turn the note into a working system.

If the article maps to a live operational bottleneck, we can scope the fix, the integration path, and the rollout.