skills/crazyswami/wp-performance/SKILL.md
WordPress performance optimization - Core Web Vitals, image/video compression, caching, asset optimization, and speed testing. Use when optimizing site speed or diagnosing performance issues.
npx skillsauth add aiskillstore/marketplace wp-performanceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Complete guide for optimizing WordPress site performance, Core Web Vitals, and passing speed tests.
| Metric | Good | Needs Improvement | Poor | |--------|------|-------------------|------| | LCP (Largest Contentful Paint) | ≤2.5s | 2.5-4s | >4s | | INP (Interaction to Next Paint) | ≤200ms | 200-500ms | >500ms | | CLS (Cumulative Layout Shift) | ≤0.1 | 0.1-0.25 | >0.25 |
EWWW Image Optimizer - Best all-around
ShortPixel - Alternative with more formats
Imagify - Simple and effective
// Recommended EWWW settings via wp-config.php or plugin settings
// Enable WebP conversion
define('EWWW_IMAGE_OPTIMIZER_WEBP', true);
// Set maximum dimensions
define('EWWW_IMAGE_OPTIMIZER_MAX_WIDTH', 2560);
define('EWWW_IMAGE_OPTIMIZER_MAX_HEIGHT', 2560);
// Enable lazy loading
define('EWWW_IMAGE_OPTIMIZER_LAZY_LOAD', true);
| Use Case | Format | Max Width | Quality | |----------|--------|-----------|---------| | Hero images | WebP (fallback JPG) | 1920px | 80-85% | | Content images | WebP (fallback JPG) | 1200px | 80% | | Thumbnails | WebP | 600px | 75% | | Icons/logos | SVG or PNG | As needed | Lossless | | Photos with transparency | WebP or PNG | As needed | 85% |
WordPress generates srcset automatically. Ensure proper sizes:
// Add custom image sizes
function theme_custom_image_sizes() {
add_image_size('hero', 1920, 1080, true);
add_image_size('hero-tablet', 1024, 768, true);
add_image_size('hero-mobile', 768, 1024, true);
add_image_size('card', 600, 400, true);
add_image_size('thumb-square', 300, 300, true);
}
add_action('after_setup_theme', 'theme_custom_image_sizes');
// Preload LCP image
function theme_preload_hero() {
if (is_front_page()) {
$hero_url = get_theme_file_uri('/assets/images/hero.webp');
echo '<link rel="preload" as="image" href="' . esc_url($hero_url) . '">';
}
}
add_action('wp_head', 'theme_preload_hero', 1);
Compress before upload
FFmpeg commands
# Compress video for web (H.264, CRF 23 = good quality)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset slow -c:a aac -b:a 128k output.mp4
# Create WebM version (smaller, modern browsers)
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus output.webm
# Extract poster image
ffmpeg -i input.mp4 -ss 00:00:01 -vframes 1 poster.jpg
# Resize to 720p
ffmpeg -i input.mp4 -vf scale=1280:720 -c:v libx264 -crf 23 output-720p.mp4
<video autoplay muted loop playsinline poster="poster.jpg">
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
</video>
For longer videos, use:
// Lazy load video on scroll
const videoObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const video = entry.target;
video.src = video.dataset.src;
video.load();
videoObserver.unobserve(video);
}
});
});
document.querySelectorAll('video[data-src]').forEach(video => {
videoObserver.observe(video);
});
// wp-config.php settings
define('LITESPEED_ON', true);
define('LITESPEED_CACHE_DIR', WP_CONTENT_DIR . '/cache/litespeed/');
Recommended LiteSpeed Settings:
| Setting | Value | |---------|-------| | Enable Cache | On | | Cache Logged-in Users | Off (unless needed) | | Cache Mobile | On | | TTL | 604800 (7 days) | | Browser Cache | On | | Browser Cache TTL | 31557600 (1 year) | | Minify CSS | On | | Minify JS | On | | Combine CSS | Test carefully | | Combine JS | Test carefully | | HTTP/2 Push | CSS, JS | | Lazy Load Images | On | | WebP Replacement | On (if EWWW handles it, disable here) |
// wp-config.php
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_DATABASE', 0);
define('WP_CACHE', true);
// Install Redis Object Cache plugin
// Cache expensive queries
function get_featured_properties() {
$cache_key = 'featured_properties';
$properties = get_transient($cache_key);
if (false === $properties) {
$properties = new WP_Query([
'post_type' => 'property',
'posts_per_page' => 6,
'meta_key' => '_featured',
'meta_value' => '1'
]);
set_transient($cache_key, $properties, HOUR_IN_SECONDS);
}
return $properties;
}
// Clear cache on update
function clear_property_cache($post_id) {
if ('property' === get_post_type($post_id)) {
delete_transient('featured_properties');
}
}
add_action('save_post', 'clear_property_cache');
// Remove unused block styles
function theme_remove_block_styles() {
wp_dequeue_style('wp-block-library');
wp_dequeue_style('wp-block-library-theme');
wp_dequeue_style('global-styles');
}
add_action('wp_enqueue_scripts', 'theme_remove_block_styles', 100);
// Defer non-critical CSS
function theme_defer_styles($html, $handle, $href, $media) {
$defer_handles = ['theme-animations', 'font-awesome'];
if (in_array($handle, $defer_handles)) {
return '<link rel="preload" as="style" href="' . $href . '" onload="this.onload=null;this.rel=\'stylesheet\'">' .
'<noscript><link rel="stylesheet" href="' . $href . '"></noscript>';
}
return $html;
}
add_filter('style_loader_tag', 'theme_defer_styles', 10, 4);
// Defer scripts
function theme_defer_scripts($tag, $handle, $src) {
$defer_scripts = ['theme-main', 'gsap', 'gsap-scrolltrigger'];
if (in_array($handle, $defer_scripts)) {
return str_replace(' src', ' defer src', $tag);
}
return $tag;
}
add_filter('script_loader_tag', 'theme_defer_scripts', 10, 3);
// Remove jQuery if not needed
function theme_remove_jquery() {
if (!is_admin()) {
wp_deregister_script('jquery');
wp_deregister_script('jquery-migrate');
}
}
add_action('wp_enqueue_scripts', 'theme_remove_jquery');
// Preload fonts
function theme_preload_fonts() {
$fonts = [
'/assets/fonts/inter-var.woff2',
'/assets/fonts/playfair-display.woff2'
];
foreach ($fonts as $font) {
echo '<link rel="preload" href="' . get_theme_file_uri($font) . '" as="font" type="font/woff2" crossorigin>';
}
}
add_action('wp_head', 'theme_preload_fonts', 1);
/* Use font-display: swap */
@font-face {
font-family: 'Inter';
src: url('fonts/inter-var.woff2') format('woff2');
font-weight: 100 900;
font-display: swap;
}
-- Delete old revisions (keep last 5)
DELETE FROM wp_posts WHERE post_type = 'revision'
AND ID NOT IN (
SELECT * FROM (
SELECT ID FROM wp_posts WHERE post_type = 'revision'
ORDER BY post_date DESC LIMIT 5
) AS t
);
-- Delete expired transients
DELETE FROM wp_options WHERE option_name LIKE '%_transient_%'
AND option_value < UNIX_TIMESTAMP();
-- Delete orphaned postmeta
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL;
-- Optimize tables
OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options, wp_comments, wp_commentmeta;
# Delete revisions
wp post delete $(wp post list --post_type=revision --format=ids)
# Delete transients
wp transient delete --expired
# Optimize database
wp db optimize
# Search-replace for migrations
wp search-replace 'old-domain.com' 'new-domain.com' --dry-run
// wp-config.php
define('WP_POST_REVISIONS', 5);
// Or disable completely
define('WP_POST_REVISIONS', false);
| Setting | Value | |---------|-------| | SSL/TLS | Full (Strict) | | Always Use HTTPS | On | | Auto Minify | CSS, JS (test first) | | Brotli | On | | Browser Cache TTL | 4 hours to 1 year | | Rocket Loader | Off (conflicts with GSAP) | | Mirage | On (mobile image optimization) | | Polish | Lossy (image optimization) | | WebP | On |
# .htaccess - Cache headers
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
# Enable Gzip/Brotli
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css
AddOutputFilterByType DEFLATE application/javascript application/json
AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>
# Using Lighthouse CLI
npm install -g lighthouse
lighthouse https://example.com --output=html --output-path=./report.html
# Using WebPageTest API
curl "https://www.webpagetest.org/runtest.php?url=https://example.com&f=json&k=YOUR_API_KEY"
#!/usr/bin/env python3
"""
Speed test automation using PageSpeed Insights API
"""
import requests
import json
def test_pagespeed(url, api_key=None):
endpoint = 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed'
params = {
'url': url,
'strategy': 'mobile',
'category': ['performance', 'accessibility', 'best-practices', 'seo']
}
if api_key:
params['key'] = api_key
response = requests.get(endpoint, params=params)
data = response.json()
lighthouse = data['lighthouseResult']
categories = lighthouse['categories']
return {
'performance': int(categories['performance']['score'] * 100),
'accessibility': int(categories['accessibility']['score'] * 100),
'best_practices': int(categories['best-practices']['score'] * 100),
'seo': int(categories['seo']['score'] * 100),
'lcp': lighthouse['audits']['largest-contentful-paint']['displayValue'],
'cls': lighthouse['audits']['cumulative-layout-shift']['displayValue'],
'fcp': lighthouse['audits']['first-contentful-paint']['displayValue']
}
if __name__ == '__main__':
result = test_pagespeed('https://example.com')
print(json.dumps(result, indent=2))
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.