A Lighthouse audit of jwatte.com turned up eight real issues that every existing audit tool I had also missed. This post shows each issue, the fix I applied, and the new tool I built so the next audit actually flags it.
The starting scores
Desktop: Performance 83, Accessibility 97, Best Practices 92, SEO 100.
Mobile: Performance 67, Accessibility 97, Best Practices 92, SEO 100. LCP 13.1s on emulated slow 4G.
Everything else on the site was solid. The drag was a handful of small issues I hadn't caught because I didn't have audit tools for them.
Issue 1: oversized book-cover images
Lighthouse flagged 450 KiB of image waste on desktop, 406 KiB on mobile. The W-2 Trap cover is 1600×2560 pixels; it renders at 188×300 on desktop, 328×525 on mobile. I was shipping a 207 KiB image to render at 150 KB of pixels.
Fix: generated 400w and 800w WebP variants via ImageMagick. Updated <img srcset> to pick the right one. Logo went from 15 KB at 1024×1024 to 684 bytes at 64×64 + 1.3 KB at 128×128.
New tool: Responsive Image Audit — loads each <img>, reads natural dimensions via new Image(), compares against the width attribute, and flags anything shipped at ≥2× the displayed width. It also estimates the waste in KB so you know what you get back for fixing it.
Issue 2: unused preconnect hints
<link rel="preconnect" href="https://fonts.googleapis.com"> and fonts.gstatic.com were in the <head>. The site uses system fonts. Lighthouse: "Unused preconnect."
Fix: deleted both lines. Kept only the GTM preconnect (actually used).
Existing tool: Preconnect + DNS-Prefetch Hygiene Audit already catches this. Now I use it as a pre-commit check before shipping layout changes.
Issue 3: GTM blocking the main thread
Google Tag Manager shipped 154 KiB, 63 KiB unused, and produced five main-thread tasks over 50ms — one of them 977ms. On mobile this ate LCP.
Fix: deferred GTM + Clarity loading behind first user interaction or 3-second idle. Analytics still fire (for every real user who interacts); the script no longer blocks LCP.
Existing tool: Third-Party Script Cost flagged this already. Separate tool: Inline Event Handler Audit catches the related pattern of inline handlers that block strict CSP.
Issue 4: Clarity script blocked by CSP
Best Practices flagged a CSP violation: scripts.clarity.ms was loading but only www.clarity.ms was in the allowlist.
Fix: added scripts.clarity.ms + c.clarity.ms to the CSP script-src / connect-src directives.
New tool: CSP Allowlist Completeness — scans every <script src>, <link rel=stylesheet>, and <iframe src> on the page, extracts the host, and cross-references each against the corresponding CSP directive. Flags every gap. Stops the "analytics stopped firing" silent failure.
Issue 5: contrast fail on the proof strip
"80+", "50", "2,611" in the stat strip used var(--gold) which maps to #d97706 in light mode. On the pale --bg-alt background it fell below WCAG 4.5:1 for normal text.
Fix: added [data-theme="light"] .proof-stat-number { color: var(--gold-accessible); } — the --gold-accessible variable is already defined at #a05d0e (5.2:1 AA).
Existing tool: WCAG Accessibility Audit catches contrast. Also useful: the Mega Analyzer's contrast section.
Issue 6: redundant alt text on book covers
<img alt="The W-2 Trap"> sat right next to <h3>The W-2 Trap</h3>. Screen readers announce the title twice. Lighthouse: "Image elements do not have [alt] attributes that are redundant text."
Fix: changed book-card images to alt="" (empty, marks decorative) + aria-label="Zoom The W-2 Trap book cover" on the zoomable button wrapper. Screen readers announce the heading once, the button action clearly.
New tool: Redundant Alt Text Audit — parses every <img>, reads the text in the nearest 2-3 ancestor elements, and flags alt attributes that duplicate that nearby text.
Issue 7: identical "Buy on Amazon" links
Six book cards, six "Buy on Amazon" buttons, six different ASINs. Lighthouse: "Links with the same destination should have the same description." (Actually it's the inverse — links with same description should have same destination.)
Fix: added aria-label="Buy The W-2 Trap on Amazon" (unique per book) while keeping visible text "Buy on Amazon" (design consistency).
New tool: Identical Link Text Audit — groups every <a href> on the page by visible text (or aria-label if present) and flags any group where the same text points to ≥2 different URLs. WCAG 2.4.4.
Issue 8: non-composited animations
Lighthouse: "57 animated elements found" — most using transition: all with color and box-shadow changes. Every frame = main-thread repaint.
Fix: partial — replaced inline onmouseover style manipulation with transform-based effects where I could. Full refactor pending.
New tool: Non-Composited Animation Audit — parses CSS (inline <style> + external stylesheets), finds every transition and animation declaration, and flags the ones targeting non-GPU properties (color, box-shadow, border, top/left/right/bottom, width/height, margin, padding). Gives a specific rewrite for each.
Bonus fixes that didn't need new tools
- COOP + CORP headers: added
Cross-Origin-Opener-Policy: same-origin-allow-popupsandCross-Origin-Resource-Policy: same-site. Cross-Origin Isolation Audit existed already. - Frame-ancestors + base-uri + object-src 'none' + upgrade-insecure-requests — CSP hardening the CSP Strictness Audit had been recommending.
- Removed 457 KB unreferenced
jw-logo.pngthat was shipping in the deploy but no template referenced it.
Why I built the tools instead of just fixing the issues
One-off fixes fade. A tool that catches the same issue on every future audit pays for itself across the next 50 sites. The 5 tools I built in this round now fire on every Mega SEO Analyzer run. The next regression surfaces automatically.
That's the whole playbook: fix the issue once, then build the check so you never miss it again.
Related reading
- The Mega SEO Analyzer v2 story — the orchestrator that runs these checks automatically
- Why I built the Mega Security Analyzer — the security-layer sibling
- CWV field vs lab gap — why Lighthouse disagrees with CrUX
Fact-check notes and sources
- Lighthouse 13.0.1 scoring formula: web.dev scoring calculator.
- WCAG 4.5:1 / 3:1 contrast thresholds: W3C WCAG 2.1 Success Criterion 1.4.3.
- WCAG 2.4.4 "Link Purpose (In Context)": W3C WCAG 2.1.
- GPU-composited properties (transform, opacity, filter): Chrome Rendering architecture.
- ImageMagick WebP conversion: ImageMagick docs.
This post is informational, not accessibility-consulting, SEO-consulting, or security-consulting advice. Mentions of Lighthouse, Google, Chrome UX Report, Cloudflare, Microsoft Clarity, ImageMagick, and similar products are nominative fair use. No affiliation is implied.