7.0 KiB
Core Web Vitals Optimization Report
Date: 2026-03-21 Agent: performance-optimizer Project: WorkRoot IT Solutions (workroot.in)
Baseline Performance (Pre-Optimization)
| Page | Performance | LCP | CLS | TBT |
|---|---|---|---|---|
| Home | 98/100 | ✅ Good | ✅ < 0.1 | ✅ Low |
| Services | 99/100 | ✅ Good | ✅ < 0.1 | ✅ Low |
| Portfolio | 99/100 | ✅ Good | ✅ < 0.1 | ✅ Low |
| About | 97/100 | ✅ Good | ✅ < 0.1 | ✅ Low |
| Contact | 99/100 | ✅ Good | ✅ < 0.1 | ✅ Low |
| Blog | 96/100 | ✅ Good | ✅ < 0.1 | ✅ Moderate |
| Average | 98/100 | ✅ | ✅ | ✅ |
Server: TTFB ~213ms, ~9ms SSR processing, 33 req/sec
Core Web Vitals Targets
| Metric | Target | Status |
|---|---|---|
| LCP (Largest Contentful Paint) | < 2.5s | ✅ Already good |
| INP (Interaction to Next Paint) | < 200ms | ✅ Already good |
| CLS (Cumulative Layout Shift) | < 0.1 | ✅ Already good |
Optimizations Implemented
1. Gzip/Brotli Compression — server.mjs
Impact: ~70% reduction in transfer size for HTML/CSS/JS responses.
Added compression Express middleware:
import compression from 'compression';
app.use(compression({ level: 6, threshold: 1024 }));
- Level 6 balances compression ratio vs CPU overhead
- Only compresses responses > 1KB (avoids overhead on tiny responses)
- Respects
X-No-Compressionheader for bypass
2. Static Asset Cache Headers — server.mjs
Impact: Near-instant repeat visits for returning users.
| Asset Type | Cache Duration | Strategy |
|---|---|---|
/_assets/* (hashed) |
1 year | immutable — never re-fetch |
Fonts (.woff2, .ttf) |
1 year | immutable |
Images (.webp, .png, etc.) |
1 week | stale-while-revalidate |
| Other static assets | 1 hour | max-age |
app.use('/_assets', express.static(path, {
maxAge: '1y',
immutable: true,
}));
3. Font Preload Hints — BaseLayout.astro
Impact: Eliminates render-blocking font load; faster FCP by ~200-400ms.
Replaced blocking @import with non-blocking load + preload hint:
<link rel="preload" as="style"
href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;700&display=swap"
onload="this.onload=null;this.rel='stylesheet'" />
<noscript>
<link rel="stylesheet" href="..." />
</noscript>
- Loads only the 2 critical weights (400/700) above-the-fold
- Full variable font range still loaded via
global.cssfor later content noscriptfallback ensures fonts load for users without JS
4. Enhanced Critical CSS — BaseLayout.astro
Impact: Faster FCP by rendering visible content immediately with correct styles.
Extended inlined critical CSS to include:
bodynow specifiesPlus Jakarta Sansfirst (vssystem-uifirst) to prevent FOUT-moz-osx-font-smoothing: grayscalefor Firefox text renderingimg { aspect-ratio: attr(width)/attr(height) }— native CLS prevention- Above-fold Tailwind utility classes (
min-h-screen,flex,flex-col,items-center) .animate-slide-up { animation-fill-mode: forwards }— prevents animation flicker
5. Navigation Prefetch Strategy — Header.astro + astro.config.mjs
Impact: Navigation feels instant (~100-300ms faster perceived navigation).
- Added
data-astro-prefetch="hover"to all desktop and mobile nav links - Changed
defaultStrategyfrom'viewport'to'hover'inastro.config.mjs hoverstrategy: prefetch starts when user hovers a link (150-200ms before click)- This gives the browser a head-start on the next page's HTML/assets
Pre-Existing Optimizations (Already in Place)
The following were already well-implemented by previous work:
Image Optimization ✅
- Sharp image service for WebP conversion
- Responsive
srcset(320–1920px breakpoints) - Native
loading="lazy"on all below-fold images - Aspect ratio wrappers on all images (CLS = 0)
- Blur placeholder support via
imageUtils.ts OptimizedImage.astroandLazyImage.astrocomponents
CSS Architecture ✅
- Tailwind CSS utility-first (no unused CSS)
- CSS code splitting by route (
cssCodeSplit: true) inlineStylesheets: 'auto'inlines small CSS files- Critical CSS inlined in
BaseLayout.astro
JavaScript Minimization ✅
- Zero heavy JS frameworks (no React bundle)
- Astro SSR with minimal client-side JS
compressHTML: trueminifies HTML output- Manual vendor chunk splitting for better caching
Resource Hints ✅
preconnectto Google Fonts (fonts.googleapis.com,fonts.gstatic.com)preconnectto Unsplash CDNdns-prefetchfor analytics providerspreconnectto GA4 and Plausible endpoints
Server Performance ✅
- TTFB: ~213ms (excellent for SSR)
- SSR processing: ~9ms
- Throughput: 33 req/sec
Remaining Opportunities (Future)
| Opportunity | Impact | Complexity |
|---|---|---|
| CDN (Cloudflare/Fastly) | High — global latency reduction | Medium |
| Self-hosted fonts | Medium — removes Google Fonts dependency | Low |
| HTTP/2 Push | Low — preload critical assets | Medium |
| Service Worker | Medium — offline support + cache | High |
| Edge Rendering | High — reduce TTFB globally | High |
| Image AVIF format | Low — ~20% smaller than WebP | Low |
| Font subsetting | Low — smaller font files | Low |
Files Modified
| File | Change |
|---|---|
server.mjs |
Added compression middleware + cache headers |
src/layouts/BaseLayout.astro |
Font preload + enhanced critical CSS |
src/components/Header.astro |
Added data-astro-prefetch="hover" to nav links |
astro.config.mjs |
Changed prefetch strategy to hover |
package.json |
Added compression dependency |
Validation Checklist
After deployment, verify with:
- PageSpeed Insights — LCP < 2.5s, CLS < 0.1, INP < 200ms
- WebPageTest — Check compression headers (
Content-Encoding: gzip) - Browser DevTools Network tab — Verify
Cache-Control: public, max-age=31536000on/_assets/ - Chrome DevTools Lighthouse — Run audit on all 6 pages
- web.dev/measure — Field data validation
Expected Header Values
# Static hashed assets
Cache-Control: public, max-age=31536000, immutable
# Images
Cache-Control: public, max-age=604800, stale-while-revalidate=86400
# HTML responses
Content-Encoding: gzip
Vary: Accept-Encoding
Summary
The project was already exceptional (98/100 avg Lighthouse). The optimizations implemented target the remaining performance gaps:
- Compression eliminates the biggest bandwidth bottleneck
- Caching makes repeat visits near-instant
- Font preload eliminates the last render-blocking resource
- Prefetch on hover makes navigation feel instantaneous
Expected improvement: +1-2 Lighthouse points on affected pages, with significant real-world improvement for repeat visitors (from cache) and first-time visitors on slow connections (from compression).