/install afrexai-web-performance-engine
Web Performance Engine
Complete web performance optimization system. Audit, diagnose, fix, and monitor — no external tools required (but integrates with Lighthouse, WebPageTest, Chrome DevTools when available).
Phase 1: Performance Audit
Quick Health Check
Run these checks in order. Stop when you find the bottleneck tier.
Tier 1 — Critical (blocks rendering):
- Time to First Byte (TTFB) > 800ms → server problem
- First Contentful Paint (FCP) > 1.8s → render-blocking resources
- Largest Contentful Paint (LCP) > 2.5s → hero element problem
- Total Blocking Time (TBT) > 200ms → JavaScript problem
- Cumulative Layout Shift (CLS) > 0.1 → layout instability
- Interaction to Next Paint (INP) > 200ms → event handler problem
Tier 2 — Important (affects experience):
- Page weight > 2MB
- Requests > 80
- JavaScript > 500KB (compressed)
- Images > 1MB total
- No compression (gzip/brotli)
- No caching headers
Tier 3 — Polish (competitive edge):
- Speed Index > 3.4s
- Time to Interactive > 3.8s
- Font loading causes flash
- Third-party scripts > 30% of JS
Audit Brief Template
audit:
url: ""
device: "mobile" # mobile | desktop | both
connection: "4G" # 3G | 4G | fiber
region: "" # closest to target users
scores:
performance: null # 0-100
fcp_ms: null
lcp_ms: null
tbt_ms: null
cls: null
inp_ms: null
ttfb_ms: null
page_weight:
total_kb: null
html_kb: null
css_kb: null
js_kb: null
images_kb: null
fonts_kb: null
other_kb: null
requests:
total: null
by_type: {}
third_party_count: null
third_party_kb: null
Getting Metrics Without Tools
If no Lighthouse/DevTools available, use web-based tools:
web_fetch "https://pagespeed.web.dev/analysis?url={encoded_url}"— Google's free toolweb_search "webpagetest {url}"— find cached resultsweb_search "site:{domain} core web vitals"— find CrUX data- Check
\x3Chead>for obvious issues: render-blocking CSS/JS, missing preloads, no meta viewport
Phase 2: Diagnosis — The Performance Waterfall
Critical Rendering Path Analysis
DNS → TCP → TLS → TTFB → HTML Parse → CSSOM → Render Tree → FCP → LCP
↓
JS Download → Parse → Execute → INP
Bottleneck Decision Tree:
High TTFB (>800ms)?
├─ YES → Phase 3A: Server optimization
└─ NO → High FCP (>1.8s)?
├─ YES → Phase 3B: Render-blocking resources
└─ NO → High LCP (>2.5s)?
├─ YES → Phase 3C: Hero element optimization
└─ NO → High TBT (>200ms)?
├─ YES → Phase 3D: JavaScript optimization
└─ NO → High CLS (>0.1)?
├─ YES → Phase 3E: Layout stability
└─ NO → High INP (>200ms)?
├─ YES → Phase 3F: Interaction optimization
└─ NO → ✅ Performance is good!
Resource Impact Scoring
Rate each resource by impact:
| Factor | Weight | Score 1 | Score 3 | Score 5 |
|---|---|---|---|---|
| Size (KB) | 3x | \x3C10 | 10-100 | >100 |
| Render-blocking | 5x | No | Partial | Full |
| Above-fold impact | 4x | None | Indirect | Direct |
| Cacheable | 2x | Long cache | Short cache | No cache |
| Compressible | 2x | Already done | Possible | Not compressed |
Priority = Sum(Factor × Weight). Fix highest scores first.
Phase 3: Fix Playbooks
3A: Server Optimization (TTFB)
Quick wins:
# CDN: If no CDN, this is #1 priority
# Check: curl -sI {url} | grep -i 'x-cache\|cf-cache\|x-cdn'
# Compression: Must have brotli or gzip
# Check: curl -sI -H "Accept-Encoding: br,gzip" {url} | grep -i content-encoding
# HTTP/2 or HTTP/3
# Check: curl -sI --http2 {url} | head -1
Server-side checklist:
- CDN in front (Cloudflare, Fastly, CloudFront)
- Brotli compression enabled (20-30% smaller than gzip)
- HTTP/2 minimum, HTTP/3 if possible
- Server-side caching (Redis, Varnish)
- Database query optimization (\x3C50ms per query)
- Connection pooling enabled
- Edge computing for dynamic content (Workers, Lambda@Edge)
Cache headers template:
# Static assets (CSS, JS, images, fonts)
Cache-Control: public, max-age=31536000, immutable
# HTML pages
Cache-Control: public, max-age=0, must-revalidate
# API responses
Cache-Control: private, max-age=60, stale-while-revalidate=300
3B: Render-Blocking Resources (FCP)
CSS optimization:
\x3C!-- BEFORE: Render-blocking -->
\x3Clink rel="stylesheet" href="styles.css">
\x3C!-- AFTER: Critical CSS inline + async load -->
\x3Cstyle>/* Critical above-fold CSS here (\x3C 14KB) */\x3C/style>
\x3Clink rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
\x3Cnoscript>\x3Clink rel="stylesheet" href="styles.css">\x3C/noscript>
Rules:
- Inline critical CSS (above-fold styles, \x3C 14KB)
- Defer non-critical CSS
- Remove unused CSS (typical savings: 60-90%)
- Combine media queries
- Avoid
@import(creates sequential loading)
JavaScript optimization:
\x3C!-- BEFORE: Render-blocking -->
\x3Cscript src="app.js">\x3C/script>
\x3C!-- AFTER: Non-blocking -->
\x3Cscript src="app.js" defer>\x3C/script>
\x3C!-- OR: Independent scripts -->
\x3Cscript src="analytics.js" async>\x3C/script>
Rules:
deferfor app scripts (maintains order, runs after parse)asyncfor independent scripts (analytics, ads)- Never put
\x3Cscript>in\x3Chead>without defer/async - Inline small scripts (\x3C 1KB)
3C: Hero Element Optimization (LCP)
LCP element types and fixes:
| LCP Element | Fix |
|---|---|
\x3Cimg> |
Preload + responsive + modern format |
\x3Cvideo> poster |
Preload poster image |
CSS background-image |
Preload + inline critical CSS |
| Text block | Preload font + font-display: optional |
Image optimization checklist:
\x3C!-- Optimal hero image -->
\x3Clink rel="preload" as="image" href="hero.webp"
imagesrcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
imagesizes="100vw">
\x3Cimg src="hero.webp"
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
sizes="100vw"
width="1200" height="600"
alt="Hero description"
fetchpriority="high"
decoding="async">
Image format decision:
Photo/complex image? → WebP (25-35% smaller than JPEG)
→ AVIF (50% smaller, but slower encode)
Simple graphic/logo? → SVG (scalable, tiny)
→ PNG only if transparency needed
Animation? → WebM/MP4 video (not GIF — 90% smaller)
Image size targets:
| Viewport | Max width | Target KB |
|---|---|---|
| Mobile | 400px | \x3C 50KB |
| Tablet | 800px | \x3C 100KB |
| Desktop | 1200px | \x3C 150KB |
| Hero/banner | 1600px | \x3C 200KB |
3D: JavaScript Optimization (TBT)
Bundle analysis approach:
- Check total JS size:
web_fetchthe page, count\x3Cscript>tags - Identify large libraries (React, Lodash, Moment.js)
- Check for duplicate code across bundles
- Identify unused exports
Common JS bloat and replacements:
| Library | Size | Alternative | Size |
|---|---|---|---|
| moment.js | 67KB | date-fns | 2-10KB |
| lodash (full) | 71KB | lodash-es (tree-shake) | 2-5KB |
| jQuery | 87KB | vanilla JS | 0KB |
| animate.css | 80KB | CSS animations | 1-2KB |
| chart.js | 60KB | lightweight-charts | 40KB |
Code splitting rules:
- Route-based splitting (each page loads its own JS)
- Component-level splitting for heavy components (modals, editors, charts)
- Dynamic import for below-fold features:
const Chart = lazy(() => import('./Chart')) - Vendor chunk for stable dependencies (changes rarely = long cache)
Long task breaking:
// BEFORE: Blocks main thread 200ms+
function processLargeList(items) {
items.forEach(item => heavyComputation(item));
}
// AFTER: Yields to main thread
async function processLargeList(items) {
for (const item of items) {
heavyComputation(item);
// Yield every 50ms
if (performance.now() - start > 50) {
await scheduler.yield(); // or setTimeout(0)
start = performance.now();
}
}
}
3E: Layout Stability (CLS)
Top CLS causes and fixes:
| Cause | Fix |
|---|---|
| Images without dimensions | Always set width + height |
| Ads/embeds without space | Reserve space with aspect-ratio or min-height |
| Dynamic content injection | Use CSS contain or reserved space |
| Web fonts causing reflow | font-display: optional or swap with size-adjust |
| Late-loading CSS | Inline critical CSS |
Anti-CLS patterns:
/* Reserve space for dynamic content */
.ad-slot { min-height: 250px; }
.embed-container { aspect-ratio: 16/9; }
/* Prevent font swap reflow */
@font-face {
font-family: 'Brand';
src: url('brand.woff2') format('woff2');
font-display: optional; /* No swap = no shift */
size-adjust: 105%; /* Match fallback metrics */
}
/* Contain layout shifts */
.dynamic-widget {
contain: layout;
min-height: 200px;
}
3F: Interaction Optimization (INP)
Event handler rules:
- Keep handlers \x3C 50ms
- Debounce scroll/resize (100-150ms)
- Use
requestAnimationFramefor visual updates - Offload heavy computation to Web Workers
- Use
content-visibility: autofor off-screen content
Input responsiveness:
// BEFORE: Blocks during type
input.addEventListener('input', (e) => {
expensiveFilter(e.target.value); // 100ms+
});
// AFTER: Debounced + visual feedback
input.addEventListener('input', (e) => {
showSpinner(); // Instant visual feedback
debounce(() => expensiveFilter(e.target.value), 150);
});
Phase 4: Resource Loading Strategy
Preload / Prefetch / Preconnect Decision
\x3C!-- Preconnect: Third-party origins you'll need soon -->
\x3Clink rel="preconnect" href="https://fonts.googleapis.com">
\x3Clink rel="preconnect" href="https://cdn.example.com" crossorigin>
\x3C!-- DNS-prefetch: Third-party origins you might need -->
\x3Clink rel="dns-prefetch" href="https://analytics.example.com">
\x3C!-- Preload: Critical resources for THIS page -->
\x3Clink rel="preload" href="critical.css" as="style">
\x3Clink rel="preload" href="hero.webp" as="image">
\x3Clink rel="preload" href="brand.woff2" as="font" type="font/woff2" crossorigin>
\x3C!-- Prefetch: Resources for NEXT page (low priority) -->
\x3Clink rel="prefetch" href="/next-page.js">
\x3C!-- Modulepreload: ES modules -->
\x3Clink rel="modulepreload" href="app.mjs">
Rules:
- Max 3-5 preloads per page (more = competing priorities)
- Always preload: LCP image, critical font, above-fold CSS
- Preconnect to known third-party origins (max 4-6)
- Prefetch only on fast connections
Lazy Loading Strategy
Above fold (viewport): fetchpriority="high", no lazy
Below fold (1-2 screens): loading="lazy", decoding="async"
Way below fold: Intersection Observer, load on demand
Off-screen widgets: content-visibility: auto
Font Loading Optimization
/* Optimal font loading */
@font-face {
font-family: 'Brand';
src: url('brand.woff2') format('woff2');
font-display: swap;
unicode-range: U+0000-00FF; /* Latin only if applicable */
}
Font checklist:
- WOFF2 format only (best compression)
- Subset fonts (Latin, extended only if needed)
- Max 2-3 font families
- Max 4 font files total (regular, bold, italic, bold-italic)
- Preload critical font files
- Consider system font stack for body text
System font stacks:
/* Modern system fonts — zero network cost */
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
/* Monospace */
font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, monospace;
Phase 5: Third-Party Script Management
Impact Assessment
third_party_audit:
- script: "Google Analytics 4"
size_kb: 45
blocks_render: false
loads_more_scripts: true
total_impact_kb: 90
essential: true
mitigation: "gtag async, delay until interaction"
- script: "Intercom chat widget"
size_kb: 200
blocks_render: false
loads_more_scripts: true
total_impact_kb: 450
essential: false
mitigation: "Load on scroll/click, not page load"
Third-party loading strategies:
// Strategy 1: Load on interaction
document.addEventListener('scroll', () => {
loadThirdParty('chat-widget.js');
}, { once: true });
// Strategy 2: Load after page is idle
requestIdleCallback(() => {
loadThirdParty('analytics.js');
});
// Strategy 3: Facade pattern (show placeholder until needed)
chatButton.addEventListener('click', () => {
loadThirdParty('intercom.js').then(() => Intercom('show'));
});
Rules:
- Audit ALL third-party scripts quarterly
- Every script needs a business justification
- If a script loads >100KB, it needs a loading strategy
- Self-host what you can (fonts, analytics alternatives)
- Use
rel="noopener"on all external links
Phase 6: Mobile Performance
Mobile-Specific Optimization
Targets (mobile on 4G):
| Metric | Good | Needs Work | Poor |
|---|---|---|---|
| FCP | \x3C 1.8s | 1.8-3.0s | > 3.0s |
| LCP | \x3C 2.5s | 2.5-4.0s | > 4.0s |
| TBT | \x3C 200ms | 200-600ms | > 600ms |
| CLS | \x3C 0.1 | 0.1-0.25 | > 0.25 |
| INP | \x3C 200ms | 200-500ms | > 500ms |
Mobile-specific checklist:
- Viewport meta tag present
- Touch targets ≥ 48×48px
- No horizontal scroll
- Images responsive (srcset + sizes)
- JS budget \x3C 300KB (compressed) on mobile
- Critical CSS \x3C 14KB (fits in first TCP round trip)
- Avoid complex CSS (heavy animations, large box-shadows)
Phase 7: Performance Budget
Setting Budgets
performance_budget:
metrics:
lcp_ms: 2500
fcp_ms: 1800
tbt_ms: 200
cls: 0.1
inp_ms: 200
resources:
total_kb: 1500
js_kb: 350
css_kb: 80
images_kb: 800
fonts_kb: 100
requests:
total: 60
third_party: 15
lighthouse:
performance: 90
accessibility: 90
best_practices: 90
seo: 90
Budget enforcement rules:
- Any PR that increases JS by >10KB needs justification
- LCP regression > 200ms blocks deploy
- Monthly Lighthouse audit — track trend
- Per-route budgets for SPAs (homepage stricter than admin)
Budget Monitoring Template
# Weekly performance check
date: "YYYY-MM-DD"
url: ""
device: "mobile"
scores:
lighthouse: null
lcp: null
fcp: null
tbt: null
cls: null
trend: "improving | stable | degrading"
regressions: []
actions: []
Phase 8: Performance Scoring Rubric
Rate the site 0-100:
| Dimension | Weight | 0-2 | 3-4 | 5 |
|---|---|---|---|---|
| Core Web Vitals | 25% | All red | Mixed | All green |
| Page weight | 15% | >5MB | 2-5MB | \x3C2MB |
| Caching strategy | 15% | None | Partial | Full with immutable |
| Render path | 15% | Multiple blockers | Some optimized | Clean critical path |
| Image optimization | 10% | Unoptimized | Partially | WebP/AVIF + responsive |
| JavaScript health | 10% | >1MB, no splitting | Some splitting | \x3C350KB, code-split |
| Third-party control | 5% | Unmanaged | Some deferred | All managed + budgeted |
| Mobile experience | 5% | Desktop-only | Responsive | Mobile-first optimized |
Score interpretation:
- 90-100: Elite. Maintain and iterate.
- 70-89: Good. Fix the weakest dimension.
- 50-69: Needs work. Follow Phase 3 playbooks.
- \x3C50: Critical. Start with server + render-blocking fixes.
Phase 9: Common Architectures — Quick Wins
Next.js / React
- Use
next/image(auto WebP, lazy, blur placeholder) - Enable ISR or SSG for static pages
- Use
dynamic()for heavy components - Check bundle with
@next/bundle-analyzer - Middleware for edge caching
WordPress
- Page cache plugin (WP Super Cache, W3 Total Cache)
- Image optimization (ShortPixel, Imagify)
- Disable unused plugins (each adds JS+CSS)
- Use a CDN plugin
- Consider static generation (Simply Static)
SPA (React/Vue/Svelte)
- Route-based code splitting (mandatory)
- SSR or SSG for SEO pages
- Service worker for repeat visits
- Skeleton screens (not spinners)
- Virtual scrolling for long lists
Static Sites
- Already fast — focus on image optimization
- Deploy to CDN edge (Cloudflare Pages, Netlify, Vercel)
- Inline all critical CSS
- Minimal JS (\x3C 50KB)
Phase 10: Advanced Techniques
Service Worker Caching
// Cache-first for static assets
self.addEventListener('fetch', (event) => {
if (event.request.url.match(/\.(css|js|woff2|webp|avif)$/)) {
event.respondWith(
caches.match(event.request).then(cached => cached || fetch(event.request))
);
}
});
Resource Hints for Navigation
// Predictive prefetch on hover
document.querySelectorAll('a').forEach(link => {
link.addEventListener('mouseenter', () => {
const prefetch = document.createElement('link');
prefetch.rel = 'prefetch';
prefetch.href = link.href;
document.head.appendChild(prefetch);
}, { once: true });
});
Performance Monitoring in Production
// Report Core Web Vitals
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Send to analytics
sendToAnalytics({
metric: entry.name,
value: entry.value,
rating: entry.rating, // "good" | "needs-improvement" | "poor"
});
}
}).observe({ type: 'largest-contentful-paint', buffered: true });
Edge Cases
Infinite scroll / pagination:
- Virtual scrolling for >100 items
- Intersection Observer to load batches
content-visibility: autofor off-screen items- Memory management: remove far-off-screen DOM nodes
SPAs with client-side routing:
- Measure soft navigations (not just initial load)
- Report per-route metrics
- Prefetch likely next routes
- Keep route JS \x3C 100KB each
E-commerce product pages:
- Preload first product image
- Lazy load review section, related products
- Defer recommendation engine JS
- Cache product data with stale-while-revalidate
Media-heavy sites:
- Lazy load everything below fold
- Use
\x3Cvideo>not GIF (90% smaller) - Adaptive quality based on connection (Network Information API)
- Progressive JPEG for large photos
Natural Language Commands
- "Audit {url}" → Run full Phase 1 audit
- "Fix LCP on {url}" → Phase 3C playbook
- "What's slowing down {url}?" → Phase 2 diagnosis tree
- "Set performance budget for {project}" → Phase 7 template
- "Score {url}" → Phase 8 rubric
- "Optimize images on {url}" → Phase 3C image checklist
- "Reduce JavaScript on {url}" → Phase 3D JS optimization
- "Fix layout shifts on {url}" → Phase 3E CLS playbook
- "Mobile performance audit for {url}" → Phase 6
- "Third-party script audit for {url}" → Phase 5
- "Weekly performance check for {url}" → Phase 7 monitoring template
- "Compare {url1} vs {url2}" → Side-by-side audit
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install afrexai-web-performance-engine - After installation, invoke the skill by name or use
/afrexai-web-performance-engine - Provide required inputs per the skill's parameter spec and get structured output
What is Web Performance Engine?
Performs comprehensive web performance audits, diagnoses bottlenecks, and provides targeted fixes for server, rendering, hero element, JavaScript, and layout... It is an AI Agent Skill for Claude Code / OpenClaw, with 745 downloads so far.
How do I install Web Performance Engine?
Run "/install afrexai-web-performance-engine" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Web Performance Engine free?
Yes, Web Performance Engine is completely free (open-source). You can download, install and use it at no cost.
Which platforms does Web Performance Engine support?
Web Performance Engine is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Web Performance Engine?
It is built and maintained by 1kalin (@1kalin); the current version is v1.0.0.