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/notificationsbut the Replit backend is atlocalhost:3001. The frontend is atlocalhost: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:
- Swap v0's default colors to our design system
- Add loading skeleton state (v0 didn't include)
- 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:
- Auth middleware used wrong user ID field (fixed in 5 minutes)
- Missing pagination (added limit/offset)
- 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:
-
API client setup
- Base URL from env var
- Auth header from Clerk session
- Error handling with retry
-
React Query for server state
- Cache notifications for 30 seconds
- Background refetch on window focus
- Optimistic update on mark-as-read
-
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:
- Define API contract BEFORE generating code
- Use OpenAPI spec or simple markdown table
- 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:
- Pick ONE auth system per project
- Document the auth convention in a
AUTH.mdfile - Include auth requirements in EVERY AI prompt
Our auth prompt template:
"Use Clerk for auth. User ID is in
req.auth.userId. Token is inreq.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:
- Enable RLS on every table (non-negotiable)
- Test with two users before shipping
- 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:
- Add pagination to EVERY list endpoint (default limit: 20)
- Add database indexes on query fields
- 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)
| Step | Tool | Time | When to Skip |
|---|---|---|---|
| 1. UI Design | v0 | 15-30 min | Skip if using existing component library |
| 2. Backend API | Replit Agent | 20-40 min | Skip if API already exists |
| 3. Integration | Cursor | 30-60 min | Never skip — this is where bugs hide |
| 4. Testing | Manual + Jest | 30-60 min | Never skip — AI doesn't test edge cases |
| Total | 2-3 hours | vs. 1-2 days manually |
For Bug Fixes (Brownfield)
| Situation | Tool | Why |
|---|---|---|
| UI bug | Cursor | Context of existing codebase |
| Logic error | Cursor | Can see full call stack |
| Performance issue | Manual | AI often makes performance worse |
| Security fix | Manual | Never trust AI with security |
Rule: For bug fixes, use Cursor (not v0 or Replit) because it has full codebase context.
For Refactoring
| Refactor Type | Tool | Approach |
|---|---|---|
| Extract component | Cursor | Select code, ask to extract |
| Rename across codebase | Cursor | Global find/replace with AI |
| Upgrade dependencies | Manual | AI doesn't understand breaking changes |
| Architecture change | Manual | AI 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:
- Cursor (daily driver)
- v0 (UI components, 2-3x/week)
- Replit (backend prototypes, 1-2x/week)
- 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?
| Tool | Monthly Cost | Value |
|---|---|---|
| Cursor Pro | $20 | Essential |
| v0 | Free (Vercel) | High |
| Replit Core | $7 | Medium |
| ChatGPT Plus | $20 | High |
| 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.
Related Reading
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


