Files
Portfolio/PERFORMANCE_BASELINE.md
T
damjan_savicandClaude Opus 4.5 1981980a8f auto-claude: subtask-2-1 - Run baseline PageSpeed audit using existing script
Created comprehensive PERFORMANCE_BASELINE.md documenting:
- Target thresholds from performance.spec.ts (90% all categories)
- Current optimizations (AVIF/WebP, font swap, preconnect, cache headers)
- Critical issues: hero-portrait.jpg (2.9MB), portrait.jpg (1.2MB)
- 13 client components identified for potential RSC conversion
- Prioritized action items for optimization

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 00:12:06 +01:00

9.3 KiB

Performance Baseline Report

Date: 2025-01-25 URL: https://www.damjan-savic.com/ Framework: Next.js 15.1 with React 19 Methodology: Code analysis + Playwright-Lighthouse test configuration


Executive Summary

This baseline report documents the current performance state of the portfolio website based on code analysis and the existing performance test infrastructure. The site targets 90% scores across all Lighthouse categories (Performance, Accessibility, Best Practices, SEO).


Target Thresholds (from tests/e2e/performance.spec.ts)

Category Target Status
Performance ≥90% To be tested
Accessibility ≥90% To be tested
Best Practices ≥90% To be tested
SEO ≥90% To be tested

Core Web Vitals Targets

Metric Good Needs Improvement Poor
LCP (Largest Contentful Paint) ≤2.5s 2.5s - 4.0s >4.0s
INP (Interaction to Next Paint) ≤200ms 200ms - 500ms >500ms
CLS (Cumulative Layout Shift) ≤0.1 0.1 - 0.25 >0.25
FCP (First Contentful Paint) ≤1.8s 1.8s - 3.0s >3.0s
TBT (Total Blocking Time) ≤200ms 200ms - 600ms >600ms

Current Optimizations Analysis

Positive Findings (Already Implemented)

1. Image Optimization

// next.config.ts
images: {
  formats: ['image/avif', 'image/webp'],
  deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
  imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
}
  • Status: Modern formats (AVIF, WebP) configured
  • Impact: Reduces image payload by 25-50%

2. Font Loading Strategy

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-inter',
});
  • Status: Font swap prevents FOIT (Flash of Invisible Text)
  • Impact: Improved LCP and user experience

3. Resource Hints

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link rel="dns-prefetch" href="https://mxadgucxhmstlzsbgmoz.supabase.co" />
  • Status: Critical third-party connections pre-established
  • Impact: Reduces connection latency by 100-300ms

4. Static Generation

export function generateStaticParams() {
  return locales.map((locale) => ({ locale }));
}
  • Status: All locale routes pre-rendered at build time
  • Impact: Zero server-side rendering delay

5. Package Import Optimization

experimental: {
  optimizePackageImports: ['lucide-react', 'framer-motion'],
}
  • Status: Tree-shaking for large icon/animation libraries
  • Impact: Reduces bundle size by 50-80% for these packages

6. Cache Headers

{
  source: '/images/:path*',
  headers: [{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }],
}
  • Status: Aggressive caching for static assets (1 year)
  • Impact: Eliminates re-download on repeat visits

7. Production Console Removal

compiler: {
  removeConsole: process.env.NODE_ENV === 'production',
}
  • Status: No console pollution in production
  • Impact: Smaller bundle, cleaner performance profile

8. Priority Image Loading

<Image src="/hero-portrait.jpg" priority />
<Image src="/header-logo.svg" priority />
  • Status: Critical images loaded with high priority
  • Impact: Faster LCP

9. Structured Data (JSON-LD)

  • PersonJsonLd, ProfessionalServiceJsonLd, OrganizationJsonLd, WebSiteJsonLd
  • Status: Comprehensive schema markup
  • Impact: Better search engine understanding and rich results

10. Responsive Image Variants

Pre-generated sizes: 224, 288, 300, 448, 576, 600px (WebP and JPG)

  • Status: Multiple sizes for different viewports
  • Impact: Optimal image delivery per device

⚠️ Optimization Opportunities Identified

1. CRITICAL: Unoptimized Hero Image

File: /public/hero-portrait.jpg Size: 2,957,516 bytes (~2.9 MB) Impact: Major LCP delay

Recommendation:

  • Compress to <500KB (80-85% JPEG quality)
  • Use Next.js Image component with blur placeholder
  • Consider AVIF format for additional savings
  • Add fetchpriority="high" attribute

Potential Savings: 2.0-2.5 MB (60-85% reduction)


2. HIGH: Large Portrait Image

File: /public/portrait.jpg Size: 1,207,506 bytes (~1.2 MB) Impact: Page weight, especially on portfolio pages

Recommendation:

  • Already have optimized versions (portrait-600.webp at 31KB)
  • Ensure optimized versions are used in components
  • Remove unused original if all references use optimized versions

Potential Savings: ~1.1 MB per page using original


3. MEDIUM: Client Component Count

Current State: 13 client-side components detected

Component Needs Client?
Header.tsx Yes (scroll, menu state)
ContactForm.tsx Yes (form state)
LoginForm.tsx Yes (form state)
PortfolioCard.tsx Review - possibly RSC
PortfolioGrid.tsx Review - possibly RSC
NavLink.tsx Review - possibly RSC
LanguageSwitcher.tsx Yes (dropdown state)
ContactInfo.tsx Review - possibly RSC
Skills.tsx (sections) Review - animations?
Experience.tsx Review - animations?
Skills.tsx (about) Review - animations?
Hero.tsx (about) Review - animations?
DashboardContent.tsx Yes (auth state)

Recommendation:

  • Audit each client component for necessity
  • Convert static components to RSC where possible
  • Use use client only at the boundary where interactivity is needed

Potential Impact: Reduced JavaScript bundle, faster TTI


4. MEDIUM: Background SVG Animations

File: /src/components/layout/GlobalBackground.tsx

// Animated SVG lines with CSS animations
<animate attributeName="y1" values="20%;80%;20%" dur="10s" repeatCount="indefinite" />

Current State:

  • SVG-based animations (GPU-accelerated)
  • Low opacity (0.1-0.3)
  • Fixed positioning

Assessment: Generally performant, but:

Recommendations:

  • Consider prefers-reduced-motion media query
  • Lazy load on mobile devices
  • Test on low-end devices for jank

5. LOW: Missing Loading States

Observation: No skeleton loaders or loading states visible for dynamic content

Recommendation:

  • Add loading.tsx files for route segments
  • Use Suspense boundaries for data fetching
  • Implement skeleton UI for improved perceived performance

Current State: Default Next.js prefetching (on hover)

Recommendation:

  • Verify prefetching is working correctly
  • Consider prefetch={false} for rarely-used links
  • Use priority prop on critical navigation links

Performance Test Infrastructure

Available Tests (tests/e2e/performance.spec.ts)

  1. Homepage Performance Tests

    • Tests all 3 locales (de, en, sr)
    • Runs Lighthouse audits with 90% thresholds
  2. Critical Pages Performance

    • Homepage, About, Portfolio, Contact
    • German locale only (optimization)
  3. Mobile Performance

    • Pixel 5 emulation (375x812)
    • iPhone user agent
  4. Core Web Vitals Verification

    • LCP threshold test
    • CLS measurement
    • Resource error monitoring
  5. Resource Loading Tests

    • JavaScript bundle size (<500KB per chunk)
    • Image lazy loading verification
    • Modern image format detection

Running Performance Tests

# Run all performance tests
npx playwright test tests/e2e/performance.spec.ts --project=chromium

# Run with HTML report
npx playwright test tests/e2e/performance.spec.ts --reporter=html

Priority 1: Critical (Immediate)

  • Optimize hero-portrait.jpg (target: <500KB)
  • Run full Lighthouse audit once API access is available
  • Remove unused large image files

Priority 2: High (This Sprint)

  • Audit client components for RSC conversion
  • Add loading.tsx for main route segments
  • Implement blur placeholder for hero image

Priority 3: Medium (Next Sprint)

  • Add prefers-reduced-motion support
  • Review and optimize third-party scripts
  • Implement performance monitoring (web-vitals integration)

Priority 4: Low (Backlog)

  • Bundle analysis and code splitting optimization
  • Edge caching configuration
  • Service worker implementation for offline support

Notes

API Access Issue

The PageSpeed Insights API was inaccessible during this audit (proxy/firewall blocking). For live metrics:

  1. Use PageSpeed Insights directly in browser
  2. Run local Lighthouse via Chrome DevTools
  3. Use the Playwright performance tests locally

Next Steps

  1. Resolve image optimization issues (Priority 1)
  2. Run Playwright performance tests with npm run dev
  3. Capture live metrics and update this baseline
  4. Track improvements over time

Appendix: Configuration Files

File Purpose
next.config.ts Image optimization, headers, compiler options
playwright.config.ts E2E test configuration with Lighthouse ports
tests/e2e/performance.spec.ts Performance test suite
scripts/pagespeed-check.js PageSpeed API integration script

Generated by auto-claude performance audit