S6 Sample · Lighthouse & a11y

← Samples

Lighthouse 95+ checklist.

The 18 failures we see on most audits and the fix code for each. Performance and accessibility, ranked by frequency in our field work.

Template - copy freely

Target bar

  • Lighthouse 95+ on Performance, Accessibility, Best Practices, SEO (mobile, throttled).
  • WCAG 2.2 AA compliance verified by axe DevTools + manual keyboard walkthrough.
  • Core Web Vitals: LCP < 2.5s, CLS < 0.1, INP < 200ms on the 75th percentile of real-user data.

Top 10 performance failures

P-01: Unoptimized hero images

Single biggest LCP offender. JPEG at original dimensions, no srcset, no priority.

Fix:

<img
  src="/hero-800.webp"
  srcset="/hero-400.webp 400w, /hero-800.webp 800w, /hero-1600.webp 1600w"
  sizes="(max-width: 768px) 100vw, 800px"
  width="800" height="450"
  alt="..."
  fetchpriority="high"
  loading="eager"
/>

P-02: Render-blocking web fonts

Fix: preload the two hero fonts, use font-display: swap, self-host.

<link rel="preload" href="fonts/geist-variable.woff2" as="font" type="font/woff2" crossorigin>

@font-face {
  font-family: "Geist";
  src: url("fonts/geist-variable.woff2") format("woff2-variations");
  font-display: swap;
  font-weight: 100 900;
}

P-03: Uncompressed JavaScript bundle

Fix: enable brotli at the edge. For Vite / Next, confirm build output uses content hashes and is served with long cache TTL. Audit imports - the classic offender is importing entire libraries (lodash, date-fns) when you only use two functions.

P-04: Third-party scripts blocking main thread

Fix: Load analytics, chat widgets, A/B tools with async defer. Use <script type="module"> where possible. For multiple third parties, consider Partytown or server-side alternatives.

P-05: Layout shifts from ads, embeds, lazy images

Fix: reserve space with explicit width and height on all images, iframes, and ad slots. Use CSS aspect-ratio.

P-06: Unminified CSS / JS

Fix: ship production builds. Confirm source maps are not served to end users (robots-excluded or behind auth).

P-07: JavaScript hydration cost on initial load

Fix: for Next / Remix / SvelteKit, use server components or islands architecture. Hydrate only interactive pieces. Avoid hydrating marketing pages as full SPA.

P-08: Long main-thread tasks

Fix: profile with Chrome DevTools Performance panel. Split long tasks with scheduler.yield() or requestIdleCallback. Move CPU-heavy work to Web Workers.

P-09: No HTTP/2 or HTTP/3

Fix: host on a CDN with HTTP/3 (Cloudflare, Fastly, Vercel, Netlify). Self-hosted origins should enable HTTP/2 at minimum.

P-10: Over-eager prefetching

Fix: strip <link rel="prefetch"> that load non-critical resources on mobile. Measure before enabling global prefetch in Next.js.

Top 8 accessibility failures

A-01: Missing or empty alt text

Decorative images need alt=""; content images need descriptive alt; interactive images need functional alt (“close menu”, not “x”).

A-02: Insufficient color contrast

Fix: minimum 4.5:1 for normal text, 3:1 for large. Our --text-muted used to be a contrast fail - increased to #C9CFDB.

A-03: Non-semantic buttons (divs with onClick)

Fix: use <button>. If you must style differently, reset with appearance: none. Keyboard access and screen reader support come free.

A-04: Missing form labels

Fix: every input has a <label for=”id”> or is wrapped in a label. aria-label is fallback, not default.

A-05: Focus indicators invisible

Fix: never set outline: none without a replacement. We use a 2px lime ring on focus-visible.

:focus-visible {
  outline: 2px solid var(--lime);
  outline-offset: 2px;
  border-radius: 0.25rem;
}

A-06: Heading hierarchy skipped

Fix: one H1 per page. H2 for sections, H3 for subsections. No jumping H2 to H4 for styling.

A-07: Accordion / dropdown not keyboard-accessible

Fix: use <details><summary> for simple disclosure. For complex menus, implement proper WAI-ARIA authoring practices (arrow keys, Escape, Home / End).

A-08: Language attribute missing

Fix: <html lang=”en”>. Required by WCAG, breaks screen readers without it.

How we verify

  1. Lighthouse CI on every PR. Fails build on <95.
  2. axe DevTools browser extension for a11y. Zero violations bar.
  3. Manual keyboard walkthrough: tab through every interactive element.
  4. Screen reader smoke test with VoiceOver on every new feature.
  5. Real-user CWV via Search Console + an RUM tool (Vercel Analytics, Sentry, Speedscale).

What we do not check for

This list does not cover: SEO metadata (covered in a separate checklist), PWA-specific audits (most SaaS does not need these), or security headers (separate in our web-dev handbook). Scope your audit intentionally.

Related sampleSpec

SaaS starter spec

What we ship, with this checklist enforced from day one.

Related serviceEngagement

Web development

Marketing sites, SaaS builds, performance retainers.