# 🚀 Lovable Clone - Quick Start Guide > Hướng dẫn bắt đầu nhanh để build MVP trong 2-4 tuần --- ## 📋 Prerequisites ```bash # Required - Node.js >= 18.0.0 - npm hoặc pnpm - Git - PostgreSQL (hoặc Supabase account) # Optional but Recommended - Docker Desktop - VS Code - OpenAI API key hoặc Anthropic API key ``` --- ## 🏁 Quick Start (MVP trong 2 tuần) ### **Bước 1: Setup Project Structure** ```bash # Create monorepo npx create-turbo@latest lovable-clone cd lovable-clone # Structure lovable-clone/ ├── apps/ │ ├── web/ # Next.js frontend │ └── api/ # Backend API ├── packages/ │ ├── ui/ # Shared UI components │ ├── agent/ # AI agent logic │ ├── database/ # Prisma schema │ └── config/ # Shared configs └── turbo.json ``` ### **Bước 2: Initialize Frontend** ```bash cd apps/web # Create Next.js app npx create-next-app@latest . --typescript --tailwind --app # Install dependencies npm install @radix-ui/react-dialog @radix-ui/react-tabs npm install class-variance-authority clsx tailwind-merge npm install lucide-react npm install zustand npm install react-markdown npm install @uiw/react-textarea-code-editor # Install shadcn/ui npx shadcn-ui@latest init npx shadcn-ui@latest add button dialog input textarea tabs scroll-area ``` **File: `apps/web/app/page.tsx`** ```typescript 'use client'; import { useState } from 'react'; import { ChatPanel } from '@/components/chat-panel'; import { LivePreview } from '@/components/live-preview'; import { Sidebar } from '@/components/sidebar'; export default function Home() { return (
{/* Sidebar */} {/* Main Content */}
{/* Chat Panel */}
{/* Live Preview */}
); } ``` ### **Bước 3: Setup Backend API** ```bash cd apps/api # Initialize npm init -y npm install express cors dotenv npm install -D typescript @types/node @types/express tsx # AI dependencies npm install openai @anthropic-ai/sdk npm install langchain @langchain/openai # Initialize TypeScript npx tsc --init ``` **File: `apps/api/src/index.ts`** ```typescript import express from 'express'; import cors from 'cors'; import { chatRouter } from './routes/chat'; import { codegenRouter } from './routes/codegen'; const app = express(); app.use(cors()); app.use(express.json()); // Routes app.use('/api/chat', chatRouter); app.use('/api/codegen', codegenRouter); const PORT = process.env.PORT || 3001; app.listen(PORT, () => { console.log(`API server running on port ${PORT}`); }); ``` ### **Bước 4: Setup Database** **Option A: Supabase (Recommended - Easier)** ```bash # Install Supabase client npm install @supabase/supabase-js # Go to https://supabase.com # Create new project # Copy URL and anon key to .env ``` **File: `.env`** ```env SUPABASE_URL=https://xxxxx.supabase.co SUPABASE_ANON_KEY=eyJxxx... ``` **Option B: Local PostgreSQL + Prisma** ```bash cd packages/database npm install prisma @prisma/client npx prisma init # Edit prisma/schema.prisma (copy from ARCHITECTURE.md section VII) npx prisma migrate dev --name init npx prisma generate ``` ### **Bước 5: Implement Basic Chat** **File: `apps/web/components/chat-panel.tsx`** ```typescript 'use client'; import { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; import { ScrollArea } from '@/components/ui/scroll-area'; interface Message { role: 'user' | 'assistant'; content: string; } export function ChatPanel() { const [messages, setMessages] = useState([]); const [input, setInput] = useState(''); const [isLoading, setIsLoading] = useState(false); const sendMessage = async () => { if (!input.trim()) return; const userMessage: Message = { role: 'user', content: input }; setMessages(prev => [...prev, userMessage]); setInput(''); setIsLoading(true); try { // Call API const response = await fetch('http://localhost:3001/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: input, history: messages }) }); const data = await response.json(); const assistantMessage: Message = { role: 'assistant', content: data.response }; setMessages(prev => [...prev, assistantMessage]); } catch (error) { console.error('Error:', error); } finally { setIsLoading(false); } }; return (
{/* Header */}

Chat

{/* Messages */} {messages.map((msg, i) => (
{msg.content}
))}
{/* Input */}