Site Performance Optimization — Approach A

Date: 2026-04-08 Branch: master (production) Goal: Improve Lighthouse performance scores (mobile 51 -> ~70-75, desktop 78 -> ~85-90) through template and asset fixes with no pipeline changes.

Current State

Metric Mobile Desktop
Performance 51 78
Accessibility 87 84
Best Practices 69 73
SEO 92 92

Constraints

Changes

1. Defer jQuery and fix dependent scripts

Why: jQuery (91KB) loads synchronously from Google CDN, blocking rendering on every page. This is the single largest render-blocking resource.

How defer works: Deferred scripts execute in source order after HTML parsing completes, but before the DOMContentLoaded event fires. Inline <script> blocks cannot be deferred — they execute immediately when the parser encounters them. This means any inline script that references $ or jQuery will throw ReferenceError if jQuery is deferred.

Changes required:

1a. Add defer to jQuery

1b. Add defer to functions.min.js in base layout

1c. Wrap inline jQuery-dependent scripts in DOMContentLoaded

Since deferred scripts execute before DOMContentLoaded, wrapping inline scripts in document.addEventListener('DOMContentLoaded', function() { ... }) guarantees jQuery is available when the callback runs.

Affected inline scripts:

  1. home.html.haml:78-82 — matchHeight call: javascript // Before: $(function() { $('.equal-testimonials').matchHeight(); }); // After: document.addEventListener('DOMContentLoaded', function() { $('.equal-testimonials').matchHeight(); });

  2. base.html.haml:234-235#{page.javascript} dynamic block. Used by:

    Fix: wrap the template output in DOMContentLoaded: haml -if page.javascript :javascript document.addEventListener('DOMContentLoaded', function() { #{page.javascript} }); The $(document).ready() inside DOMContentLoaded is redundant but harmless — jQuery executes the callback immediately since DOM is already ready.

  3. base.html.haml:255-265 — customers page mixItUp initialization using $(function(){...}): javascript // Wrap in DOMContentLoaded instead of $(function(){}) document.addEventListener('DOMContentLoaded', function() { // ... existing mixItUp code using jQuery });

2. Remove source maps from production deployment

Why: css/maps/styles.css.map (401KB) and css/maps/mmenu.css.map (56KB) are committed to git and deployed to S3. Browsers download them when DevTools are open, but they waste bandwidth and expose source structure.

Approach: Add css/maps/ to .gitignore and remove tracked maps from git. The Gulpfile will continue generating them locally for development. They just won't be committed or deployed.

Files: - .gitignore — add css/maps/ - Run git rm -r --cached css/maps/ to untrack existing files

3. Subset Google Fonts

Why: Currently loading wght@0,300..800;1,300..800 — every weight 300-800 in both regular and italic. The SCSS only uses weights 400, 500, 600, 700, 800 with no italic. This over-fetches font data on every page load.

New URL: https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700;800&display=swap

Files: - _layouts/base.html.haml lines 11-14 — update all four Google Fonts references - _layouts/home.html.haml lines 15-18 — update all four Google Fonts references

4. Add loading="lazy" to below-fold images

Why: Below-fold images without lazy loading compete with critical resources during initial page load, delaying LCP and increasing total blocking time.

Files and images: - _partials/front_page/outcomes.html.haml — 3 customer logo SVGs (tunedglobal.svg, logo-boddle.svg, parakeet-logo-pms-aero.svg) - _partials/front_page/scroller_compliance.html.haml — 2 logos (ISO-27001-certified_col.svg, jasanz.svg) - _partials/footer-home.html.hamlbase2_white.svg, jasanz.svg

Not touched: Header logo (base2.svg) stays eager — it's above fold. Hero image already has fetchpriority="high" and loading="eager".

Out of Scope (Approach B/C)

Verification

After changes, rebuild locally and run Lighthouse on the local _site output: 1. gulp sassTask (recompile CSS if SCSS changed, though no SCSS changes in this spec) 2. Build with Awestruct via Podman 3. Serve _site/ and run Lighthouse in Chrome DevTools 4. Compare mobile and desktop performance scores to baseline