{
+ const start = Date.now();
+ const response = await fetch(request);
+ const duration = Date.now() - start;
+
+ // Log to D1 analytics
+ ctx.waitUntil(
+ env.ANALYTICS.prepare(
+ 'INSERT INTO metrics (endpoint, duration, status) VALUES (?, ?, ?)'
+ ).bind(request.url, duration, response.status).run()
+ );
+
+ return response;
+ }
+};
+```
+
+## Next Steps
+
+1. **Prototype:** Deploy simple edge auth worker (1 day)
+2. **Measure:** Compare edge vs origin performance (1 week)
+3. **Iterate:** Expand to rate limiting, A/B testing (1 month)
+4. **Optimize:** Move 70%+ traffic to edge (3 months)
+
+## References
+
+- [Cloudflare Workers Docs](https://developers.cloudflare.com/workers/)
+- [R2 Storage](https://developers.cloudflare.com/r2/)
+- [D1 Database](https://developers.cloudflare.com/d1/)
+- [Workers Examples](https://developers.cloudflare.com/workers/examples/)
+- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/)
diff --git a/docs/performance-checklist.md b/docs/performance-checklist.md
new file mode 100644
index 0000000..b6d9aca
--- /dev/null
+++ b/docs/performance-checklist.md
@@ -0,0 +1,753 @@
+# Performance Checklist for Mylder Platform
+
+## Core Web Vitals Targets
+
+### Production Goals (75th Percentile)
+
+| Metric | Target | Good | Needs Improvement | Poor |
+|--------|--------|------|-------------------|------|
+| **LCP** (Largest Contentful Paint) | <2.5s | <2.5s | 2.5s-4.0s | >4.0s |
+| **FID** (First Input Delay) | <100ms | <100ms | 100ms-300ms | >300ms |
+| **CLS** (Cumulative Layout Shift) | <0.1 | <0.1 | 0.1-0.25 | >0.25 |
+| **INP** (Interaction to Next Paint) | <200ms | <200ms | 200ms-500ms | >500ms |
+| **TTFB** (Time to First Byte) | <600ms | <800ms | 800ms-1800ms | >1800ms |
+| **FCP** (First Contentful Paint) | <1.8s | <1.8s | 1.8s-3.0s | >3.0s |
+
+### Current vs Target Performance
+
+**Baseline (before optimization):**
+```
+LCP: ~3.5s → Target: <2.5s (30% improvement needed)
+FID: ~150ms → Target: <100ms
+CLS: ~0.15 → Target: <0.1
+TTFB: ~800ms → Target: <600ms (edge caching)
+```
+
+### Measurement Tools
+
+#### 1. Real User Monitoring (RUM)
+```typescript
+// app/layout.tsx
+import { SpeedInsights } from '@vercel/speed-insights/next';
+import { Analytics } from '@vercel/analytics/react';
+
+export default function RootLayout({ children }) {
+ return (
+
+
+ {children}
+
+
+
+
+ );
+}
+```
+
+**Alternative:** Cloudflare Web Analytics (privacy-friendly, no cookies)
+```html
+
+```
+
+#### 2. Lab Testing
+```bash
+# Lighthouse (local)
+npx lighthouse https://mylder.io --view
+
+# WebPageTest (global)
+# https://www.webpagetest.org
+
+# Chrome DevTools
+# DevTools → Performance → Record → Analyze
+```
+
+#### 3. Continuous Monitoring
+```bash
+# Lighthouse CI (in CI/CD pipeline)
+npm install -g @lhci/cli
+lhci autorun --collect.url=https://mylder.io
+```
+
+## Next.js Optimization Settings
+
+### 1. Production Build Configuration
+
+```typescript
+// next.config.ts
+import type { NextConfig } from 'next';
+
+const nextConfig: NextConfig = {
+ // Enable React strict mode for better error handling
+ reactStrictMode: true,
+
+ // Optimize bundle size
+ swcMinify: true,
+
+ // Compress output
+ compress: true,
+
+ // Optimize images
+ images: {
+ formats: ['image/avif', 'image/webp'],
+ deviceSizes: [640, 750, 828, 1080, 1200, 1920],
+ imageSizes: [16, 32, 48, 64, 96, 128, 256],
+ minimumCacheTTL: 2592000, // 30 days
+ dangerouslyAllowSVG: false,
+ contentDispositionType: 'attachment',
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: 'supabase.mylder.io',
+ pathname: '/storage/v1/object/**',
+ },
+ ],
+ },
+
+ // Optimize fonts (automatic optimization)
+ optimizeFonts: true,
+
+ // Experimental features
+ experimental: {
+ // Optimize CSS
+ optimizeCss: true,
+ // Tree shaking for smaller bundles
+ optimizePackageImports: ['@radix-ui/react-icons', 'lucide-react'],
+ },
+
+ // Custom headers for caching
+ async headers() {
+ return [
+ {
+ source: '/:path*',
+ headers: [
+ {
+ key: 'X-DNS-Prefetch-Control',
+ value: 'on',
+ },
+ {
+ key: 'X-Frame-Options',
+ value: 'SAMEORIGIN',
+ },
+ ],
+ },
+ {
+ source: '/_next/static/:path*',
+ headers: [
+ {
+ key: 'Cache-Control',
+ value: 'public, max-age=31536000, immutable',
+ },
+ ],
+ },
+ {
+ source: '/_next/image/:path*',
+ headers: [
+ {
+ key: 'Cache-Control',
+ value: 'public, max-age=2592000, stale-while-revalidate=86400',
+ },
+ ],
+ },
+ ];
+ },
+};
+
+export default nextConfig;
+```
+
+### 2. Bundle Analyzer
+```bash
+# Install
+npm install -D @next/bundle-analyzer
+
+# next.config.ts
+import bundleAnalyzer from '@next/bundle-analyzer';
+
+const withBundleAnalyzer = bundleAnalyzer({
+ enabled: process.env.ANALYZE === 'true',
+});
+
+export default withBundleAnalyzer(nextConfig);
+
+# Run analysis
+ANALYZE=true npm run build
+```
+
+**Target:** Total bundle size <500KB (gzipped)
+
+### 3. Code Splitting Strategies
+
+#### Dynamic Imports
+```typescript
+// app/dashboard/page.tsx
+import dynamic from 'next/dynamic';
+
+// Lazy load heavy components
+const HeavyChart = dynamic(() => import('@/components/HeavyChart'), {
+ loading: () => ,
+ ssr: false, // Client-side only if needed
+});
+
+export default function Dashboard() {
+ return ;
+}
+```
+
+#### Route-Based Splitting
+```typescript
+// Automatic with App Router
+app/
+ dashboard/ # Separate chunk
+ settings/ # Separate chunk
+ (marketing)/ # Separate chunk (route group)
+```
+
+#### Vendor Splitting
+```typescript
+// next.config.ts
+experimental: {
+ optimizePackageImports: [
+ '@radix-ui/react-icons',
+ 'lucide-react',
+ 'date-fns',
+ ],
+},
+```
+
+### 4. Server Components (Default)
+```typescript
+// app/page.tsx (Server Component by default)
+export default async function Home() {
+ // Fetch at build time or request time
+ const data = await fetch('https://api.mylder.io/data', {
+ next: { revalidate: 3600 } // ISR: 1 hour cache
+ });
+
+ return {/* No client-side JS for this component */}
;
+}
+```
+
+**Benefits:**
+- 0KB JavaScript sent to client
+- Faster initial page load
+- Better SEO
+
+### 5. Client Components (Opt-In)
+```typescript
+// components/InteractiveButton.tsx
+'use client';
+
+import { useState } from 'react';
+
+export default function InteractiveButton() {
+ const [count, setCount] = useState(0);
+ return ;
+}
+```
+
+**Rule:** Only use 'use client' when you need:
+- Interactivity (useState, useEffect)
+- Browser APIs (localStorage, window)
+- Event handlers (onClick, onSubmit)
+
+## Image Optimization
+
+### 1. Next.js Image Component
+```typescript
+import Image from 'next/image';
+
+// Optimized image with automatic sizing
+
+
+// Responsive image
+
+```
+
+### 2. Image Format Priority
+1. **AVIF** (best compression, 50% smaller than JPEG)
+2. **WebP** (wide support, 30% smaller than JPEG)
+3. **JPEG/PNG** (fallback)
+
+### 3. Cloudflare Image Optimization
+```typescript
+// next.config.ts
+images: {
+ loader: 'custom',
+ loaderFile: './lib/cloudflare-image-loader.ts',
+}
+
+// lib/cloudflare-image-loader.ts
+export default function cloudflareLoader({ src, width, quality }) {
+ const params = [`width=${width}`, `quality=${quality || 75}`, 'format=auto'];
+ return `https://mylder.io/cdn-cgi/image/${params.join(',')}/${src}`;
+}
+```
+
+### 4. Lazy Loading Images
+```typescript
+// Non-critical images (below fold)
+
+
+// Critical images (above fold, LCP)
+
+```
+
+### 5. Responsive Images Checklist
+- [ ] Use Next.js Image component (automatic optimization)
+- [ ] Set explicit width/height (prevent CLS)
+- [ ] Use `priority` for LCP images
+- [ ] Use `loading="lazy"` for below-fold images
+- [ ] Provide blur placeholder for better UX
+- [ ] Compress images before upload (80-85% quality)
+- [ ] Use modern formats (AVIF, WebP)
+
+## Font Optimization
+
+### 1. Next.js Font Optimization (Built-In)
+```typescript
+// app/layout.tsx
+import { Inter, Roboto_Mono } from 'next/font/google';
+
+const inter = Inter({
+ subsets: ['latin'],
+ display: 'swap', // Prevent invisible text flash
+ variable: '--font-inter',
+ preload: true,
+});
+
+const robotoMono = Roboto_Mono({
+ subsets: ['latin'],
+ display: 'swap',
+ variable: '--font-roboto-mono',
+ weight: ['400', '700'], // Only load needed weights
+});
+
+export default function RootLayout({ children }) {
+ return (
+
+ {children}
+
+ );
+}
+```
+
+**Benefits:**
+- Self-hosted fonts (no external requests)
+- Automatic subset optimization
+- Zero layout shift (font-display: swap)
+
+### 2. Custom Fonts
+```typescript
+import localFont from 'next/font/local';
+
+const myFont = localFont({
+ src: './fonts/MyFont.woff2',
+ display: 'swap',
+ variable: '--font-my-font',
+});
+```
+
+### 3. Font Loading Best Practices
+- [ ] Use only 2-3 font families max
+- [ ] Load only needed weights (400, 700)
+- [ ] Use `font-display: swap`
+- [ ] Preload critical fonts
+- [ ] Self-host fonts (no Google Fonts CDN)
+
+## CSS Optimization
+
+### 1. Tailwind CSS Production Config
+```typescript
+// tailwind.config.ts
+import type { Config } from 'tailwindcss';
+
+const config: Config = {
+ content: [
+ './app/**/*.{ts,tsx}',
+ './components/**/*.{ts,tsx}',
+ ],
+ theme: {
+ extend: {},
+ },
+ // Remove unused styles in production
+ future: {
+ hoverOnlyWhenSupported: true, // Better mobile UX
+ },
+};
+
+export default config;
+```
+
+### 2. Critical CSS
+Next.js automatically inlines critical CSS for first paint.
+
+### 3. CSS Module Best Practices
+```typescript
+// Use CSS Modules for component-specific styles
+import styles from './Button.module.css';
+
+export function Button() {
+ return ;
+}
+```
+
+## JavaScript Optimization
+
+### 1. Tree Shaking
+```typescript
+// Good: Import only what you need
+import { format } from 'date-fns';
+
+// Bad: Import entire library
+import * as dateFns from 'date-fns';
+```
+
+### 2. Remove Unused Dependencies
+```bash
+# Analyze bundle
+npx depcheck
+
+# Remove unused
+npm uninstall unused-package
+```
+
+### 3. Use Smaller Alternatives
+
+| Heavy Package | Lightweight Alternative | Savings |
+|---------------|------------------------|---------|
+| Moment.js (232KB) | date-fns (13KB) | 95% |
+| Lodash (70KB) | Lodash-es (24KB) | 66% |
+| Axios (30KB) | Fetch API (native) | 100% |
+| React Icons (full) | Lucide React (tree-shakeable) | 80% |
+
+### 4. Debounce/Throttle Heavy Operations
+```typescript
+// components/Search.tsx
+'use client';
+
+import { useState, useCallback } from 'react';
+import { debounce } from 'lodash-es/debounce';
+
+export function Search() {
+ const [query, setQuery] = useState('');
+
+ const handleSearch = useCallback(
+ debounce(async (value: string) => {
+ const results = await fetch(`/api/search?q=${value}`);
+ // Handle results
+ }, 300),
+ []
+ );
+
+ return handleSearch(e.target.value)} />;
+}
+```
+
+## Caching Strategy
+
+### 1. Static Generation (Fastest)
+```typescript
+// app/blog/page.tsx
+export const revalidate = false; // Static at build time
+
+export default async function Blog() {
+ const posts = await fetchPosts();
+ return ;
+}
+```
+
+### 2. Incremental Static Regeneration (ISR)
+```typescript
+// app/blog/[slug]/page.tsx
+export const revalidate = 3600; // Revalidate every hour
+
+export async function generateStaticParams() {
+ const posts = await fetchPosts();
+ return posts.map((post) => ({ slug: post.slug }));
+}
+
+export default async function Post({ params }) {
+ const post = await fetchPost(params.slug);
+ return ;
+}
+```
+
+### 3. Server-Side Rendering (SSR)
+```typescript
+// app/dashboard/page.tsx
+export const dynamic = 'force-dynamic'; // Always server-render
+
+export default async function Dashboard() {
+ const data = await fetchUserData(); // Per-request
+ return ;
+}
+```
+
+### 4. Client-Side Caching
+```typescript
+// Use SWR or React Query for client-side data fetching
+'use client';
+
+import useSWR from 'swr';
+
+export function Profile() {
+ const { data, error } = useSWR('/api/user', fetcher, {
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false,
+ refreshInterval: 60000, // 1 minute
+ });
+
+ if (error) return Error
;
+ if (!data) return Loading...
;
+ return {data.name}
;
+}
+```
+
+### 5. HTTP Cache Headers
+```typescript
+// app/api/data/route.ts
+export async function GET() {
+ const data = await fetchData();
+
+ return new Response(JSON.stringify(data), {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Cache-Control': 'public, max-age=3600, stale-while-revalidate=86400',
+ },
+ });
+}
+```
+
+## Cache Invalidation Strategy
+
+### 1. On-Demand Revalidation
+```typescript
+// app/api/revalidate/route.ts
+import { revalidatePath, revalidateTag } from 'next/cache';
+
+export async function POST(request: Request) {
+ const { path, tag } = await request.json();
+
+ if (path) {
+ revalidatePath(path);
+ }
+
+ if (tag) {
+ revalidateTag(tag);
+ }
+
+ return Response.json({ revalidated: true });
+}
+```
+
+### 2. Webhook Triggers (n8n)
+```typescript
+// n8n workflow: CMS Update → POST /api/revalidate
+{
+ "path": "/blog",
+ "tag": "posts"
+}
+```
+
+### 3. Cloudflare Cache Purge
+```bash
+# On deploy (CI/CD)
+curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
+ -H "Authorization: Bearer {api_token}" \
+ -H "Content-Type: application/json" \
+ --data '{"purge_everything":true}'
+```
+
+### 4. Selective Purge
+```bash
+# Purge specific URLs
+--data '{"files":["https://mylder.io/blog","https://mylder.io/about"]}'
+
+# Purge by tag
+--data '{"tags":["blog-posts"]}'
+```
+
+## Performance Testing Workflow
+
+### 1. Pre-Deploy Checks
+```bash
+# Run before every deployment
+npm run build # Must succeed
+npm run lint # No errors
+npm run typecheck # No type errors
+
+# Optional but recommended
+ANALYZE=true npm run build # Check bundle size
+npx lighthouse https://staging.mylder.io --view
+```
+
+### 2. Post-Deploy Verification
+```bash
+# Production smoke tests
+curl -I https://mylder.io # Check TTFB
+curl -I https://mylder.io/_next/static/[hash]/[file].js # Check caching
+
+# Full performance audit
+npx lighthouse https://mylder.io --view
+
+# Real user monitoring
+# Check Cloudflare Analytics or Vercel Analytics dashboard
+```
+
+### 3. Continuous Monitoring
+```bash
+# Set up alerts in Cloudflare/monitoring tool
+- LCP > 3s → Alert
+- Error rate > 1% → Alert
+- TTFB > 1s → Alert
+```
+
+## Quick Wins Checklist
+
+### Immediate (1 day)
+- [ ] Enable Cloudflare CDN (see cloudflare-setup.md)
+- [ ] Add proper cache headers to static assets
+- [ ] Use Next.js Image component everywhere
+- [ ] Enable `reactStrictMode` and `swcMinify`
+- [ ] Remove unused dependencies
+
+### Short-term (1 week)
+- [ ] Implement ISR for blog/content pages
+- [ ] Lazy load heavy components
+- [ ] Optimize images (compress, convert to WebP/AVIF)
+- [ ] Set up bundle analyzer
+- [ ] Add loading states and skeletons (improve perceived performance)
+
+### Medium-term (1 month)
+- [ ] Implement edge caching for auth (see cloudflare-workers-roadmap.md)
+- [ ] Set up real user monitoring (RUM)
+- [ ] Optimize third-party scripts (defer/async)
+- [ ] Implement stale-while-revalidate for APIs
+- [ ] Add Lighthouse CI to deployment pipeline
+
+### Long-term (3 months)
+- [ ] Move 70% traffic to edge (Cloudflare Workers)
+- [ ] Implement edge personalization
+- [ ] Set up A/B testing at edge
+- [ ] Achieve Core Web Vitals targets consistently
+- [ ] Reduce VPS load by 60%+
+
+## Common Performance Issues & Fixes
+
+### Issue: High LCP (>4s)
+**Causes:**
+- Large hero image not optimized
+- Server response time (TTFB) too high
+- Render-blocking resources
+
+**Fixes:**
+- Use Next.js Image with `priority` for LCP image
+- Enable Cloudflare CDN for faster TTFB
+- Inline critical CSS
+- Preload fonts
+
+### Issue: High CLS (>0.25)
+**Causes:**
+- Images without width/height
+- Web fonts loading late
+- Dynamic content injections
+
+**Fixes:**
+- Set explicit dimensions on images
+- Use `font-display: swap`
+- Reserve space for dynamic content
+- Avoid inserting content above existing content
+
+### Issue: High FID/INP (>300ms)
+**Causes:**
+- Heavy JavaScript execution
+- Long tasks blocking main thread
+- Unoptimized event handlers
+
+**Fixes:**
+- Code split large bundles
+- Debounce/throttle event handlers
+- Use Web Workers for heavy computation
+- Optimize third-party scripts
+
+### Issue: Slow TTFB (>1s)
+**Causes:**
+- Slow server response
+- No CDN
+- Database queries during render
+
+**Fixes:**
+- Enable Cloudflare CDN
+- Use ISR instead of SSR
+- Move database queries to edge (D1)
+- Implement caching layers
+
+## Monitoring Dashboard Setup
+
+### Cloudflare Web Analytics
+```html
+
+
+```
+
+### Custom Performance Monitoring
+```typescript
+// app/layout.tsx
+'use client';
+
+import { useEffect } from 'react';
+import { usePathname } from 'next/navigation';
+
+export function PerformanceMonitor() {
+ const pathname = usePathname();
+
+ useEffect(() => {
+ // Measure Web Vitals
+ import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ getCLS(console.log);
+ getFID(console.log);
+ getFCP(console.log);
+ getLCP(console.log);
+ getTTFB(console.log);
+ });
+ }, [pathname]);
+
+ return null;
+}
+```
+
+## Resources
+
+- [Next.js Performance Docs](https://nextjs.org/docs/app/building-your-application/optimizing)
+- [Web.dev Core Web Vitals](https://web.dev/vitals/)
+- [Lighthouse CI](https://github.com/GoogleChrome/lighthouse-ci)
+- [Cloudflare Performance](https://developers.cloudflare.com/fundamentals/speed/)
diff --git a/src/app/health/route.ts b/src/app/health/route.ts
new file mode 100644
index 0000000..c8c2736
--- /dev/null
+++ b/src/app/health/route.ts
@@ -0,0 +1,5 @@
+import { NextResponse } from 'next/server'
+
+export async function GET() {
+ return NextResponse.json({ status: 'ok', timestamp: Date.now() })
+}
diff --git a/supabase/migrations/20241214_add_phase_metadata.sql b/supabase/migrations/20241214_add_phase_metadata.sql
new file mode 100644
index 0000000..f8b0be4
--- /dev/null
+++ b/supabase/migrations/20241214_add_phase_metadata.sql
@@ -0,0 +1,70 @@
+-- Add phase_metadata column for agentic workflow tracking
+ALTER TABLE projects ADD COLUMN IF NOT EXISTS phase_metadata JSONB DEFAULT '{
+ "currentPhase": "think",
+ "completedPhases": [],
+ "phaseStatus": "not_started",
+ "activities": [],
+ "metrics": {
+ "totalDuration": 0,
+ "phaseDurations": {},
+ "iterationCount": 0
+ }
+}'::jsonb;
+
+-- Create index for efficient querying
+CREATE INDEX IF NOT EXISTS idx_projects_phase_metadata ON projects USING gin(phase_metadata);
+
+-- Add comment for documentation
+COMMENT ON COLUMN projects.phase_metadata IS 'Stores agentic development loop state: currentPhase, completedPhases, phaseStatus, activities, metrics';
+
+-- Create function to update phase
+CREATE OR REPLACE FUNCTION update_project_phase(
+ p_project_id UUID,
+ p_new_phase TEXT,
+ p_status TEXT DEFAULT 'in_progress'
+)
+RETURNS JSONB AS $$
+DECLARE
+ v_current_metadata JSONB;
+ v_current_phase TEXT;
+ v_completed_phases JSONB;
+ v_new_activity JSONB;
+ v_updated_metadata JSONB;
+BEGIN
+ -- Get current metadata
+ SELECT phase_metadata INTO v_current_metadata
+ FROM projects WHERE id = p_project_id;
+
+ v_current_phase := v_current_metadata->>'currentPhase';
+ v_completed_phases := COALESCE(v_current_metadata->'completedPhases', '[]'::jsonb);
+
+ -- Add current phase to completed if transitioning
+ IF v_current_phase IS NOT NULL AND v_current_phase != p_new_phase THEN
+ v_completed_phases := v_completed_phases || to_jsonb(v_current_phase);
+ END IF;
+
+ -- Create activity record
+ v_new_activity := jsonb_build_object(
+ 'id', gen_random_uuid(),
+ 'type', 'phase_change',
+ 'message', 'Transitioned to ' || p_new_phase || ' phase',
+ 'timestamp', now()
+ );
+
+ -- Build updated metadata
+ v_updated_metadata := jsonb_build_object(
+ 'currentPhase', p_new_phase,
+ 'completedPhases', v_completed_phases,
+ 'phaseStatus', p_status,
+ 'activities', (v_new_activity || COALESCE(v_current_metadata->'activities', '[]'::jsonb))[0:49],
+ 'metrics', COALESCE(v_current_metadata->'metrics', '{}'::jsonb)
+ );
+
+ -- Update project
+ UPDATE projects
+ SET phase_metadata = v_updated_metadata, updated_at = now()
+ WHERE id = p_project_id;
+
+ RETURN v_updated_metadata;
+END;
+$$ LANGUAGE plpgsql;