P0-1 (featured-image fallback path):
- AppImage.tsx: default fallbackSrc changed from /assets/images/no_image.png
to /assets/images/article-placeholder.svg, so any article image that
loads but 404s gets the new clean dark gradient placeholder instead of
the old grey BB_Gray-style box. The smoke-test article
(matrox-video-and-amagi-collaborate-...) had a featured_image URL that
404s on broadcastbeat.com; it now renders the new placeholder.
P0-1 batch (Wayback recovery) is NOT done — see PENDING_ads.md. The
attempted backfill via Wayback found no snapshots for the Matrox smoke
article (it is a 2026 NAB story Wayback never crawled), and the batch
loop tripped a 403 from one of its outbound calls. Proper backfill
needs per-vendor press-kit scraping and a new bb-media storage bucket.
PENDING_ads.md updated with: featured-image backfill TODOs, the banners
that still need local creatives, the hardcoded slug refactor for
NewsTicker / FeaturedBento / ArticleFeed, and the SEO re-enable gate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Banner spec from Ryan:
- 728x90 header (every page): pool is now LiveU only; rotates when more
728x90 entries are added to ads.ts.
- 728x90 below main menu on article pages: removed (was the article-top
AdSlot stub).
- 728x90 footer (every page): replaces the old 300x250 rocket.new
placeholder in Footer.tsx. Rotates from the same ADS_728X90 pool.
- 300x250 sidebar: now renders EVERY entry in ADS_300X250 stacked
vertically, shuffled per page-view. Pool: AJA, Zixi, Telycam, LiveU,
Lectrosonics, Opengear, Studio Hero, Magewell. Adding more entries to
ads.ts auto-grows the stack.
- 300x600 fixed slot: Blackmagic (Adsanity ad-210571), top of sidebar,
never rotated.
Implementation:
- ads.ts: Ad interface now allows either src (local image) or adsanity_id
(iframe). New rotateAll() returns ALL ads of a size shuffled; pickAds
kept for ArticleBody bounded slots.
- AdImage.tsx: dropped the legacy ADSANITY_CAMPAIGN_MAP label fallback —
ads.ts is now the single source of truth, so Telycam (no adsanity_id)
renders its local GIF instead of the iframe.
- SidebarAdStack.tsx: rotateAll(300x250) instead of pickAds with a
count cap. count prop removed; callers updated.
- NewsArticleDetailClient.tsx: removed article-top 728x90 stub.
- Footer.tsx: 728x90 AdImage in place of the 300x250 placeholder.
- LeaderboardAd.tsx: deleted (was unused after the earlier home-page
cleanup).
- PENDING_ads.md: rewritten — Adsanity IDs to verify (Studio Hero,
Blackmagic) and optional local-file upgrades.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove duplicate 728x90 LeaderboardAd below news ticker (per Ryan)
- Footer: remove NAB Official Media Partner badge
- Header: replace AdSlot stub with real AdImage rotation (3 verified 728x90s)
- Header: fix logo path from dead WP URL to local /assets/images/logo.png
- ads.ts: only include ads with verified real images (3x728x90, 2x300x250)
- ads.ts: remove 22 unrecovered ads — see PENDING_ads.md for upload list
- SidebarAdStack: handle null FIXED_300X600 gracefully (Blackmagic not recovered)
- public/legacy/ads/: 5 real ad images committed (Tower, Sony, LiveU 728x90; LiveU PAYG, Telycam 300x250)
- public/assets/images/logo.png: recovered from Wayback Machine
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>