Three issues caused the 'images don't work, video doesn't play' report on
https://water.tuxedocorn.com/tuxedo:
1. (ROOT CAUSE) Next.js standalone build was missing .next/standalone/public/.
The deploy workflow copied .next/static to .next/standalone/.next/static
but never mirrored public/. Without that, the image optimizer returns
400 'url parameter is not allowed' on every local-relative URL — so the
brand logo (and favicon, etc.) went blank. Symptom: HTTP 400 on
/_next/image?url=%2Fbrand-logos%2F64294306-...%2Flogo.png.
Fixed by:
- cp -r public/. .next/standalone/public/ on the running server (live)
- updating .gitea/workflows/deploy.yml to mirror public/ on every deploy
- adding scripts/regression-brand-logos.mjs so this can't regress silently
2. Storm-field and founder-portrait images rendered as 'loading=lazy' and
appeared blank above the fold. Marked priority so they preload.
3. Pre-existing build error: Next.js 16.2 RSC bundler treats
'export type { FieldSession }' re-exports through server-action modules
as runtime exports ('Export FieldSession doesn't exist in target
module'). Removed the re-exports in water-log/auth.ts and field.ts;
field.ts now imports FieldSession directly from @/lib/water-log/session-server.
Verified live (post-fix) on 2026-07-06:
- regression-brand-logos.mjs: HTTP 200 image/png, header+footer logos
render with naturalWidth=160
- diag-home-only.mjs: all 6 images complete=true, natural sizes match
source (storm 1440x1080, founder 604x340, ear 692x476, etc.)
- verify-hero-video.mjs: readyState=4, paused=false, currentTime
advancing 2.86s -> 6.87s over 4s (=30fps; the prior 'video doesn't
play' was likely user perception — the poster+video look near-
identical, and 'net::ERR_ABORTED' on the MP4 is normal Chrome
behavior for parallel byte-range requests)