Performance Optimization Plan for simonprickett.dev
Context
This GitHub Pages site (Jekyll-powered blog with 81+ posts) currently has several performance bottlenecks affecting page load speed:
- Large unminified CSS: 209KB main.css + 14KB theme.css loaded on every page
- No lazy loading: All images load immediately (489 WebP images, 23.2MB total)
- Render-blocking JavaScript: jQuery (85KB) loaded in
<head>blocks HTML parsing - Suboptimal external resources: Font Awesome and Google Fonts loaded synchronously
The goal is to improve page loading speed without any visual changes, focusing on high-impact optimizations compatible with GitHub Pages constraints.
Current estimated load time: ~3-5s on 3G Target load time: <2.5s on 3G Expected improvement: 40-50% faster initial page loads
Implementation Plan
Phase 1: CSS Minification (Highest Impact - ~33% CSS size reduction)
Problem: CSS files are served unminified, wasting ~73KB per page load
Solution: Use Jekyll’s built-in Sass processor to automatically minify CSS
Steps:
- Rename
/assets/css/main.cssto/assets/css/main.scss - Rename
/assets/css/theme.cssto/assets/css/theme.scss - Add YAML front matter to both files (add these 2 lines at the very top):
--- --- - Add Sass compression to
_config.yml:# CSS Minification sass: style: compressed - Update CSS references in
_layouts/default.html:- Line 23:
main.css→main.scss - Line 26:
theme.css→theme.scss
- Line 23:
Expected Results:
- main.css: 209KB → ~140KB (33% smaller)
- theme.css: 14KB → ~10KB (29% smaller)
- Total savings: ~73KB per page
Files to modify:
/assets/css/main.css→ rename tomain.scss/assets/css/theme.css→ rename totheme.scss/_layouts/default.html(lines 23, 26)/_config.yml(add sass config)
Phase 2: Native Image Lazy Loading (High Impact - reduces initial load by 2-5MB)
Problem: All images load immediately, even those below the fold
Solution: Add loading="lazy" attribute to below-the-fold images
Strategy:
- Above-the-fold images: NO lazy loading (hero images, first post)
- Below-the-fold images: Add
loading="lazy"(sidebar, pagination, thumbnails)
Steps:
- Add
loading="lazy"to blog card images in/_includes/main-loop-card.html(line 20):<img class="w-100" src="..." alt="..." loading="lazy"> - Add to post layout images in
/_layouts/post.html:- Line 64: Author avatar
- Lines 86, 91: Previous/next post thumbnails
- Add to pagination cards in
/index.html:- Lines 54, 78, 102 (featured post images)
-
Add to 404 page image
/404.html(line 10) - DO NOT add to hero images (line 29 in
/_layouts/post.html) - they’re above the fold
Expected Results:
- Homepage: Load ~4 images initially instead of ~15-20
- Post pages: Load hero + 1-2 images instead of all sidebar/navigation images
- Savings: 2-5MB reduction on image-heavy pages
Files to modify:
/_includes/main-loop-card.html(line 20)/_layouts/post.html(lines 64, 86, 91)/index.html(lines 54, 78, 102)/404.html(line 10)
Phase 3: Move jQuery to Footer (Eliminates render-blocking JS)
Problem: jQuery loaded in <head> blocks HTML parsing and rendering
Solution: Move jQuery to footer before other scripts that depend on it
Steps:
- Remove jQuery from head in
/_layouts/default.html(delete lines 34-38) - Add jQuery to footer before Popper.js (insert after line 71):
<!-- jQuery must load before Bootstrap --> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
Load order in footer (critical for dependencies):
jQuery → Popper.js → Bootstrap → theme.js → Slick (posts only)
Expected Results:
- Eliminates 85KB render-blocking script
- Faster First Contentful Paint (FCP)
- Faster Largest Contentful Paint (LCP)
Files to modify:
/_layouts/default.html(move lines 35-38 to after line 71)
Phase 4: Font Loading Optimization (Reduces render-blocking)
Problem: Google Fonts loaded synchronously, Font Awesome from external CDN
Solution: Add font-display: swap and resource hints
Steps:
- Add resource hints to
/_layouts/default.html(insert after line 6):<!-- Resource hints for faster DNS/connection --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="dns-prefetch" href="https://code.jquery.com"> <link rel="dns-prefetch" href="https://cdnjs.cloudflare.com"> <link rel="dns-prefetch" href="https://stackpath.bootstrapcdn.com"> - Update Google Fonts URL (line 20) to use
font-display: swap:<link href="https://fonts.googleapis.com/css?family=Lora:400,400i,700&display=swap" rel="stylesheet">
Expected Results:
- 100-300ms faster connection to external resources
- Reduced Flash of Invisible Text (FOIT)
- Faster font rendering
Files to modify:
/_layouts/default.html(add resource hints after line 6, update line 20)
Critical Files Summary
These 5 files contain all the changes needed:
/_layouts/default.html- Main layout template- Move jQuery to footer (lines 35-38 → after 71)
- Update CSS references (lines 23, 26)
- Add resource hints (after line 6)
- Update Google Fonts URL (line 20)
/assets/css/main.css→main.scss- Primary stylesheet- Rename to .scss extension
- Add YAML front matter
/assets/css/theme.css→theme.scss- Custom theme- Rename to .scss extension
- Add YAML front matter
/_includes/main-loop-card.html- Blog post card component- Add
loading="lazy"to image (line 20)
- Add
/_config.yml- Jekyll configuration- Add Sass compression config
Verification Plan
Before Implementation:
Run baseline Lighthouse audit:
npx lighthouse https://simonprickett.dev --output=html --output-path=before-report.html
After Implementation:
1. Build and serve locally:
bundle exec jekyll serve
2. Manual testing checklist:
- Homepage loads correctly
- CSS styles appear identical (no visual changes)
- Images lazy load (check Network tab in DevTools)
- Navbar toggle works on mobile
- Search functionality works
- Slick carousel works on posts
- Font Awesome icons display
- No console errors
- No layout shifts
3. Run Lighthouse again:
npx lighthouse http://localhost:4000 --output=html --output-path=after-report.html
4. Key metrics to verify:
- First Contentful Paint (FCP): Should improve by 30-40%
- Largest Contentful Paint (LCP): Should improve by 20-30%
- Total Blocking Time (TBT): Should decrease significantly
- Performance Score: Target 90+ (from ~60-70)
5. Browser testing:
- Chrome (Desktop/Mobile)
- Firefox (Desktop/Mobile)
- Safari (Desktop/Mobile)
Expected Impact
Performance Improvements:
- Initial page load: 40-50% faster
- CSS payload: 73KB smaller (33% reduction)
- Initial images loaded: 75% fewer on homepage
- Render-blocking JS: Eliminated
Lighthouse Score Improvements (estimated):
- Performance: 60-70 → 90+
- FCP: ~2.5s → ~1.5s
- LCP: ~4.0s → ~2.5s
- TBT: ~500ms → ~200ms
Rollback Plan
All changes are isolated and reversible:
- CSS minification: Rename .scss back to .css, remove sass config
- Lazy loading: Remove
loading="lazy"attributes - jQuery position: Move jQuery back to head
- Font loading: Remove resource hints, restore original Google Fonts URL
All changes tracked in Git for easy reversion with git checkout.
Future Optimization Opportunities
After implementing these foundational optimizations, consider:
- GIF to Video Conversion (134MB → ~15MB): Convert large GIF animations to MP4/WebM format for 85-90% size reduction
- Critical CSS Inlining: Extract and inline above-the-fold CSS for faster FCP
- Service Worker: Add offline caching for instant repeat visits
These advanced optimizations require more effort but provide additional 20-30% performance gains.
Implementation Status
- Phase 1: CSS Minification
- Phase 2: Image Lazy Loading
- Phase 3: Move jQuery to Footer
- Phase 4: Font Loading Optimization
- Verification and Testing Complete