## Context Chrome Lighthouse runs against `https://santhoshj.com/` (desktop + mobile) report several audits that prevent a 100 score. Inputs: - Desktop report: `C:\Users\simpl\Downloads\santhoshj.com-20260210T182644.json` - Mobile report: `C:\Users\simpl\Downloads\santhoshj.com-20260210T182538.json` Key failing audits (non-exhaustive): - Accessibility: `color-contrast` - SEO: `robots-txt`, `crawlable-anchors` - Best Practices: `inspector-issues` (Content Security Policy) - Performance: `render-blocking-insight`, `image-delivery-insight`, `unminified-css`, `unused-css-rules`, `unused-javascript`, `cache-insight` (plus mobile LCP/TTI pressure) Constraints: - Site is a static Astro build served behind Docker Compose + reverse proxy. - Some assets are third-party (YouTube thumbnails, CloudFront podcast images, Umami script). These can influence some performance/cache audits and must be handled carefully (reduce impact where possible, but avoid breaking content). - Service worker script MUST remain at stable URL `/sw.js` and should not be versioned via query string. ## Goals / Non-Goals **Goals:** - Achieve a 100 Lighthouse rating on the homepage in all categories (Performance, Accessibility, Best Practices, SEO) using the audits provided. - Make contrast compliant (WCAG AA) for secondary text and pill/chip labels. - Ensure SEO hygiene: - `robots.txt` includes a valid (absolute) sitemap URL - interactive elements do not render anchor tags without `href`. - Remove DevTools Issues panel findings related to CSP by implementing an explicit CSP baseline that matches site needs. - Reduce render-blocking requests and improve asset delivery so mobile LCP/TTI is consistently fast. **Non-Goals:** - Redesigning the site's visual identity or typography scale. - Removing all third-party content sources (YouTube thumbnails, podcast cover images) or analytics. - Building a full PWA manifest/offline-first experience (out of scope). ## Decisions 1. **Contrast remediation via token-level CSS adjustments** Rationale: Lighthouse flags specific selectors in card footers and pills. Fixing contrast at the token level (e.g., `--muted`, pill bg/fg) avoids per-component overrides and reduces regressions. Alternatives: - Component-local overrides (harder to maintain, easy to miss). 2. **Robots sitemap MUST be absolute** Rationale: Lighthouse treats `Sitemap: /sitemap-index.xml` as invalid. Robots will be updated to point at the full absolute URL. Alternatives: - Switch to `sitemap.xml` only (not desired; site already emits sitemap-index). 3. **No anchor elements without href in rendered HTML** Rationale: Lighthouse flags the media modal anchors because they exist at load time without `href` (populated later by JS). Fix by using buttons for non-navigational actions, and ensuring any `` is rendered with a valid `href` in initial HTML (or not rendered until it has one). Alternatives: - Keep anchors and set `href="#"` (still crawlable but semantically wrong, and can degrade UX). 4. **CSP baseline implemented at the edge (reverse proxy), compatible with site JS** Rationale: DevTools Issues panel reports CSP issues. Implement a CSP that matches current needs (site inline scripts, Umami, fonts, images, frames) and remove/avoid inline scripts where possible to keep CSP strict. Alternatives: - Avoid CSP entirely (does not resolve audit and leaves security posture ambiguous). 5. **Font delivery: prefer self-hosting to remove render-blocking third-party CSS** Rationale: Lighthouse render-blocking points to Google Fonts stylesheet. Self-hosting WOFF2 and using `@font-face` reduces blocking and improves reliability. Alternatives: - Keep Google Fonts and rely on preload hints (still incurs third-party CSS request; harder to reach 100). 6. **CSS delivery: move global CSS into the build pipeline (minified output)** Rationale: Lighthouse flags unminified/unused CSS. Keeping `global.css` as a raw file in `public/` makes it harder to guarantee minification/unused pruning. Prefer having Astro/Vite handle minification and (where possible) pruning. Alternatives: - Add a bespoke minify step for `public/styles/global.css` (works, but adds build complexity and can drift). 7. **Caching headers: stable URLs get revalidated; fingerprinted assets get long-lived caching** Rationale: Lighthouse cache-lifetime audit penalizes short cache lifetimes on first-party CSS/JS. For assets that are not fingerprinted (e.g., `/sw.js`, possibly `/styles/global.css`), use `no-cache` or revalidation to avoid staleness. For fingerprinted build outputs, use long-lived caching. Alternatives: - Querystring versioning on SW (known pitfall; can break update chain). ## Risks / Trade-offs - **[CSP breaks site behavior]** → Start with Report-Only CSP, verify in production, then enforce. Prefer eliminating inline scripts to avoid `unsafe-inline`. - **[Self-hosting fonts changes appearance slightly]** → Keep the same Manrope font files and weights, verify typography visually. - **[Optimizing images reduces perceived sharpness]** → Use responsive images and appropriate sizes; keep high-DPR support via srcset. - **[Third-party cache lifetimes cannot be controlled]** → Focus on first-party cache headers and reduce critical path reliance on third-party where possible. ## Migration Plan 1. Reproduce Lighthouse findings from a clean Chrome profile (no extensions) for both mobile/desktop. 2. Apply fixes in small slices (contrast, robots/anchors, CSP, fonts, CSS pipeline/minify, image delivery). 3. Deploy behind the reverse proxy with Report-Only CSP first. 4. Re-run Lighthouse on production URL until 100 is reached and stable. 5. Enable enforced CSP after confirming no violations. ## Open Questions - What exact CSP issue is being reported in the DevTools Issues panel (violation message)? Lighthouse only surfaces the issue type without sub-items. - Do we want to keep Google Fonts or commit to self-hosting fonts for maximum Lighthouse consistency? - For cache-lifetime scoring: do we want to introduce fingerprinted CSS output (preferred) or add explicit versioning for `/styles/global.css`?