diff --git a/LOVABLE_CLONE_ADVANCED_FEATURES.md b/LOVABLE_CLONE_ADVANCED_FEATURES.md
new file mode 100644
index 00000000..a7e6d04c
--- /dev/null
+++ b/LOVABLE_CLONE_ADVANCED_FEATURES.md
@@ -0,0 +1,815 @@
+# π Lovable Clone - Advanced Features & Production Setup
+
+> Edge Functions, Webhooks, Testing, CI/CD, Monitoring, vΓ Advanced Features
+
+---
+
+# π Table of Contents
+
+1. [Supabase Edge Functions](#supabase-edge-functions)
+2. [Webhook Handlers](#webhook-handlers)
+3. [Testing Setup](#testing-setup)
+4. [CI/CD Pipeline](#cicd-pipeline)
+5. [Monitoring & Analytics](#monitoring--analytics)
+6. [Advanced Features](#advanced-features)
+7. [Production Deployment](#production-deployment)
+
+---
+
+# β‘ I. SUPABASE EDGE FUNCTIONS
+
+## 1. AI Chat Edge Function
+
+**File: `supabase/functions/chat-completion/index.ts`**
+
+```typescript
+import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
+import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.0';
+import OpenAI from 'https://esm.sh/openai@4.28.0';
+
+const corsHeaders = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type'
+};
+
+serve(async (req) => {
+ // Handle CORS
+ if (req.method === 'OPTIONS') {
+ return new Response('ok', { headers: corsHeaders });
+ }
+
+ try {
+ // Create Supabase client
+ const supabaseClient = createClient(
+ Deno.env.get('SUPABASE_URL') ?? '',
+ Deno.env.get('SUPABASE_ANON_KEY') ?? '',
+ {
+ global: {
+ headers: { Authorization: req.headers.get('Authorization')! }
+ }
+ }
+ );
+
+ // Verify user
+ const {
+ data: { user },
+ error: authError
+ } = await supabaseClient.auth.getUser();
+
+ if (authError || !user) {
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), {
+ status: 401,
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
+ });
+ }
+
+ const { message, conversationId, systemPrompt } = await req.json();
+
+ // Check usage limits
+ const { data: canGenerate } = await supabaseClient.rpc('can_generate', {
+ target_user_id: user.id,
+ required_tokens: 2000
+ });
+
+ if (!canGenerate) {
+ return new Response(
+ JSON.stringify({ error: 'Monthly token limit exceeded' }),
+ {
+ status: 429,
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
+ }
+ );
+ }
+
+ // Get conversation history
+ const { data: messages } = await supabaseClient
+ .from('messages')
+ .select('*')
+ .eq('conversation_id', conversationId)
+ .order('created_at', { ascending: true })
+ .limit(20); // Last 20 messages for context
+
+ // Initialize OpenAI
+ const openai = new OpenAI({
+ apiKey: Deno.env.get('OPENAI_API_KEY')
+ });
+
+ // Call OpenAI
+ const completion = await openai.chat.completions.create({
+ model: 'gpt-4-turbo-preview',
+ messages: [
+ {
+ role: 'system',
+ content: systemPrompt || 'You are Lovable, an AI that helps build web apps.'
+ },
+ ...(messages || []).map((msg: any) => ({
+ role: msg.role,
+ content: msg.content
+ })),
+ {
+ role: 'user',
+ content: message
+ }
+ ],
+ temperature: 0.7,
+ max_tokens: 4000
+ });
+
+ const response = completion.choices[0].message.content;
+ const tokensUsed = completion.usage?.total_tokens || 0;
+
+ // Save user message
+ await supabaseClient.from('messages').insert({
+ conversation_id: conversationId,
+ role: 'user',
+ content: message
+ });
+
+ // Save assistant message
+ await supabaseClient.from('messages').insert({
+ conversation_id: conversationId,
+ role: 'assistant',
+ content: response
+ });
+
+ // Track usage
+ await supabaseClient.from('usage').insert({
+ user_id: user.id,
+ tokens: tokensUsed,
+ type: 'chat'
+ });
+
+ return new Response(
+ JSON.stringify({ response, tokensUsed }),
+ {
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
+ }
+ );
+ } catch (error) {
+ return new Response(
+ JSON.stringify({ error: error.message }),
+ {
+ status: 500,
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
+ }
+ );
+ }
+});
+```
+
+## 2. Code Generation Edge Function
+
+**File: `supabase/functions/generate-code/index.ts`**
+
+```typescript
+import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
+import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.0';
+import Anthropic from 'https://esm.sh/@anthropic-ai/sdk@0.17.0';
+
+const corsHeaders = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type'
+};
+
+serve(async (req) => {
+ if (req.method === 'OPTIONS') {
+ return new Response('ok', { headers: corsHeaders });
+ }
+
+ try {
+ const supabaseClient = createClient(
+ Deno.env.get('SUPABASE_URL') ?? '',
+ Deno.env.get('SUPABASE_ANON_KEY') ?? '',
+ {
+ global: {
+ headers: { Authorization: req.headers.get('Authorization')! }
+ }
+ }
+ );
+
+ const {
+ data: { user }
+ } = await supabaseClient.auth.getUser();
+
+ if (!user) {
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), {
+ status: 401,
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
+ });
+ }
+
+ const { prompt, projectId, componentType } = await req.json();
+
+ // Load Lovable system prompt from storage
+ const { data: systemPromptData } = await supabaseClient.storage
+ .from('system-prompts')
+ .download('lovable-agent-prompt.txt');
+
+ const systemPrompt = await systemPromptData?.text();
+
+ // Get project context
+ const { data: project } = await supabaseClient
+ .from('projects')
+ .select('file_tree, design_system')
+ .eq('id', projectId)
+ .single();
+
+ // Initialize Anthropic (better for code generation)
+ const anthropic = new Anthropic({
+ apiKey: Deno.env.get('ANTHROPIC_API_KEY')
+ });
+
+ const message = await anthropic.messages.create({
+ model: 'claude-3-5-sonnet-20241022',
+ max_tokens: 4096,
+ messages: [
+ {
+ role: 'user',
+ content: `${systemPrompt}
+
+## Project Context
+File Tree:
+\`\`\`json
+${JSON.stringify(project?.file_tree, null, 2)}
+\`\`\`
+
+Design System:
+\`\`\`json
+${JSON.stringify(project?.design_system, null, 2)}
+\`\`\`
+
+## Task
+Generate a ${componentType} component:
+${prompt}
+
+Return the complete code with proper imports and exports.
+`
+ }
+ ]
+ });
+
+ const generatedCode = message.content[0].type === 'text'
+ ? message.content[0].text
+ : '';
+
+ // Track usage
+ await supabaseClient.from('usage').insert({
+ user_id: user.id,
+ tokens: message.usage.input_tokens + message.usage.output_tokens,
+ type: 'generation'
+ });
+
+ return new Response(
+ JSON.stringify({
+ code: generatedCode,
+ tokensUsed: message.usage.input_tokens + message.usage.output_tokens
+ }),
+ {
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
+ }
+ );
+ } catch (error) {
+ return new Response(
+ JSON.stringify({ error: error.message }),
+ {
+ status: 500,
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
+ }
+ );
+ }
+});
+```
+
+## 3. Deploy Edge Functions
+
+**File: `supabase/functions/deploy.sh`**
+
+```bash
+#!/bin/bash
+
+# Deploy all edge functions to Supabase
+
+echo "π Deploying Edge Functions to Supabase..."
+
+# Deploy chat completion
+echo "π¦ Deploying chat-completion..."
+supabase functions deploy chat-completion \
+ --no-verify-jwt \
+ --project-ref $SUPABASE_PROJECT_REF
+
+# Deploy code generation
+echo "π¦ Deploying generate-code..."
+supabase functions deploy generate-code \
+ --no-verify-jwt \
+ --project-ref $SUPABASE_PROJECT_REF
+
+# Set secrets
+echo "π Setting secrets..."
+supabase secrets set \
+ OPENAI_API_KEY=$OPENAI_API_KEY \
+ ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
+ --project-ref $SUPABASE_PROJECT_REF
+
+echo "β
Deployment complete!"
+```
+
+---
+
+# π II. WEBHOOK HANDLERS
+
+## 1. Stripe Webhooks
+
+**File: `src/app/api/webhooks/stripe/route.ts`**
+
+```typescript
+import { headers } from 'next/headers';
+import { NextResponse } from 'next/server';
+import { createAdminClient } from '@/lib/supabase/server';
+import Stripe from 'stripe';
+
+const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
+ apiVersion: '2023-10-16'
+});
+
+const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;
+
+export async function POST(req: Request) {
+ const body = await req.text();
+ const signature = (await headers()).get('stripe-signature')!;
+
+ let event: Stripe.Event;
+
+ try {
+ event = stripe.webhooks.constructEvent(body, signature, webhookSecret);
+ } catch (err) {
+ console.error('Webhook signature verification failed:', err);
+ return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });
+ }
+
+ const supabase = createAdminClient();
+
+ try {
+ switch (event.type) {
+ case 'checkout.session.completed': {
+ const session = event.data.object as Stripe.Checkout.Session;
+ const userId = session.metadata?.userId;
+
+ if (!userId) break;
+
+ // Update user subscription
+ await supabase
+ .from('profiles')
+ .update({
+ subscription_plan: session.metadata?.plan || 'pro',
+ subscription_status: 'active',
+ stripe_customer_id: session.customer as string,
+ stripe_subscription_id: session.subscription as string,
+ monthly_tokens: session.metadata?.plan === 'pro' ? 200000 : 50000,
+ monthly_projects: session.metadata?.plan === 'pro' ? 10 : 3
+ })
+ .eq('id', userId);
+
+ break;
+ }
+
+ case 'customer.subscription.updated': {
+ const subscription = event.data.object as Stripe.Subscription;
+
+ await supabase
+ .from('profiles')
+ .update({
+ subscription_status: subscription.status,
+ subscription_plan:
+ subscription.items.data[0].price.metadata.plan || 'pro'
+ })
+ .eq('stripe_subscription_id', subscription.id);
+
+ break;
+ }
+
+ case 'customer.subscription.deleted': {
+ const subscription = event.data.object as Stripe.Subscription;
+
+ await supabase
+ .from('profiles')
+ .update({
+ subscription_status: 'canceled',
+ subscription_plan: 'free',
+ monthly_tokens: 50000,
+ monthly_projects: 3
+ })
+ .eq('stripe_subscription_id', subscription.id);
+
+ break;
+ }
+
+ case 'invoice.payment_failed': {
+ const invoice = event.data.object as Stripe.Invoice;
+
+ await supabase
+ .from('profiles')
+ .update({
+ subscription_status: 'past_due'
+ })
+ .eq('stripe_customer_id', invoice.customer as string);
+
+ break;
+ }
+ }
+
+ return NextResponse.json({ received: true });
+ } catch (error) {
+ console.error('Webhook handler error:', error);
+ return NextResponse.json(
+ { error: 'Webhook handler failed' },
+ { status: 500 }
+ );
+ }
+}
+```
+
+## 2. GitHub Webhooks
+
+**File: `src/app/api/webhooks/github/route.ts`**
+
+```typescript
+import { NextRequest, NextResponse } from 'next/server';
+import { createAdminClient } from '@/lib/supabase/server';
+import crypto from 'crypto';
+
+export async function POST(req: NextRequest) {
+ const supabase = createAdminClient();
+
+ // Verify signature
+ const signature = req.headers.get('x-hub-signature-256');
+ const body = await req.text();
+
+ const hmac = crypto.createHmac('sha256', process.env.GITHUB_WEBHOOK_SECRET!);
+ const digest = 'sha256=' + hmac.update(body).digest('hex');
+
+ if (signature !== digest) {
+ return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
+ }
+
+ const payload = JSON.parse(body);
+ const event = req.headers.get('x-github-event');
+
+ try {
+ switch (event) {
+ case 'push': {
+ // Handle push events (auto-deploy)
+ const { repository, ref, commits } = payload;
+
+ // Find project linked to this repo
+ const { data: project } = await supabase
+ .from('projects')
+ .select('*')
+ .eq('github_repo', repository.full_name)
+ .single();
+
+ if (project) {
+ // Trigger deployment
+ await supabase.from('deployments').insert({
+ project_id: project.id,
+ provider: 'vercel',
+ status: 'pending',
+ url: ''
+ });
+
+ // You can trigger Vercel deployment here
+ // await triggerVercelDeployment(project);
+ }
+
+ break;
+ }
+
+ case 'pull_request': {
+ const { action, pull_request } = payload;
+
+ if (action === 'opened' || action === 'synchronize') {
+ // Create preview deployment for PR
+ // await createPreviewDeployment(pull_request);
+ }
+
+ break;
+ }
+ }
+
+ return NextResponse.json({ received: true });
+ } catch (error) {
+ console.error('GitHub webhook error:', error);
+ return NextResponse.json(
+ { error: 'Webhook handler failed' },
+ { status: 500 }
+ );
+ }
+}
+```
+
+## 3. Vercel Deploy Webhook
+
+**File: `src/app/api/webhooks/vercel/route.ts`**
+
+```typescript
+import { NextRequest, NextResponse } from 'next/server';
+import { createAdminClient } from '@/lib/supabase/server';
+
+export async function POST(req: NextRequest) {
+ const supabase = createAdminClient();
+ const payload = await req.json();
+
+ try {
+ const { deployment, type } = payload;
+
+ // Find deployment in database
+ const { data: existingDeployment } = await supabase
+ .from('deployments')
+ .select('*')
+ .eq('url', deployment.url)
+ .single();
+
+ if (!existingDeployment) {
+ return NextResponse.json({ received: true });
+ }
+
+ let status = 'pending';
+ let buildLogs = '';
+
+ switch (type) {
+ case 'deployment.created':
+ status = 'building';
+ break;
+ case 'deployment.ready':
+ status = 'ready';
+ break;
+ case 'deployment.error':
+ status = 'error';
+ buildLogs = deployment.errorMessage || 'Deployment failed';
+ break;
+ }
+
+ // Update deployment status
+ await supabase
+ .from('deployments')
+ .update({
+ status,
+ build_logs: buildLogs,
+ updated_at: new Date().toISOString()
+ })
+ .eq('id', existingDeployment.id);
+
+ // Notify user via realtime
+ await supabase
+ .from('deployments')
+ .update({ updated_at: new Date().toISOString() })
+ .eq('id', existingDeployment.id);
+
+ return NextResponse.json({ received: true });
+ } catch (error) {
+ console.error('Vercel webhook error:', error);
+ return NextResponse.json(
+ { error: 'Webhook handler failed' },
+ { status: 500 }
+ );
+ }
+}
+```
+
+---
+
+# π§ͺ III. TESTING SETUP
+
+## 1. Vitest Configuration
+
+**File: `vitest.config.ts`**
+
+```typescript
+import { defineConfig } from 'vitest/config';
+import react from '@vitejs/plugin-react';
+import path from 'path';
+
+export default defineConfig({
+ plugins: [react()],
+ test: {
+ environment: 'jsdom',
+ setupFiles: ['./src/test/setup.ts'],
+ globals: true,
+ coverage: {
+ provider: 'v8',
+ reporter: ['text', 'json', 'html'],
+ exclude: [
+ 'node_modules/',
+ 'src/test/',
+ '**/*.d.ts',
+ '**/*.config.*',
+ '**/mockData'
+ ]
+ }
+ },
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src')
+ }
+ }
+});
+```
+
+**File: `src/test/setup.ts`**
+
+```typescript
+import { expect, afterEach, vi } from 'vitest';
+import { cleanup } from '@testing-library/react';
+import * as matchers from '@testing-library/jest-dom/matchers';
+
+expect.extend(matchers);
+
+// Cleanup after each test
+afterEach(() => {
+ cleanup();
+});
+
+// Mock Supabase client
+vi.mock('@/lib/supabase/client', () => ({
+ createClient: () => ({
+ auth: {
+ getUser: vi.fn(),
+ signIn: vi.fn(),
+ signOut: vi.fn()
+ },
+ from: vi.fn(() => ({
+ select: vi.fn().mockReturnThis(),
+ insert: vi.fn().mockReturnThis(),
+ update: vi.fn().mockReturnThis(),
+ delete: vi.fn().mockReturnThis(),
+ eq: vi.fn().mockReturnThis(),
+ single: vi.fn()
+ }))
+ })
+}));
+
+// Mock Next.js router
+vi.mock('next/navigation', () => ({
+ useRouter: () => ({
+ push: vi.fn(),
+ replace: vi.fn(),
+ prefetch: vi.fn()
+ }),
+ usePathname: () => '/',
+ useSearchParams: () => new URLSearchParams()
+}));
+```
+
+## 2. Component Tests
+
+**File: `src/components/chat/__tests__/chat-panel.test.tsx`**
+
+```typescript
+import { describe, it, expect, vi } from 'vitest';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import { ChatPanel } from '../chat-panel';
+
+describe('ChatPanel', () => {
+ it('renders chat input', () => {
+ render();
+
+ expect(
+ screen.getByPlaceholderText(/describe what you want to build/i)
+ ).toBeInTheDocument();
+ });
+
+ it('sends message on button click', async () => {
+ const { getByRole, getByPlaceholderText } = render(
+
+ );
+
+ const input = getByPlaceholderText(/describe what you want to build/i);
+ const button = getByRole('button', { name: /send/i });
+
+ fireEvent.change(input, { target: { value: 'Create a button' } });
+ fireEvent.click(button);
+
+ await waitFor(() => {
+ expect(screen.getByText('Create a button')).toBeInTheDocument();
+ });
+ });
+
+ it('disables input while loading', async () => {
+ const { getByPlaceholderText, getByRole } = render(
+
+ );
+
+ const input = getByPlaceholderText(/describe what you want to build/i);
+ const button = getByRole('button');
+
+ fireEvent.change(input, { target: { value: 'Test' } });
+ fireEvent.click(button);
+
+ expect(input).toBeDisabled();
+ });
+});
+```
+
+## 3. E2E Tests with Playwright
+
+**File: `playwright.config.ts`**
+
+```typescript
+import { defineConfig, devices } from '@playwright/test';
+
+export default defineConfig({
+ testDir: './e2e',
+ fullyParallel: true,
+ forbidOnly: !!process.env.CI,
+ retries: process.env.CI ? 2 : 0,
+ workers: process.env.CI ? 1 : undefined,
+ reporter: 'html',
+ use: {
+ baseURL: 'http://localhost:3000',
+ trace: 'on-first-retry'
+ },
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] }
+ },
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] }
+ },
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] }
+ }
+ ],
+ webServer: {
+ command: 'npm run dev',
+ url: 'http://localhost:3000',
+ reuseExistingServer: !process.env.CI
+ }
+});
+```
+
+**File: `e2e/auth.spec.ts`**
+
+```typescript
+import { test, expect } from '@playwright/test';
+
+test.describe('Authentication', () => {
+ test('user can sign up', async ({ page }) => {
+ await page.goto('/signup');
+
+ await page.fill('input[type="email"]', 'test@example.com');
+ await page.fill('input[type="password"]', 'password123');
+ await page.fill('input[name="fullName"]', 'Test User');
+
+ await page.click('button[type="submit"]');
+
+ await expect(page).toHaveURL('/');
+ });
+
+ test('user can sign in', async ({ page }) => {
+ await page.goto('/login');
+
+ await page.fill('input[type="email"]', 'test@example.com');
+ await page.fill('input[type="password"]', 'password123');
+
+ await page.click('button[type="submit"]');
+
+ await expect(page).toHaveURL('/');
+ });
+});
+
+test.describe('Project Management', () => {
+ test.beforeEach(async ({ page }) => {
+ // Login first
+ await page.goto('/login');
+ await page.fill('input[type="email"]', 'test@example.com');
+ await page.fill('input[type="password"]', 'password123');
+ await page.click('button[type="submit"]');
+ await page.waitForURL('/');
+ });
+
+ test('user can create a project', async ({ page }) => {
+ await page.click('text=New Project');
+
+ await expect(page).toHaveURL(/\/project\/.+/);
+ await expect(page.locator('text=Chat')).toBeVisible();
+ });
+
+ test('user can send chat message', async ({ page }) => {
+ await page.click('text=New Project');
+
+ const textarea = page.locator('textarea');
+ await textarea.fill('Create a button component');
+ await page.click('button:has-text("Send")');
+
+ await expect(
+ page.locator('text=Create a button component')
+ ).toBeVisible();
+ });
+});
+```
+
+---
+
+_TiαΊΏp tα»₯c vα»i CI/CD, Monitoring, vΓ Advanced Features..._
diff --git a/LOVABLE_CLONE_DEPLOYMENT_GUIDE.md b/LOVABLE_CLONE_DEPLOYMENT_GUIDE.md
new file mode 100644
index 00000000..cbd20dfa
--- /dev/null
+++ b/LOVABLE_CLONE_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,801 @@
+# π’ Lovable Clone - Complete Deployment Guide
+
+> Step-by-step production deployment vα»i Vercel + Supabase
+
+---
+
+# π Table of Contents
+
+1. [Pre-Deployment Checklist](#pre-deployment-checklist)
+2. [Supabase Production Setup](#supabase-production-setup)
+3. [Vercel Deployment](#vercel-deployment)
+4. [Domain & SSL](#domain--ssl)
+5. [Environment Variables](#environment-variables)
+6. [Database Backups](#database-backups)
+7. [Monitoring Setup](#monitoring-setup)
+8. [Post-Deployment](#post-deployment)
+
+---
+
+# β
I. PRE-DEPLOYMENT CHECKLIST
+
+## 1. Code Quality
+
+```bash
+# Run all checks
+npm run lint
+npm run type-check
+npm run test:unit
+npm run test:e2e
+npm run build
+
+# Check bundle size
+npx @next/bundle-analyzer
+```
+
+## 2. Security Audit
+
+```bash
+# Check for vulnerabilities
+npm audit
+
+# Fix if possible
+npm audit fix
+
+# Check for outdated packages
+npm outdated
+
+# Update safely
+npm update
+```
+
+## 3. Performance Audit
+
+```bash
+# Run Lighthouse
+npx lighthouse https://your-staging-url.vercel.app \
+ --output=html \
+ --output-path=./lighthouse-report.html
+
+# Aim for:
+# - Performance: > 90
+# - Accessibility: > 95
+# - Best Practices: > 95
+# - SEO: > 95
+```
+
+## 4. Configuration Checklist
+
+- [ ] All environment variables configured
+- [ ] Database migrations applied
+- [ ] RLS policies enabled
+- [ ] Storage buckets created
+- [ ] Realtime enabled
+- [ ] Email templates configured
+- [ ] Webhook endpoints ready
+- [ ] Rate limiting configured
+- [ ] Analytics integrated
+- [ ] Error tracking setup
+- [ ] Backup strategy in place
+
+---
+
+# ποΈ II. SUPABASE PRODUCTION SETUP
+
+## 1. Create Production Project
+
+```bash
+# Go to https://supabase.com
+# Click "New Project"
+# Choose:
+# - Organization
+# - Project name: lovable-production
+# - Database password: Use strong password (save it!)
+# - Region: Choose closest to users
+# - Pricing plan: Pro (recommended)
+```
+
+## 2. Run Database Migrations
+
+```sql
+-- Copy from supabase/migrations/00000000000000_initial_schema.sql
+-- Paste into SQL Editor
+-- Click "Run"
+
+-- Verify tables created
+SELECT table_name
+FROM information_schema.tables
+WHERE table_schema = 'public';
+
+-- Check RLS enabled
+SELECT tablename, rowsecurity
+FROM pg_tables
+WHERE schemaname = 'public';
+```
+
+## 3. Configure Authentication
+
+```bash
+# In Supabase Dashboard:
+# Authentication > Providers
+
+# Enable Email
+- Confirm Email: ON
+- Double Confirm: OFF
+- Secure Email Change: ON
+
+# Enable Google OAuth
+- Client ID: [Google Cloud Console]
+- Client Secret: [Google Cloud Console]
+- Redirect URL: https://[project-ref].supabase.co/auth/v1/callback
+
+# Enable GitHub OAuth
+- Client ID: [GitHub OAuth Apps]
+- Client Secret: [GitHub OAuth Apps]
+- Redirect URL: https://[project-ref].supabase.co/auth/v1/callback
+```
+
+## 4. Setup Storage
+
+```bash
+# Storage > Create Bucket
+
+Bucket name: project-assets
+Public: Yes
+File size limit: 10 MB
+Allowed MIME types: image/*, application/zip
+
+# Set RLS policies for bucket
+CREATE POLICY "Users can upload own files"
+ON storage.objects FOR INSERT
+WITH CHECK (
+ bucket_id = 'project-assets' AND
+ auth.uid()::text = (storage.foldername(name))[1]
+);
+
+CREATE POLICY "Anyone can view files"
+ON storage.objects FOR SELECT
+USING (bucket_id = 'project-assets');
+
+CREATE POLICY "Users can delete own files"
+ON storage.objects FOR DELETE
+USING (
+ bucket_id = 'project-assets' AND
+ auth.uid()::text = (storage.foldername(name))[1]
+);
+```
+
+## 5. Enable Realtime
+
+```sql
+-- Enable realtime for tables
+ALTER PUBLICATION supabase_realtime ADD TABLE messages;
+ALTER PUBLICATION supabase_realtime ADD TABLE project_files;
+ALTER PUBLICATION supabase_realtime ADD TABLE deployments;
+
+-- Verify
+SELECT schemaname, tablename
+FROM pg_publication_tables
+WHERE pubname = 'supabase_realtime';
+```
+
+## 6. Deploy Edge Functions
+
+```bash
+# Install Supabase CLI
+npm install -g supabase
+
+# Login
+supabase login
+
+# Link production project
+supabase link --project-ref your-production-ref
+
+# Deploy functions
+supabase functions deploy chat-completion
+supabase functions deploy generate-code
+
+# Set secrets
+supabase secrets set \
+ OPENAI_API_KEY=sk-... \
+ ANTHROPIC_API_KEY=sk-ant-... \
+ --project-ref your-production-ref
+```
+
+---
+
+# π III. VERCEL DEPLOYMENT
+
+## 1. Connect Repository
+
+```bash
+# Go to https://vercel.com
+# Click "Add New Project"
+# Import Git Repository
+# Select your GitHub repo
+```
+
+## 2. Configure Build Settings
+
+```
+Framework Preset: Next.js
+Root Directory: ./
+Build Command: npm run build
+Output Directory: .next
+Install Command: npm ci
+
+Node.js Version: 18.x
+```
+
+## 3. Environment Variables
+
+```env
+# Production environment variables
+NEXT_PUBLIC_SUPABASE_URL=https://[your-ref].supabase.co
+NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
+
+# Service role (for admin operations)
+SUPABASE_SERVICE_ROLE_KEY=eyJ...
+
+# AI Keys
+AI_PROVIDER=openai
+OPENAI_API_KEY=sk-...
+# OR
+ANTHROPIC_API_KEY=sk-ant-...
+
+# Stripe
+STRIPE_SECRET_KEY=sk_live_...
+STRIPE_WEBHOOK_SECRET=whsec_...
+NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
+
+# Email
+RESEND_API_KEY=re_...
+FROM_EMAIL=noreply@yourdomain.com
+
+# Monitoring
+NEXT_PUBLIC_SENTRY_DSN=https://...@sentry.io/...
+SENTRY_AUTH_TOKEN=sntrys_...
+SENTRY_ORG=your-org
+SENTRY_PROJECT=lovable-clone
+
+# Analytics
+NEXT_PUBLIC_POSTHOG_KEY=phc_...
+NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
+
+# Rate Limiting
+UPSTASH_REDIS_REST_URL=https://...upstash.io
+UPSTASH_REDIS_REST_TOKEN=...
+
+# GitHub Integration (optional)
+GITHUB_TOKEN=ghp_...
+GITHUB_WEBHOOK_SECRET=...
+
+# Deployment
+VERCEL_TOKEN=...
+NETLIFY_TOKEN=...
+```
+
+## 4. Deploy
+
+```bash
+# First deployment
+git push origin main
+
+# Or manual deploy
+vercel --prod
+
+# Check deployment
+vercel ls
+```
+
+## 5. Post-Deploy Verification
+
+```bash
+# Test endpoints
+curl https://your-domain.com/api/health
+
+# Check SSR
+curl https://your-domain.com
+
+# Test authentication
+# Visit https://your-domain.com/login
+
+# Test Supabase connection
+# Try signing up a user
+
+# Check Realtime
+# Open browser console, should see WebSocket connection
+```
+
+---
+
+# π IV. DOMAIN & SSL
+
+## 1. Add Custom Domain
+
+```bash
+# In Vercel Dashboard:
+# Settings > Domains > Add
+
+# Add your domain:
+yourdomain.com
+www.yourdomain.com
+
+# Vercel will provide DNS records
+```
+
+## 2. Configure DNS
+
+```
+# Add these records to your DNS provider:
+
+Type: A
+Name: @
+Value: 76.76.21.21
+
+Type: CNAME
+Name: www
+Value: cname.vercel-dns.com
+
+# For Supabase custom domain (optional):
+Type: CNAME
+Name: api
+Value: [your-ref].supabase.co
+```
+
+## 3. SSL Certificate
+
+```
+# Vercel automatically provisions SSL
+# Check in Vercel Dashboard > Domains
+# Should show: "SSL Certificate Valid"
+
+# Force HTTPS redirect
+# Already handled by next.config.js headers
+```
+
+---
+
+# π V. ENVIRONMENT MANAGEMENT
+
+## 1. Vercel Environment Setup
+
+```bash
+# Production
+NEXT_PUBLIC_SUPABASE_URL=production-url
+SUPABASE_SERVICE_ROLE_KEY=production-key
+
+# Preview (for PRs)
+NEXT_PUBLIC_SUPABASE_URL=staging-url
+SUPABASE_SERVICE_ROLE_KEY=staging-key
+
+# Development (local)
+NEXT_PUBLIC_SUPABASE_URL=local-url
+SUPABASE_SERVICE_ROLE_KEY=local-key
+```
+
+## 2. Secrets Management
+
+```bash
+# Use Vercel CLI to set secrets
+vercel env add STRIPE_SECRET_KEY production
+
+# Or use Vercel Dashboard
+# Settings > Environment Variables
+
+# Never commit secrets to git!
+# Add to .gitignore:
+.env*.local
+.env.production
+```
+
+---
+
+# πΎ VI. DATABASE BACKUPS
+
+## 1. Automated Backups (Supabase Pro)
+
+```bash
+# Supabase automatically backs up:
+# - Daily backups: 7 days retention
+# - Weekly backups: 4 weeks retention
+# - Monthly backups: 3 months retention
+
+# Enable in Supabase Dashboard:
+# Database > Backups > Enable
+```
+
+## 2. Manual Backup Script
+
+```bash
+#!/bin/bash
+# backup.sh
+
+DATE=$(date +%Y%m%d_%H%M%S)
+BACKUP_DIR="./backups"
+PROJECT_REF="your-project-ref"
+
+mkdir -p $BACKUP_DIR
+
+# Backup database
+supabase db dump \
+ --project-ref $PROJECT_REF \
+ --password $DB_PASSWORD \
+ > $BACKUP_DIR/db_$DATE.sql
+
+# Backup storage
+supabase storage download \
+ --project-ref $PROJECT_REF \
+ --bucket project-assets \
+ --output $BACKUP_DIR/storage_$DATE.tar.gz
+
+# Upload to S3 (optional)
+aws s3 cp $BACKUP_DIR/ s3://your-backup-bucket/ --recursive
+
+echo "Backup completed: $DATE"
+```
+
+## 3. Point-in-Time Recovery
+
+```sql
+-- Supabase Pro includes PITR
+-- Can restore to any point in last 7 days
+
+-- To restore:
+-- 1. Go to Supabase Dashboard
+-- 2. Database > Backups
+-- 3. Click "Restore"
+-- 4. Select timestamp
+-- 5. Confirm
+```
+
+---
+
+# π VII. MONITORING SETUP
+
+## 1. Vercel Analytics
+
+```typescript
+// Already enabled in layout.tsx
+import { Analytics } from '@vercel/analytics/react';
+
+export default function RootLayout({ children }) {
+ return (
+
+
+ {children}
+
+
+
+ );
+}
+```
+
+## 2. Sentry Setup
+
+```bash
+# Install Sentry
+npm install @sentry/nextjs
+
+# Run Sentry wizard
+npx @sentry/wizard@latest -i nextjs
+
+# Configure in sentry.client.config.ts
+Sentry.init({
+ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
+ tracesSampleRate: 1.0,
+ replaysSessionSampleRate: 0.1,
+ replaysOnErrorSampleRate: 1.0
+});
+```
+
+## 3. Uptime Monitoring
+
+```bash
+# Use services like:
+# - UptimeRobot (https://uptimerobot.com)
+# - Pingdom
+# - Better Uptime
+
+# Monitor endpoints:
+- https://yourdomain.com (main site)
+- https://yourdomain.com/api/health (API health)
+- https://[ref].supabase.co (database)
+```
+
+## 4. Performance Monitoring
+
+```bash
+# Lighthouse CI
+npm install -g @lhci/cli
+
+# Create lighthouserc.js
+module.exports = {
+ ci: {
+ collect: {
+ url: ['https://yourdomain.com'],
+ numberOfRuns: 3
+ },
+ assert: {
+ assertions: {
+ 'categories:performance': ['error', { minScore: 0.9 }],
+ 'categories:accessibility': ['error', { minScore: 0.95 }]
+ }
+ },
+ upload: {
+ target: 'temporary-public-storage'
+ }
+ }
+};
+
+# Run in CI
+lhci autorun
+```
+
+---
+
+# π― VIII. POST-DEPLOYMENT
+
+## 1. Smoke Tests
+
+```bash
+# Test critical paths
+curl -f https://yourdomain.com || exit 1
+curl -f https://yourdomain.com/api/health || exit 1
+
+# Test authentication
+# - Sign up new user
+# - Sign in
+# - Create project
+# - Send chat message
+# - Generate code
+```
+
+## 2. Performance Baseline
+
+```bash
+# Run Lighthouse
+# Save scores for comparison
+
+Performance: ___
+Accessibility: ___
+Best Practices: ___
+SEO: ___
+```
+
+## 3. Set Up Alerts
+
+```yaml
+# alerts.yml
+alerts:
+ - name: Error Rate High
+ condition: error_rate > 5%
+ notify: email, slack
+
+ - name: Response Time Slow
+ condition: p95_response_time > 2s
+ notify: email
+
+ - name: Database Connection Issues
+ condition: db_connection_failures > 0
+ notify: pagerduty
+
+ - name: High Traffic
+ condition: requests_per_minute > 10000
+ notify: slack
+```
+
+## 4. Documentation
+
+```markdown
+# Create DEPLOYMENT.md
+
+## Production URLs
+
+- Main Site: https://yourdomain.com
+- API: https://yourdomain.com/api
+- Dashboard: https://yourdomain.com/dashboard
+
+## Deployment Process
+
+1. Create PR
+2. Wait for CI checks
+3. Merge to main
+4. Automatic deploy to production
+5. Run smoke tests
+6. Monitor for errors
+
+## Rollback Procedure
+
+1. Go to Vercel dashboard
+2. Find previous deployment
+3. Click "Promote to Production"
+4. Verify deployment
+
+## Emergency Contacts
+
+- On-call: +1-xxx-xxx-xxxx
+- Slack: #alerts
+- Email: oncall@company.com
+```
+
+---
+
+# π₯ IX. DISASTER RECOVERY
+
+## 1. Incident Response Plan
+
+```markdown
+## Severity Levels
+
+**P0 - Critical**
+
+- Site completely down
+- Data loss occurring
+- Security breach
+- Response time: Immediate
+
+**P1 - High**
+
+- Major features broken
+- Performance degraded >50%
+- Response time: 15 minutes
+
+**P2 - Medium**
+
+- Minor features broken
+- Performance degraded <50%
+- Response time: 2 hours
+
+**P3 - Low**
+
+- Cosmetic issues
+- Response time: 24 hours
+```
+
+## 2. Recovery Procedures
+
+```bash
+# Database Recovery
+1. Identify issue
+2. Stop writes if needed
+3. Restore from backup
+4. Verify data integrity
+5. Resume normal operations
+
+# Application Recovery
+1. Roll back deployment
+2. Check logs
+3. Fix issue
+4. Deploy fix
+5. Verify
+
+# Data Center Failover
+1. Switch DNS to backup region
+2. Activate read replicas
+3. Restore write capability
+4. Monitor performance
+```
+
+## 3. Communication Plan
+
+```
+Internal:
+- Post in #incidents Slack channel
+- Email stakeholders
+- Update status page
+
+External:
+- Update status.yourdomain.com
+- Tweet from @yourcompany
+- Email affected users
+```
+
+---
+
+# π X. PRODUCTION CHECKLIST
+
+## Launch Day
+
+- [ ] All tests passing
+- [ ] Database backups verified
+- [ ] Monitoring alerts configured
+- [ ] Error tracking working
+- [ ] Analytics tracking
+- [ ] SSL certificate valid
+- [ ] Custom domain configured
+- [ ] Email sending works
+- [ ] Webhooks configured
+- [ ] Rate limiting active
+- [ ] RLS policies enabled
+- [ ] API keys secured
+- [ ] Documentation updated
+- [ ] Team trained
+- [ ] Support ready
+
+## Week 1
+
+- [ ] Monitor error rates
+- [ ] Check performance metrics
+- [ ] Review user feedback
+- [ ] Optimize slow queries
+- [ ] Address quick wins
+- [ ] Update documentation
+
+## Month 1
+
+- [ ] Review analytics
+- [ ] Plan improvements
+- [ ] Security audit
+- [ ] Cost optimization
+- [ ] Scale planning
+
+---
+
+# π XI. MAINTENANCE
+
+## Daily
+
+```bash
+# Check dashboards
+- Vercel Analytics
+- Sentry errors
+- Supabase logs
+- PostHog events
+
+# Review metrics
+- Active users
+- Error rate
+- Response time
+- Database size
+```
+
+## Weekly
+
+```bash
+# Update dependencies
+npm update
+
+# Review performance
+- Lighthouse scores
+- Web Vitals
+- Bundle size
+
+# Check backups
+- Verify last backup
+- Test restore
+```
+
+## Monthly
+
+```bash
+# Security audit
+npm audit
+npm outdated
+
+# Cost review
+- Vercel usage
+- Supabase usage
+- Third-party services
+
+# Capacity planning
+- Database growth
+- Storage usage
+- API calls
+```
+
+---
+
+**π Congratulations! Your Lovable Clone is now production-ready and deployed!**
+
+## Support Resources
+
+- **Vercel Docs**: https://vercel.com/docs
+- **Supabase Docs**: https://supabase.com/docs
+- **Next.js Docs**: https://nextjs.org/docs
+
+## Need Help?
+
+- GitHub Issues: https://github.com/your-repo/issues
+- Discord: https://discord.gg/your-server
+- Email: support@yourdomain.com
diff --git a/LOVABLE_CLONE_PRODUCTION_READY.md b/LOVABLE_CLONE_PRODUCTION_READY.md
new file mode 100644
index 00000000..9a4f3699
--- /dev/null
+++ b/LOVABLE_CLONE_PRODUCTION_READY.md
@@ -0,0 +1,937 @@
+# π Lovable Clone - Production Ready Setup
+
+> CI/CD, Monitoring, Security, Performance, vΓ Deployment Guide
+
+---
+
+# π Table of Contents
+
+1. [CI/CD Pipeline](#cicd-pipeline)
+2. [Monitoring & Analytics](#monitoring--analytics)
+3. [Security Best Practices](#security-best-practices)
+4. [Performance Optimization](#performance-optimization)
+5. [Production Deployment](#production-deployment)
+6. [Disaster Recovery](#disaster-recovery)
+
+---
+
+# π I. CI/CD PIPELINE
+
+## 1. GitHub Actions Workflow
+
+**File: `.github/workflows/ci.yml`**
+
+```yaml
+name: CI/CD Pipeline
+
+on:
+ push:
+ branches: [main, develop]
+ pull_request:
+ branches: [main, develop]
+
+env:
+ NODE_VERSION: '18.x'
+
+jobs:
+ lint-and-type-check:
+ name: Lint & Type Check
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run ESLint
+ run: npm run lint
+
+ - name: Run TypeScript check
+ run: npx tsc --noEmit
+
+ test:
+ name: Test
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run unit tests
+ run: npm run test:unit
+
+ - name: Upload coverage
+ uses: codecov/codecov-action@v3
+ with:
+ files: ./coverage/coverage-final.json
+ flags: unittests
+
+ e2e-test:
+ name: E2E Tests
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Install Playwright
+ run: npx playwright install --with-deps
+
+ - name: Run E2E tests
+ run: npm run test:e2e
+ env:
+ NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
+ NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
+
+ - name: Upload test results
+ uses: actions/upload-artifact@v3
+ if: always()
+ with:
+ name: playwright-report
+ path: playwright-report/
+
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ needs: [lint-and-type-check, test]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build application
+ run: npm run build
+ env:
+ NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
+ NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: build
+ path: .next/
+
+ deploy-staging:
+ name: Deploy to Staging
+ runs-on: ubuntu-latest
+ needs: [build, e2e-test]
+ if: github.ref == 'refs/heads/develop'
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Deploy to Vercel Staging
+ uses: amondnet/vercel-action@v25
+ with:
+ vercel-token: ${{ secrets.VERCEL_TOKEN }}
+ vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
+ vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
+ scope: ${{ secrets.VERCEL_ORG_ID }}
+
+ deploy-production:
+ name: Deploy to Production
+ runs-on: ubuntu-latest
+ needs: [build, e2e-test]
+ if: github.ref == 'refs/heads/main'
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Deploy to Vercel Production
+ uses: amondnet/vercel-action@v25
+ with:
+ vercel-token: ${{ secrets.VERCEL_TOKEN }}
+ vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
+ vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
+ vercel-args: '--prod'
+ scope: ${{ secrets.VERCEL_ORG_ID }}
+
+ - name: Create Sentry release
+ uses: getsentry/action-release@v1
+ env:
+ SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
+ SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
+ with:
+ environment: production
+```
+
+## 2. Pre-commit Hooks
+
+**File: `.husky/pre-commit`**
+
+```bash
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+# Run lint-staged
+npx lint-staged
+
+# Run type check
+npm run type-check
+```
+
+**File: `.husky/commit-msg`**
+
+```bash
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+# Validate commit message
+npx --no -- commitlint --edit ${1}
+```
+
+**File: `package.json` (add scripts)**
+
+```json
+{
+ "scripts": {
+ "prepare": "husky install",
+ "test:unit": "vitest run",
+ "test:e2e": "playwright test",
+ "test:watch": "vitest",
+ "type-check": "tsc --noEmit",
+ "lint": "next lint",
+ "lint:fix": "next lint --fix",
+ "format": "prettier --write \"**/*.{ts,tsx,md}\""
+ },
+ "lint-staged": {
+ "*.{ts,tsx}": [
+ "eslint --fix",
+ "prettier --write"
+ ],
+ "*.{md,json}": [
+ "prettier --write"
+ ]
+ }
+}
+```
+
+## 3. Commitlint Configuration
+
+**File: `commitlint.config.js`**
+
+```javascript
+module.exports = {
+ extends: ['@commitlint/config-conventional'],
+ rules: {
+ 'type-enum': [
+ 2,
+ 'always',
+ [
+ 'feat', // New feature
+ 'fix', // Bug fix
+ 'docs', // Documentation
+ 'style', // Formatting
+ 'refactor', // Code restructuring
+ 'perf', // Performance
+ 'test', // Tests
+ 'chore', // Maintenance
+ 'ci', // CI/CD
+ 'build' // Build system
+ ]
+ ]
+ }
+};
+```
+
+---
+
+# π II. MONITORING & ANALYTICS
+
+## 1. Sentry Error Tracking
+
+**File: `src/lib/sentry.ts`**
+
+```typescript
+import * as Sentry from '@sentry/nextjs';
+
+export function initSentry() {
+ if (process.env.NEXT_PUBLIC_SENTRY_DSN) {
+ Sentry.init({
+ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
+ environment: process.env.NODE_ENV,
+ tracesSampleRate: 1.0,
+
+ // Performance Monitoring
+ integrations: [
+ new Sentry.BrowserTracing({
+ tracePropagationTargets: [
+ 'localhost',
+ /^https:\/\/.*\.vercel\.app/
+ ]
+ }),
+ new Sentry.Replay({
+ maskAllText: true,
+ blockAllMedia: true
+ })
+ ],
+
+ // Session Replay
+ replaysSessionSampleRate: 0.1,
+ replaysOnErrorSampleRate: 1.0,
+
+ beforeSend(event, hint) {
+ // Filter out sensitive data
+ if (event.request) {
+ delete event.request.cookies;
+ delete event.request.headers;
+ }
+ return event;
+ }
+ });
+ }
+}
+
+// Custom error logging
+export function logError(error: Error, context?: Record) {
+ console.error(error);
+
+ if (process.env.NEXT_PUBLIC_SENTRY_DSN) {
+ Sentry.captureException(error, {
+ extra: context
+ });
+ }
+}
+
+// Performance monitoring
+export function startTransaction(name: string, op: string) {
+ return Sentry.startTransaction({ name, op });
+}
+```
+
+**File: `src/app/layout.tsx` (add Sentry)**
+
+```typescript
+import { initSentry } from '@/lib/sentry';
+
+// Initialize Sentry
+if (typeof window !== 'undefined') {
+ initSentry();
+}
+
+export default function RootLayout({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+```
+
+## 2. PostHog Analytics
+
+**File: `src/lib/posthog.ts`**
+
+```typescript
+import posthog from 'posthog-js';
+
+export function initPostHog() {
+ if (
+ typeof window !== 'undefined' &&
+ process.env.NEXT_PUBLIC_POSTHOG_KEY
+ ) {
+ posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
+ api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://app.posthog.com',
+ loaded: (posthog) => {
+ if (process.env.NODE_ENV === 'development') {
+ posthog.debug();
+ }
+ },
+ capture_pageview: false, // We'll manually track
+ capture_pageleave: true,
+ autocapture: {
+ dom_event_allowlist: ['click', 'submit'],
+ element_allowlist: ['button', 'a']
+ }
+ });
+ }
+}
+
+export function trackEvent(
+ eventName: string,
+ properties?: Record
+) {
+ if (typeof window !== 'undefined') {
+ posthog.capture(eventName, properties);
+ }
+}
+
+export function identifyUser(userId: string, traits?: Record) {
+ if (typeof window !== 'undefined') {
+ posthog.identify(userId, traits);
+ }
+}
+
+export function trackPageView() {
+ if (typeof window !== 'undefined') {
+ posthog.capture('$pageview');
+ }
+}
+```
+
+**File: `src/components/analytics/posthog-provider.tsx`**
+
+```typescript
+'use client';
+
+import { useEffect } from 'react';
+import { usePathname, useSearchParams } from 'next/navigation';
+import { initPostHog, trackPageView } from '@/lib/posthog';
+
+export function PostHogProvider({ children }: { children: React.ReactNode }) {
+ const pathname = usePathname();
+ const searchParams = useSearchParams();
+
+ useEffect(() => {
+ initPostHog();
+ }, []);
+
+ useEffect(() => {
+ trackPageView();
+ }, [pathname, searchParams]);
+
+ return <>{children}>;
+}
+```
+
+## 3. Performance Monitoring
+
+**File: `src/lib/performance.ts`**
+
+```typescript
+import { Metric } from 'web-vitals';
+
+export function sendToAnalytics(metric: Metric) {
+ // Send to PostHog
+ if (typeof window !== 'undefined' && window.posthog) {
+ window.posthog.capture('web_vitals', {
+ metric_name: metric.name,
+ metric_value: metric.value,
+ metric_id: metric.id,
+ metric_rating: metric.rating
+ });
+ }
+
+ // Send to Vercel Analytics
+ if (process.env.NEXT_PUBLIC_VERCEL_ENV) {
+ const body = JSON.stringify({
+ dsn: process.env.NEXT_PUBLIC_VERCEL_ANALYTICS_ID,
+ id: metric.id,
+ page: window.location.pathname,
+ href: window.location.href,
+ event_name: metric.name,
+ value: metric.value.toString(),
+ speed: navigator?.connection?.effectiveType || ''
+ });
+
+ const url = 'https://vitals.vercel-insights.com/v1/vitals';
+
+ if (navigator.sendBeacon) {
+ navigator.sendBeacon(url, body);
+ } else {
+ fetch(url, { body, method: 'POST', keepalive: true });
+ }
+ }
+}
+
+// Log slow renders
+export function logSlowRender(componentName: string, renderTime: number) {
+ if (renderTime > 16) {
+ // More than 1 frame (60fps)
+ console.warn(`Slow render: ${componentName} took ${renderTime}ms`);
+
+ if (typeof window !== 'undefined' && window.posthog) {
+ window.posthog.capture('slow_render', {
+ component: componentName,
+ render_time: renderTime
+ });
+ }
+ }
+}
+```
+
+**File: `src/app/layout.tsx` (add Web Vitals)**
+
+```typescript
+'use client';
+
+import { useReportWebVitals } from 'next/web-vitals';
+import { sendToAnalytics } from '@/lib/performance';
+
+export function WebVitals() {
+ useReportWebVitals((metric) => {
+ sendToAnalytics(metric);
+ });
+
+ return null;
+}
+```
+
+## 4. Logging System
+
+**File: `src/lib/logger.ts`**
+
+```typescript
+import pino from 'pino';
+
+const logger = pino({
+ level: process.env.LOG_LEVEL || 'info',
+ formatters: {
+ level: (label) => {
+ return { level: label };
+ }
+ },
+ redact: {
+ paths: ['password', 'apiKey', 'token'],
+ remove: true
+ },
+ ...(process.env.NODE_ENV === 'production'
+ ? {
+ // Structured logging for production
+ transport: {
+ target: 'pino/file',
+ options: { destination: 1 } // stdout
+ }
+ }
+ : {
+ // Pretty printing for development
+ transport: {
+ target: 'pino-pretty',
+ options: {
+ colorize: true
+ }
+ }
+ })
+});
+
+export { logger };
+
+// Usage:
+// logger.info({ userId: '123', action: 'login' }, 'User logged in');
+// logger.error({ err, context }, 'Error occurred');
+```
+
+---
+
+# π III. SECURITY BEST PRACTICES
+
+## 1. Security Headers
+
+**File: `next.config.js`**
+
+```javascript
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ async headers() {
+ return [
+ {
+ source: '/:path*',
+ headers: [
+ {
+ key: 'X-DNS-Prefetch-Control',
+ value: 'on'
+ },
+ {
+ key: 'Strict-Transport-Security',
+ value: 'max-age=63072000; includeSubDomains; preload'
+ },
+ {
+ key: 'X-Frame-Options',
+ value: 'SAMEORIGIN'
+ },
+ {
+ key: 'X-Content-Type-Options',
+ value: 'nosniff'
+ },
+ {
+ key: 'X-XSS-Protection',
+ value: '1; mode=block'
+ },
+ {
+ key: 'Referrer-Policy',
+ value: 'strict-origin-when-cross-origin'
+ },
+ {
+ key: 'Permissions-Policy',
+ value: 'camera=(), microphone=(), geolocation=()'
+ },
+ {
+ key: 'Content-Security-Policy',
+ value: [
+ "default-src 'self'",
+ "script-src 'self' 'unsafe-eval' 'unsafe-inline' https://cdn.jsdelivr.net",
+ "style-src 'self' 'unsafe-inline'",
+ "img-src 'self' data: https:",
+ "font-src 'self' data:",
+ "connect-src 'self' https://*.supabase.co wss://*.supabase.co",
+ "frame-src 'self'"
+ ].join('; ')
+ }
+ ]
+ }
+ ];
+ },
+
+ // Enable React Strict Mode
+ reactStrictMode: true,
+
+ // Remove powered by header
+ poweredByHeader: false,
+
+ // Compression
+ compress: true,
+
+ // Image optimization
+ images: {
+ domains: ['*.supabase.co'],
+ formats: ['image/avif', 'image/webp']
+ }
+};
+
+module.exports = nextConfig;
+```
+
+## 2. Rate Limiting
+
+**File: `src/lib/rate-limit.ts`**
+
+```typescript
+import { Ratelimit } from '@upstash/ratelimit';
+import { Redis } from '@upstash/redis';
+
+// Create Redis client
+const redis = new Redis({
+ url: process.env.UPSTASH_REDIS_REST_URL!,
+ token: process.env.UPSTASH_REDIS_REST_TOKEN!
+});
+
+// Create rate limiter
+export const ratelimit = new Ratelimit({
+ redis,
+ limiter: Ratelimit.slidingWindow(10, '10 s'), // 10 requests per 10 seconds
+ analytics: true
+});
+
+// Custom rate limits
+export const aiRatelimit = new Ratelimit({
+ redis,
+ limiter: Ratelimit.slidingWindow(3, '60 s'), // 3 AI requests per minute
+ analytics: true
+});
+
+export const authRatelimit = new Ratelimit({
+ redis,
+ limiter: Ratelimit.slidingWindow(5, '60 s'), // 5 auth attempts per minute
+ analytics: true
+});
+```
+
+**File: `src/middleware.ts` (add rate limiting)**
+
+```typescript
+import { NextResponse } from 'next/server';
+import type { NextRequest } from 'next/server';
+import { ratelimit } from '@/lib/rate-limit';
+
+export async function middleware(request: NextRequest) {
+ // Rate limiting for API routes
+ if (request.nextUrl.pathname.startsWith('/api/')) {
+ const ip = request.ip ?? '127.0.0.1';
+ const { success, limit, reset, remaining } = await ratelimit.limit(ip);
+
+ if (!success) {
+ return NextResponse.json(
+ { error: 'Too many requests' },
+ {
+ status: 429,
+ headers: {
+ 'X-RateLimit-Limit': limit.toString(),
+ 'X-RateLimit-Remaining': remaining.toString(),
+ 'X-RateLimit-Reset': reset.toString()
+ }
+ }
+ );
+ }
+ }
+
+ return NextResponse.next();
+}
+```
+
+## 3. Input Validation
+
+**File: `src/lib/validation.ts`**
+
+```typescript
+import { z } from 'zod';
+
+// User schemas
+export const signUpSchema = z.object({
+ email: z.string().email('Invalid email address'),
+ password: z
+ .string()
+ .min(8, 'Password must be at least 8 characters')
+ .regex(
+ /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
+ 'Password must contain uppercase, lowercase, and number'
+ ),
+ fullName: z.string().min(2, 'Name must be at least 2 characters')
+});
+
+export const signInSchema = z.object({
+ email: z.string().email('Invalid email address'),
+ password: z.string().min(1, 'Password is required')
+});
+
+// Project schemas
+export const createProjectSchema = z.object({
+ name: z.string().min(1).max(100),
+ description: z.string().max(500).optional(),
+ framework: z.enum(['next', 'vite', 'remix'])
+});
+
+// Message schema
+export const chatMessageSchema = z.object({
+ message: z.string().min(1).max(5000),
+ conversationId: z.string().uuid()
+});
+
+// Validate function
+export function validate(schema: z.Schema, data: unknown): T {
+ try {
+ return schema.parse(data);
+ } catch (error) {
+ if (error instanceof z.ZodError) {
+ const errors = error.errors.map((e) => e.message).join(', ');
+ throw new Error(`Validation failed: ${errors}`);
+ }
+ throw error;
+ }
+}
+```
+
+## 4. SQL Injection Prevention
+
+Already handled by Supabase RLS, but for raw queries:
+
+**File: `src/lib/supabase/safe-query.ts`**
+
+```typescript
+import { createClient } from './server';
+
+export async function safeQuery(
+ query: string,
+ params: any[] = []
+): Promise {
+ const supabase = await createClient();
+
+ // Use parameterized queries
+ const { data, error } = await supabase.rpc('execute_safe_query', {
+ query_string: query,
+ query_params: params
+ });
+
+ if (error) throw error;
+ return data;
+}
+
+// Example usage:
+// const users = await safeQuery(
+// 'SELECT * FROM users WHERE email = $1',
+// ['user@example.com']
+// );
+```
+
+---
+
+# β‘ IV. PERFORMANCE OPTIMIZATION
+
+## 1. Image Optimization
+
+**File: `src/components/optimized-image.tsx`**
+
+```typescript
+import Image from 'next/image';
+import { useState } from 'react';
+
+interface OptimizedImageProps {
+ src: string;
+ alt: string;
+ width?: number;
+ height?: number;
+ className?: string;
+ priority?: boolean;
+}
+
+export function OptimizedImage({
+ src,
+ alt,
+ width,
+ height,
+ className,
+ priority = false
+}: OptimizedImageProps) {
+ const [isLoading, setIsLoading] = useState(true);
+
+ return (
+
+ setIsLoading(false)}
+ className={`
+ duration-700 ease-in-out
+ ${isLoading ? 'scale-110 blur-2xl grayscale' : 'scale-100 blur-0 grayscale-0'}
+ `}
+ sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
+ />
+
+ );
+}
+```
+
+## 2. Code Splitting
+
+**File: `src/app/project/[id]/page.tsx`**
+
+```typescript
+import dynamic from 'next/dynamic';
+import { Suspense } from 'react';
+import { LoadingSpinner } from '@/components/ui/loading';
+
+// Lazy load heavy components
+const ProjectEditor = dynamic(
+ () => import('@/components/project/project-editor'),
+ {
+ loading: () => ,
+ ssr: false
+ }
+);
+
+const LivePreview = dynamic(
+ () => import('@/components/preview/live-preview'),
+ {
+ loading: () => ,
+ ssr: false
+ }
+);
+
+export default async function ProjectPage({ params }: { params: { id: string } }) {
+ // ... fetch data
+
+ return (
+ }>
+
+
+ );
+}
+```
+
+## 3. Database Query Optimization
+
+**File: `src/lib/supabase/optimized-queries.ts`**
+
+```typescript
+import { createClient } from './server';
+
+// Use select to only fetch needed columns
+export async function getProjects() {
+ const supabase = await createClient();
+
+ const { data, error } = await supabase
+ .from('projects')
+ .select('id, name, description, updated_at') // Only needed fields
+ .order('updated_at', { ascending: false })
+ .limit(20); // Pagination
+
+ if (error) throw error;
+ return data;
+}
+
+// Use joins to avoid N+1 queries
+export async function getProjectWithMessages(projectId: string) {
+ const supabase = await createClient();
+
+ const { data, error } = await supabase
+ .from('projects')
+ .select(`
+ *,
+ conversations (
+ id,
+ messages (
+ id,
+ role,
+ content,
+ created_at
+ )
+ )
+ `)
+ .eq('id', projectId)
+ .single();
+
+ if (error) throw error;
+ return data;
+}
+
+// Use count for pagination
+export async function getProjectsWithCount(page: number = 1, limit: number = 20) {
+ const supabase = await createClient();
+
+ const from = (page - 1) * limit;
+ const to = from + limit - 1;
+
+ const { data, error, count } = await supabase
+ .from('projects')
+ .select('*', { count: 'exact' })
+ .range(from, to)
+ .order('updated_at', { ascending: false });
+
+ if (error) throw error;
+
+ return {
+ projects: data,
+ total: count,
+ page,
+ totalPages: Math.ceil((count || 0) / limit)
+ };
+}
+```
+
+---
+
+_Continue vα»i Production Deployment vΓ Disaster Recovery trong message tiαΊΏp..._