Skip to content

feat(web): hero photo slideshow with Ken Burns pan + crossfade#67

Merged
themightychris merged 4 commits into
mainfrom
feat/hero-slideshow
May 19, 2026
Merged

feat(web): hero photo slideshow with Ken Burns pan + crossfade#67
themightychris merged 4 commits into
mainfrom
feat/hero-slideshow

Conversation

@themightychris
Copy link
Copy Markdown
Member

Summary

  • Replaces the never-loaded <video> hero on / with a <HeroSlideshow /> that cycles through a 16-photo set (shuffled per page load): 8 s visible, 1.5 s crossfade, with each layer mounting under a fresh randomized ±2 % pan vector on a 1.05 → 1.10 scale ramp.
  • Respects prefers-reduced-motion: the Ken Burns pan is suppressed while the crossfade continues to run.
  • Adds a reproducible apps/web/scripts/optimize-hero-photos.sh pipeline (ImageMagick → 1920×1280 cover, EXIF stripped, JPG q82 + WebP q80) plus the first 16 optimized assets and a manifest.json index.
  • Updates specs/screens/home.md Section 1 to describe the slideshow as the new background substrate, per the repo's spec-first convention.

Plan: plans/hero-slideshow.md (status: in-progress — will flip to done in the merge commit with validation checked).

Test plan

  • npm run -w apps/web test — 30/30 pass (Home.test.tsx mock now also handles /hero/manifest.json[])
  • npm run type-check clean
  • npm run lint clean
  • npm run -w apps/web builddist/hero/ contains 16 JPG + 16 WebP + manifest.json
  • Browser walkthrough (Chrome): photos cycle every ~8 s, crossfade smooth, transforms confirmed mid-pan (scale ~1.087 with translate), different starting photo across reloads (008 → 015 → 016 observed)
  • Reduced-motion: with matchMedia patched to return matches: true, mid-crossfade inspection shows both layers at ~equal opacity with animationName: "none" — crossfade preserved, pan suppressed
  • Reviewer: spot-check that the dark gradient overlay keeps hero text legible across all 16 photos (especially the lighter ones)

🤖 Generated with Claude Code

themightychris and others added 4 commits May 19, 2026 08:06
Replace the looped <video> hero with a Ken Burns photo slideshow:
shuffled per load, 8s visible / 1.5s crossfade, ±2% random pan per
photo, prefers-reduced-motion honored. Spec update + photo pipeline +
HeroSlideshow component + Home wiring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spec change driving plans/hero-slideshow. Describes <HeroSlideshow />,
timing (8s visible / 1.5s crossfade), pan envelope (±2% on scale
1.05→1.10), and prefers-reduced-motion handling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
optimize-hero-photos.sh: ImageMagick pipeline that resizes/center-crops
to 1920x1280, strips EXIF, emits JPG (q82) + WebP (q80), and writes
manifest.json. Re-running clears and regenerates deterministically.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HeroSlideshow shuffles the manifest on mount and cycles indefinitely
(8s visible, 1.5s crossfade). Each layer mounts with a fresh randomized
pan vector (±2% translate over a 1.05→1.10 scale ramp); the keyframes
live in index.css. Next image is preloaded before the crossfade kicks
off, capped at 3s so the cycle never stalls.

usePrefersReducedMotion follows the matchMedia pattern from useOnline
and disables only the pan animation — crossfades still play.

Home swaps the never-loaded <video> for HeroSlideshow + a dark gradient
overlay for legibility; hero headline + subhead go to white to read
against the photos.

Home.test.tsx mock now returns [] for /hero/manifest.json so the
slideshow renders nothing in JSDOM.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@themightychris themightychris merged commit c5f52ba into main May 19, 2026
1 of 2 checks passed
@themightychris themightychris deleted the feat/hero-slideshow branch May 19, 2026 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant