← Back to Blog

Lighthouse ran fixes2.txt against jwatte.com and I built 5 new tools the next hour

Lighthouse ran fixes2.txt against jwatte.com and I built 5 new tools the next hour

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-popups and Cross-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.png that 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

Fact-check notes and sources

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.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026