# Performance Optimization Checklist **Current Status**: Largest Contentful Paint (LCP) = 2.6s **Target**: LCP < 1.2s (excellent), < 2.5s (good) **Priority**: 🔴 Critical - Blocking user experience **Instructions**: Each task should be completed individually. AI should ask for user validation before marking as complete and moving to next task. --- ## 🚨 Critical Issues (Must Fix) ### Task 1: Remove Blocking Startup Check from Layout **Impact**: -1.5s LCP improvement **Status**: ❌ Pending **File**: `app/layout.tsx` **Lines**: 37-40 **Action**: Remove the following blocking code from root layout: ```typescript // REMOVE THIS: if (typeof window === 'undefined') { const { runStartupChecks } = await import('@/lib/startup') await runStartupChecks() } ``` **Validation**: Page should load immediately without waiting for database connections - [ ] **TASK 1 COMPLETED** ✅ --- ### Task 2: Create Background Startup Instrumentation **Impact**: Maintain startup checks without blocking **Status**: ❌ Pending **File**: Create `app/instrumentation.ts` **Action**: Create new file with background startup checks: ```typescript export async function register() { if (process.env.NEXT_RUNTIME === 'nodejs') { import('./lib/startup').then(({ runStartupChecks }) => { runStartupChecks().catch(console.error) }) } } ``` **Validation**: Startup checks run in background, visible in terminal logs - [ ] **TASK 2 COMPLETED** ✅ --- ### Task 3: Create Redis User Caching Utility **Impact**: -0.45s improvement **Status**: ❌ Pending **File**: Create `lib/auth-cache.ts` **Action**: Create Redis caching utility: ```typescript import { connectRedis } from './redis' const USER_CACHE_PREFIX = 'user:' const CACHE_TTL = 300 // 5 minutes export async function getCachedUser(userId: string) { try { const redis = await connectRedis() const cached = await redis.get(`${USER_CACHE_PREFIX}${userId}`) return cached ? JSON.parse(cached) : null } catch (error) { console.error('Redis cache get error:', error) return null // Fallback to DB if Redis fails } } export async function setCachedUser(userId: string, userData: any) { try { const redis = await connectRedis() await redis.setex(`${USER_CACHE_PREFIX}${userId}`, CACHE_TTL, JSON.stringify(userData)) } catch (error) { console.error('Redis cache set error:', error) // Don't throw - caching is optional } } export async function clearCachedUser(userId: string) { try { const redis = await connectRedis() await redis.del(`${USER_CACHE_PREFIX}${userId}`) } catch (error) { console.error('Redis cache clear error:', error) } } ``` **Validation**: File created with proper Redis integration - [ ] **TASK 3 COMPLETED** ✅ --- ### Task 4: Update /me Endpoint to Use Redis Cache **Impact**: Reduce MongoDB calls by 80% **Status**: ❌ Pending **File**: `app/api/auth/me/route.ts` **Action**: Replace the current GET function with: ```typescript import { getCachedUser, setCachedUser } from '@/lib/auth-cache' export const GET = withAuth(async (request: NextRequest & { user?: any }) => { try { // 1. Check Redis cache first const cached = await getCachedUser(request.user.userId) if (cached) { return NextResponse.json({ success: true, data: { user: cached }, }) } // 2. Only hit MongoDB if not cached await connectDB() const user = await User.findById(request.user.userId).select('-password -refreshToken').lean() // Better performance if (!user) { return NextResponse.json( { success: false, error: { message: 'User not found', code: 'USER_NOT_FOUND' } }, { status: 404 } ) } // 3. Cache for next time await setCachedUser(request.user.userId, user) return NextResponse.json({ success: true, data: { user }, }) } catch (error) { console.error('Get user info error:', error) return NextResponse.json( { success: false, error: { message: 'Internal server error', code: 'INTERNAL_ERROR' } }, { status: 500 } ) } }) ``` **Validation**: /me endpoint returns cached data on subsequent calls - [ ] **TASK 4 COMPLETED** ✅ --- ### Task 5: Add Cache Invalidation to User Updates **Impact**: Ensure cache consistency **Status**: ❌ Pending **File**: `app/api/auth/refresh/route.ts` **Action**: Add cache clearing after user update: ```typescript // Add import at top: import { setCachedUser } from '@/lib/auth-cache' // After user.save(), add: await setCachedUser(user._id.toString(), user.toJSON()) ``` **Validation**: User cache updates when refresh token is used - [ ] **TASK 5 COMPLETED** ✅ --- ### Task 6: Optimize Auth Context with localStorage **Impact**: -0.25s improvement **Status**: ❌ Pending **File**: `contexts/AuthContext.tsx` **Lines**: 157-180 **Action**: Replace the restoreSession function: ```typescript const restoreSession = async () => { try { setLoading(true) // 1. Load from localStorage immediately (sync) const cachedUser = localStorage.getItem('nextjs_user') if (cachedUser) { const userData = JSON.parse(cachedUser) setUser(userData) setHasCheckedAuth(true) setLoading(false) // 2. Validate in background (async) apiCall('/me') .then((data) => { setUser(data.data.user) localStorage.setItem('nextjs_user', JSON.stringify(data.data.user)) }) .catch(() => { // Try refresh token if /me fails apiCall('/refresh', { method: 'POST' }) .then((refreshData) => { setUser(refreshData.data.user) localStorage.setItem('nextjs_user', JSON.stringify(refreshData.data.user)) }) .catch(() => { // Both failed, clear cache and user localStorage.removeItem('nextjs_user') setUser(null) }) }) return } // 3. Only do full auth check if no cached user const data = await apiCall('/me') setUser(data.data.user) localStorage.setItem('nextjs_user', JSON.stringify(data.data.user)) setHasCheckedAuth(true) } catch (err) { // If /me fails, try refresh token try { const refreshData = await apiCall('/refresh', { method: 'POST' }) setUser(refreshData.data.user) localStorage.setItem('nextjs_user', JSON.stringify(refreshData.data.user)) setHasCheckedAuth(true) } catch (refreshErr) { // Both failed, user is not authenticated setUser(null) setHasCheckedAuth(true) } } finally { setLoading(false) } } ``` **Validation**: Page loads show cached user immediately, then validates in background - [ ] **TASK 6 COMPLETED** ✅ --- ### Task 7: Clear localStorage on Logout **Impact**: Proper cache cleanup **Status**: ❌ Pending **File**: `contexts/AuthContext.tsx` **Function**: logout **Action**: Add localStorage clearing to logout function: ```typescript // In the logout function, add this line: localStorage.removeItem('nextjs_user') ``` **Validation**: User data cleared from localStorage after logout - [ ] **TASK 7 COMPLETED** ✅ --- ### Task 8: Add Database Query Optimization **Impact**: -0.1s improvement **Status**: ❌ Pending **File**: `app/api/auth/login/route.ts` **Lines**: 23 **Action**: Optimize user lookup query: ```typescript // Replace: const user = await User.findOne({ email: validatedData.email.toLowerCase() }) // With: const user = await User.findOne({ email: validatedData.email.toLowerCase() }) .lean() .select('+password') ``` **Validation**: Login queries use optimized database access - [ ] **TASK 8 COMPLETED** ✅ --- ## 📊 Progress Tracking **Completed**: 0/8 tasks **Expected LCP Improvement**: 0s of 2.2s total **Current Status**: Ready to start Task 1 --- ## 🎯 Success Criteria After completing all tasks: - **LCP**: Should improve from 2.6s to ~0.4s - **Redis Cache Hit Rate**: Should be >80% for /me endpoint - **Page Load**: Should render immediately without database waits - **Auth Restoration**: Should show cached user instantly --- **Next Action**: Start with Task 1 - Remove Blocking Startup Check