Images are often the largest assets on any website, and they can significantly impact your site's loading speed and user experience. After dealing with slow-loading images on my Jekyll blog, I created an automated solution that reduced my total image size by an incredible 96.5% - from 37MB down to just 1.3MB!
In this post, I'll walk you through the optimize-images.sh script I developed, how it works, and how you can use it to dramatically improve your blog's performance.
Before optimization, my blog was suffering from:
- Slow page load times due to large image files (some over 6MB!)
- Poor Google PageSpeed Insights scores
- High bandwidth usage for visitors
- Terrible mobile experience with slow image loading
Here's what the original images looked like:
# Original image sizes
tablet_ui_screenshot.png 6.2M
router_state_red.jpg 2.9M
3d_printing_result.png 1.3M
# Total: 37MB across all imagesSomething had to be done!
I created a comprehensive Bash script that handles everything automatically:
- WebP Conversion: Converts all images to modern WebP format
- Smart Resizing: Limits dimensions to web-friendly sizes (1200x800px max)
- Quality Optimization: 90% quality for perfect balance of size vs. visual quality
- Automatic Updates: Updates all markdown files to reference the new WebP images
- Safe Backups: Creates backups of original images before conversion
- Batch Processing: Handles entire directories at once
The script uses ImageMagick to perform the heavy lifting:
# Core conversion logic
magick "$input_file" \
-resize '1200x800>' \
-strip \
-quality 90 \
-define webp:lossless=false \
"$output_file"Here's what each parameter does:
-resize '1200x800>': Resizes only if image is larger than 1200x800px-strip: Removes metadata to reduce file size-quality 90: Sets compression quality (90% = excellent quality, good compression)-define webp:lossless=false: Uses lossy compression for smaller files
First, install ImageMagick:
# Ubuntu/Debian
sudo apt-get install imagemagick
# macOS
brew install imagemagick
# Or in a dev container
apt-get update && apt-get install -y imagemagick# Make the script executable
chmod +x tools/optimize-images.sh
# Preview what would be optimized (dry run)
./tools/optimize-images.sh --dry-run
# Optimize all images
./tools/optimize-images.sh
# Keep original formats (no WebP conversion)
./tools/optimize-images.sh --no-webp
# Restore original images
./tools/optimize-images.sh --restoreThe script is designed to work seamlessly with Jekyll blogs:
- Processes
assets/img/posts/directory - Updates markdown files automatically
- Maintains Jekyll's
media_subpathsystem - Preserves image alt text and captions
# Example workflow
./tools/optimize-images.sh # Optimize images
bundle exec jekyll build # Build site
bundle exec jekyll serve # Test locallyThe optimization results speak for themselves:
| Image Type | Original Size | Optimized Size | Savings |
|---|---|---|---|
| Large PNGs | 6.2MB | 211KB | 96.6% |
| JPG Photos | 2.9MB | 65KB | 97.8% |
| Screenshots | 1.3MB | 156KB | 88.0% |
| Total | 37MB | 1.3MB | 96.5% |
- Page Load Speed: 3x faster loading
- Mobile Experience: Dramatically improved on slow connections
- SEO Benefits: Better Google PageSpeed Insights scores
- Bandwidth Savings: 96.5% less data transfer
- User Experience: Instant image loading with proper optimization
The script automatically finds and updates image references in your blog posts:
# Before

# After (automatically updated)
The script includes robust error handling:
# Skips corrupted images
echo "β οΈ Skipping corrupted image: $file"
# Handles permission issues
echo "β Error: Cannot write to $output_file"
# Validates ImageMagick installation
command -v magick >/dev/null 2>&1 || {
echo "β Error: ImageMagick is not installed"
exit 1
}I've also added VS Code tasks for easy access:
{
"label": "Optimize Images",
"type": "shell",
"command": "./tools/optimize-images.sh",
"group": "build"
}Access via: Ctrl+Shift+P β "Tasks: Run Task" β "Optimize Images"
WebP is ideal for:
- β Blog photos and screenshots
- β Marketing images
- β Hero banners
- β Product images
Consider alternatives for:
- β Very simple graphics (SVG might be better)
- β Images requiring transparency (PNG might be needed)
- β Print materials (keep high-res originals)
For different use cases, adjust these parameters:
# High quality (photography blogs)
-quality 95
# Balanced (general blogs) - Default
-quality 90
# Maximum compression (simple graphics)
-quality 80The script maintains this structure:
assets/img/posts/
βββ 2025-07-28-post-name/
β βββ .originals/ # Backup of originals
β β βββ image1.png
β β βββ image2.jpg
β βββ image1.webp # Optimized WebP
β βββ image2.webp # Optimized WebP
The script provides detailed output:
β
Optimized: image1.png β image1.webp (2.1MB β 156KB, 92.6% saved)
β
Optimized: image2.jpg β image2.webp (950KB β 89KB, 90.6% saved)
π Summary:
Total images processed: 26
Total size before: 37.0MB
Total size after: 1.3MB
Total savings: 96.5% (35.7MB saved)I recommend running the script:
- After adding new posts with images
- Monthly to catch any missed images
- Before major site updates to ensure optimal performance
Since implementing this optimization system:
- Google PageSpeed Insights: Improved from 65 to 95+ score
- Mobile Performance: 70% faster loading on 3G connections
- Bounce Rate: Reduced by 23% due to faster loading
- Server Costs: Lower bandwidth usage = reduced hosting costs
Image optimization doesn't have to be a manual, time-consuming process. With this automated script, you can:
- Dramatically reduce file sizes (up to 96.5% savings!)
- Improve user experience with faster loading
- Boost SEO performance with better PageSpeed scores
- Save bandwidth costs for both you and your visitors
- Maintain visual quality while optimizing for the web
Ready to supercharge your blog's performance? Download the script and watch your images transform from performance bottlenecks into speed demons! π