lighthouse fixes

This commit is contained in:
2026-02-10 22:37:29 -05:00
parent 26a8c97841
commit 07d8787972
785 changed files with 166486 additions and 77 deletions

View File

@@ -0,0 +1,46 @@
## ADDED Requirements
### Requirement: Deterministic Lighthouse configuration
The project MUST define a deterministic Lighthouse run configuration that specifies:
- a fixed list of URLs to audit
- mobile and desktop runs
- theme variants: `light`, `dark`, and `high-contrast`
- a clean run environment (no browser extensions)
- throttling / device emulation settings
The configuration MUST be checked into the repository.
#### Scenario: Lighthouse config is version-controlled
- **WHEN** a developer checks the repository
- **THEN** a Lighthouse configuration file/script exists and is referenced by a documented command
### Requirement: Lighthouse gate enforces perfect scores
The project MUST provide a command that runs Lighthouse for the configured URLs and variants and fails if any category score is below 100:
- Performance
- Accessibility
- Best Practices
- SEO
The command MUST output the reports as build artifacts (HTML and/or JSON) to a deterministic output directory.
#### Scenario: Gate fails on a regression
- **WHEN** Lighthouse runs and any audited variant scores 99 in any category
- **THEN** the command exits non-zero and reports which URL/variant failed
#### Scenario: Gate produces artifacts
- **WHEN** Lighthouse runs successfully
- **THEN** the reports are written to the configured output directory for later inspection
### Requirement: Repeatable scoring rule
The Lighthouse gate MUST define a repeatable scoring rule to reduce run-to-run noise.
At minimum, it MUST document one of the following:
- single-run with fixed throttling and clean environment, or
- multiple runs per variant with a deterministic selection rule (e.g., median)
#### Scenario: Run-to-run method is documented
- **WHEN** a developer runs the gate locally or in CI
- **THEN** the method for selecting/reporting scores is explicitly documented

View File

@@ -0,0 +1,49 @@
## MODIFIED Requirements
### Requirement: Media modal dialog
The site MUST provide a modal dialog that displays embedded media (YouTube video or podcast episode) when a user clicks a video or podcast content card on a listing surface (homepage, `/videos`, `/podcast`).
The modal MUST render the following elements in order:
- A header row with the content title on the left and a close button on the right
- An embedded media player (YouTube iframe for videos; Spotify embed for podcast episodes when the URL is a Spotify URL; otherwise an in-modal audio player when an `audioUrl` is available)
- The full description/summary text (not truncated)
- The publish date and view count (when available)
- A "Subscribe on YouTube" / "Follow on Spotify" CTA and a "View on YouTube" / "Listen on Spotify" CTA
All modal CTAs that represent navigation MUST be implemented as crawlable anchors:
- Each CTA MUST be an `<a>` element with a non-empty `href` attribute.
- The UI MUST NOT render placeholder `<a>` elements without `href` in the initial HTML.
- If CTA destinations are not known until a user selects an item, the CTA UI MUST be rendered as non-anchor elements until the destinations are known.
#### Scenario: User clicks a YouTube video card
- **WHEN** a user clicks a video content card on any listing surface
- **THEN** a modal dialog opens displaying a YouTube iframe embed, the video title, full description, date, view count (if available), and CTAs for "Subscribe on YouTube" and "View on YouTube"
#### Scenario: User clicks a podcast episode card with a Spotify URL
- **WHEN** a user clicks a podcast content card whose URL is a Spotify URL
- **THEN** a modal dialog opens displaying a Spotify episode embed, the episode title, full description, date, and CTAs for "Follow on Spotify" and "Listen on Spotify"
#### Scenario: User clicks a podcast episode card with a non-Spotify URL
- **WHEN** a user clicks a podcast content card whose URL is not a Spotify URL
- **THEN** the modal dialog opens displaying the episode metadata (title, description, date) and either:
- an in-modal audio player when an `audioUrl` is available
- otherwise, a "Listen on Spotify" outbound link
#### Scenario: Modal renders with missing optional fields
- **WHEN** a content item has no view count or no summary
- **THEN** the modal MUST still render cleanly with those fields omitted
#### Scenario: Modal CTAs are crawlable anchors
- **WHEN** the modal is present in the DOM (before any user interaction)
- **THEN** the document contains no `<a>` elements in the modal that are missing `href`
## ADDED Requirements
### Requirement: Embed fallback is a link only when a destination is available
If an embed fallback is presented as a link to an external page, it MUST be an anchor with a valid `href`. If no destination is available, the fallback MUST be hidden or rendered as non-link text.
#### Scenario: Embed fallback does not render a non-crawlable anchor
- **WHEN** the modal is rendered before any item selection
- **THEN** the embed fallback is not rendered as an anchor without `href`

View File

@@ -0,0 +1,29 @@
## ADDED Requirements
### Requirement: Card thumbnails have explicit dimensions
All card thumbnail images MUST include explicit `width` and `height` attributes matching the rendered aspect ratio.
#### Scenario: Thumbnail dimensions are present
- **WHEN** a crawler or browser loads a listing surface with content cards
- **THEN** each card thumbnail `<img>` includes `width` and `height` attributes
### Requirement: Above-the-fold imagery is optimized
The site MUST ensure above-the-fold images are optimized for performance:
- avoid unnecessarily large image payloads for the requested viewport
- prefer modern image formats when first-party controlled
- avoid layout shift caused by late image dimension discovery
#### Scenario: Above-the-fold images do not cause layout shift
- **WHEN** a user loads the home page on a mobile viewport
- **THEN** the hero/top content area does not shift vertically due to image loading
### Requirement: Third-party image variability is controlled for the Lighthouse gate
If a gated page depends on third-party images (e.g., external thumbnails), the gate MUST either:
- ensure those images do not block reaching 100s by design (e.g., not above-the-fold, lazy-loaded), or
- provide a first-party controlled alternative for gated pages.
#### Scenario: Gated pages avoid third-party image volatility
- **WHEN** Lighthouse runs against the gated URL set
- **THEN** third-party image delivery does not prevent meeting the required scores

View File

@@ -0,0 +1,39 @@
## MODIFIED Requirements
### Requirement: Sitemap and robots
The site MUST provide:
- `sitemap-index.xml` enumerating indexable pages (and/or referencing sitemap shards)
- `robots.txt` that allows indexing of indexable pages
The sitemap MUST include the blog surface routes:
- `/blog`
- blog post detail routes
- blog page detail routes
- blog category listing routes
`robots.txt` MUST reference the sitemap using an absolute URL for the production domain.
#### Scenario: Sitemap index is available
- **WHEN** a crawler requests `/sitemap-index.xml`
- **THEN** the server returns an XML sitemap index (or sitemap) listing `/`, `/videos`, `/podcast`, `/about`, and `/blog`
#### Scenario: Blog URLs appear in sitemap
- **WHEN** WordPress content is available in the cache at build time
- **THEN** the generated sitemap includes the blog detail URLs for those items
#### Scenario: Robots references sitemap with absolute URL
- **WHEN** a crawler requests `/robots.txt`
- **THEN** the response contains a `Sitemap:` line with an absolute URL to `/sitemap-index.xml`
## ADDED Requirements
### Requirement: Organization and website structured data
The home page SHOULD include JSON-LD structured data for the site and its owner/organization.
If present, the JSON-LD MUST be valid JSON and MUST use a recognized schema type.
#### Scenario: Home page includes valid JSON-LD
- **WHEN** a crawler requests `/`
- **THEN** the HTML contains a JSON-LD script tag that parses as valid JSON

View File

@@ -0,0 +1,17 @@
## ADDED Requirements
### Requirement: Critical assets do not remain stale after deploy
The service worker and server caching strategy MUST ensure critical shell assets (including the global stylesheet and service worker script) do not remain stale across deploys.
The implementation MUST include at least one cache-busting mechanism for critical assets, such as:
- content-hashed asset filenames, or
- an asset version query suffix that changes per deploy
#### Scenario: New deploy updates critical CSS
- **WHEN** a new deploy is released and a returning user loads the site
- **THEN** the user receives the updated global stylesheet without requiring a manual hard refresh
#### Scenario: Service worker updates predictably
- **WHEN** a new deploy is released
- **THEN** the browser can retrieve the updated service worker script and activate it without being pinned by long-lived caches

View File

@@ -0,0 +1,41 @@
## ADDED Requirements
### Requirement: Theme tokens meet contrast intent
For each supported theme (`dark`, `light`, `high-contrast`), the theme token pairs used for primary text and primary surfaces MUST meet WCAG 2.2 AA contrast intent.
At minimum:
- primary body text on the primary background MUST be high-contrast
- link text on the primary background MUST be distinguishable and meet contrast intent
- secondary labels on the primary background MUST remain readable
#### Scenario: Dark theme text is readable
- **WHEN** `data-theme="dark"` is active
- **THEN** primary text remains readable against primary surfaces without low-contrast combinations
#### Scenario: Dark theme links are readable
- **WHEN** `data-theme="dark"` is active
- **THEN** links in common surfaces are readable against their background
## MODIFIED Requirements
### Requirement: Site themes
The site MUST support three themes:
- `dark`
- `light`
- `high-contrast`
Themes MUST be applied by setting a `data-theme` attribute on the root document element (`<html>`).
#### Scenario: Dark theme active
- **WHEN** `data-theme="dark"` is set on `<html>`
- **THEN** the site's background, text, and component styling reflect the dark palette
#### Scenario: Light theme active
- **WHEN** `data-theme="light"` is set on `<html>`
- **THEN** the site's background, text, and component styling reflect the light palette
#### Scenario: High contrast theme active
- **WHEN** `data-theme="high-contrast"` is set on `<html>`
- **THEN** the site uses a high-contrast palette with a clearly visible focus ring and high-contrast borders

View File

@@ -0,0 +1,21 @@
## ADDED Requirements
### Requirement: Interactive elements use correct semantics
Interactive elements MUST use correct semantic elements:
- Navigation MUST use anchors (`<a>`) with valid `href`.
- Actions that do not navigate MUST use `<button>`.
The site MUST NOT render anchor elements that lack an `href` attribute.
#### Scenario: Modal triggers are buttons
- **WHEN** a content card opens the media modal
- **THEN** the card is a `<button>` element and is keyboard operable
#### Scenario: Navigation CTAs are anchors
- **WHEN** a user sees a CTA that navigates to another page
- **THEN** the CTA is an `<a>` element with a valid `href`
#### Scenario: No non-crawlable anchors exist
- **WHEN** a crawler inspects the rendered HTML
- **THEN** there are no `<a>` elements without `href`