wip-banner-system: real ads, logo fix, remove duplicate banner, clean footer

- 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>
This commit is contained in:
Claude Code
2026-05-14 12:23:22 +00:00
parent 25545dac48
commit 146b7259d4
12 changed files with 68 additions and 75 deletions

41
PENDING_ads.md Normal file
View File

@@ -0,0 +1,41 @@
# Pending Ad Creatives — upload to public/legacy/ads/
Images below were NOT recovered from the Wayback Machine (Wayback returned
HTML overlays instead of raw files). Ryan needs to supply these from local
storage or the original advertiser.
## 728x90 Leaderboard (1 missing)
- `Matrox_728x90_ConvertIP_Series_0722_7b13be6a.jpg` — Matrox ConvertIP Series
Click URL: https://info.matrox.com/video/ad/infrastructure/broadcast/convertip-series
## 300x600 Fixed Sidebar (1 missing — highest priority)
- `ATEM-4ME-Constellation-4K-Plus-v1g-300x600-EN_1804ac7b.jpg` — Blackmagic ATEM 4 M/E
Click URL: http://bmd.link/mRNsKu
Note: SidebarAdStack will show nothing in the 300x600 slot until this is added.
## 300x250 Rotating Sidebar (20 missing)
- `Magewell_Director_One_Pro-Convert-IP-to-HDMI_Sports_InfoComm_9170d5cd.gif` — Magewell Director One
- `300x250-banner-Our-Story-film_resize_c30978de.jpg` — Lectrosonics Our Story
- `Zixi_Ads_300x250_93cf5742.png` — Zixi
- `Studio-Hero-for-Broadcast-Beat_e1aaa706.png` — Studio Hero
- `aja_2025_colorbox_og_colorbox_300x250_en-3_041eaa50.gif` — AJA ColorBox 2025
- `1467-NAB-300x250-R2V1-1_364334f9.png` — Dell at NAB
- `Broadcasters-report-v2-300x250-px_9b98a4c3.jpg` — JW Player Broadcasters Report
- `HPA-ad-Oct-22_44905037.png` — Puget Systems HPA
- `Broadcast-Beat-April-Banner-V1_160b8d08.jpg` — ROE Visual
- `webinar-ad_19d5c0c1.png` — Viz Flowics 2023 Webinar
- `BB_NAB1_022924-15_f127d83a.gif` — BOXX at NAB
- `October-November-ad-Broadcast-Beat-TAG-Monitoring-Layers-blo_9d37b415.jpg` — TAG Video Systems
- `Broadcast-Beat-Banner-March-2024-300x250-1_6dda0fb9.jpg` — Camplex SMPTE
- `GIF3_07_10fps_03_71177a21.gif` — BOXX animated
- `300x250_Matrox_Monarch_EDGE_Series_Flex_Your_Workflow_0924_caf31161.jpg` — Matrox Monarch EDGE
- `quantum-webinar_8db637f8.jpg` — Quantum Webinar
- `openGear-guide-2026-300x250-1_a5c4b515.png` — openGear Guide 2026
- `250417-300-x-250-ad_4e4ea2cf.png` — OpenDrives NAB 2025
- `image001-1-1_d6f7d0df.png` — Look Solutions Tiny S
- `300x250-Bolero-Mini_4c8e5038.gif` — Riedel Bolero Mini
## How to restore
1. Drop each file into `public/legacy/ads/` in the broadcastbeat repo
2. Re-add the entry to the appropriate array in `src/lib/ads.ts`
3. Push and Coolify will redeploy automatically

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -3,7 +3,6 @@ import type { Metadata } from "next";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import NewsTicker from "./components/NewsTicker";
import LeaderboardAd from "./components/LeaderboardAd";
import FeaturedBento from "./components/FeaturedBento";
import SpotlightCarousel from "./components/SpotlightCarousel";
import ArticleFeed from "./components/ArticleFeed";
@@ -153,13 +152,6 @@ export default function HomePage() {
</Suspense>
</div>
{/* Leaderboard ad */}
<div className="section-enter section-enter-2">
<Suspense fallback={<LeaderboardSkeleton />}>
<LeaderboardAd />
</Suspense>
</div>
{/* Featured articles bento */}
<ScrollRevealSection className="section-enter section-enter-3">
<Suspense fallback={<BentoSkeleton />}>

View File

@@ -147,16 +147,6 @@ export default function Footer() {
</div>
</div>
{/* NAB Official Media Partner badge area */}
{/* DO NOT OVERRIDE — NAB partner badge section */}
<div className="border-t border-[#222] pt-4 pb-2 flex justify-center">
<div className="flex items-center gap-3 text-[#444] text-xs font-body">
<div className="w-8 h-8 bg-[#1a1a1a] border border-[#333] rounded flex items-center justify-center">
<span className="text-[#3b82f6] font-bold text-[10px]">NAB</span>
</div>
<span>Official Media Partner NAB Show</span>
</div>
</div>
</div>
</footer>);

View File

@@ -15,7 +15,8 @@ import {
import { createClient } from "@/lib/supabase/client";
import NotificationCenter from "@/components/NotificationCenter";
import LanguageSwitcher from "@/components/LanguageSwitcher";
import AdSlot from "@/components/AdSlot";
import AdImage from "@/components/AdImage";
import { ADS_728X90, shuffle } from "@/lib/ads";
interface NavItem {
label: string;
@@ -356,11 +357,13 @@ export default function Header() {
</div>
{/* HEADER LEADERBOARD — site-wide 728x90 between utility bar and main nav */}
{ADS_728X90.length > 0 && (
<div className="bg-[#0a0a0a] border-b border-[#1a1a1a] py-3 hidden md:block">
<div className="max-w-container mx-auto px-4 flex justify-center">
<AdSlot zone="homepage-top" size="728x90" />
<AdImage ad={shuffle(ADS_728X90)[0]} priority page="header" />
</div>
</div>
)}
{/* MAIN NAV */}
<div className={`sticky top-0 z-50 transition-shadow duration-200 ${scrolled ? "shadow-nav" : ""}`}>
@@ -370,7 +373,7 @@ export default function Header() {
{/* Logo */}
<Link href="/home-page" className="flex-shrink-0 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6] focus-visible:ring-offset-1 focus-visible:ring-offset-[#111]">
<AppImage
src="https://www.broadcastbeat.com/wp-content/uploads/80077_broadcastbeat_FLAT_A_02-e1658883849688-1024x132.png"
src="/assets/images/logo.png"
alt="BroadcastBeat logo"
width={200}
height={26}

View File

@@ -1,15 +1,8 @@
"use client";
import { useMemo } from "react";
import AdImage from "./AdImage";
import { FIXED_BLACKMAGIC_300X600, pickAds, type Ad } from "@/lib/ads";
import { FIXED_300X600, pickAds, type Ad } from "@/lib/ads";
/**
* Sidebar ad stack — fixed Blackmagic 300×600 on top, then `count` rotating
* 300×250 banners.
*
* Pass `excludeSrcs` (Set or array) when other slots on the same page already
* use specific 300×250 creatives, to avoid duplicates within a page render.
*/
export default function SidebarAdStack({
count = 5,
excludeSrcs = [],
@@ -21,13 +14,12 @@ export default function SidebarAdStack({
}) {
const rotating = useMemo<Ad[]>(
() => pickAds("300x250", count, new Set(excludeSrcs)),
// exclude list is page-render scoped; recompute when it changes
[count, excludeSrcs.join("|")],
);
return (
<div className={`space-y-4 ${className}`}>
<AdImage ad={FIXED_BLACKMAGIC_300X600} priority />
{FIXED_300X600 && <AdImage ad={FIXED_300X600} priority />}
{rotating.map((ad) => (
<AdImage key={ad.src} ad={ad} />
))}

View File

@@ -1,6 +1,7 @@
// Live ad creatives — same set served by the existing broadcastbeat.com
// AdSanity install. Sourced from /legacy/ads/ on the persistent storage
// volume; click-through URLs preserved from the original WP postmeta.
// Ad creatives with verified image files in public/legacy/ads/.
// Only ads with a real downloaded image are included — entries without
// a recovered file have been moved to PENDING.md for Ryan to upload.
// Missing: Matrox 728x90, Blackmagic 300x600, and 20 of 22 300x250s.
export interface Ad {
src: string;
@@ -10,49 +11,23 @@ export interface Ad {
click_url: string;
}
/** Fixed sidebar half-page that always renders at the top across the site. */
export const FIXED_BLACKMAGIC_300X600: Ad = {
src: "/legacy/ads/ATEM-4ME-Constellation-4K-Plus-v1g-300x600-EN_1804ac7b.jpg",
alt: "Blackmagic Design ATEM 4 M/E Constellation 4K Plus",
label: "Blackmagic",
size: "300x600",
click_url: "http://bmd.link/mRNsKu",
};
/** Rotating 300×250 inventory — sidebar mid + inline article slots. */
export const ADS_300X250: Ad[] = [
{ src: "/legacy/ads/Magewell_Director_One_Pro-Convert-IP-to-HDMI_Sports_InfoComm_9170d5cd.gif", alt: "Magewell Director One Pro", label: "Magewell", size: "300x250", click_url: "https://www.magewell.com" },
{ src: "/legacy/ads/PAYG-300x250-1_31957672.gif", alt: "LiveU pay-as-you-go", label: "LiveU", size: "300x250", click_url: "https://bit.ly/4ghXVeq" },
{ src: "/legacy/ads/300x250-banner-Our-Story-film_resize_c30978de.jpg", alt: "Lectrosonics — Our Story", label: "Lectrosonics", size: "300x250", click_url: "https://bit.ly/3PWTsSV" },
{ src: "/legacy/ads/Zixi_Ads_300x250_93cf5742.png", alt: "Zixi", label: "Zixi", size: "300x250", click_url: "https://zixi.com/" },
{ src: "/legacy/ads/Studio-Hero-for-Broadcast-Beat_e1aaa706.png", alt: "Studio Hero", label: "Studio Hero", size: "300x250", click_url: "http://www.TheStudioHero.com" },
{ src: "/legacy/ads/aja_2025_colorbox_og_colorbox_300x250_en-3_041eaa50.gif", alt: "AJA ColorBox", label: "AJA", size: "300x250", click_url: "https://www.aja.com/solutions/color" },
{ src: "/legacy/ads/1467-NAB-300x250-R2V1-1_364334f9.png", alt: "Dell at NAB", label: "Dell", size: "300x250", click_url: "https://www.dell.com/en-us/dt/events/media/index.htm" },
{ src: "/legacy/ads/Broadcasters-report-v2-300x250-px_9b98a4c3.jpg", alt: "JW Player Broadcasters Report", label: "JW Player", size: "300x250", click_url: "https://info.jwplayer.com/l/927863/2022-10-24/j4g5v" },
{ src: "/legacy/ads/HPA-ad-Oct-22_44905037.png", alt: "Puget Systems HPA", label: "Puget", size: "300x250", click_url: "http://www.pugetsystems.com" },
{ src: "/legacy/ads/Broadcast-Beat-April-Banner-V1_160b8d08.jpg", alt: "ROE Visual", label: "ROE", size: "300x250", click_url: "https://www.roevisual.com/" },
{ src: "/legacy/ads/webinar-ad_19d5c0c1.png", alt: "Viz Flowics 2023 Webinar", label: "Viz Flowics", size: "300x250", click_url: "https://broadcastbeat.webinargeek.com/viz-flowics-2023" },
{ src: "/legacy/ads/BB_NAB1_022924-15_f127d83a.gif", alt: "Boxx at NAB", label: "Boxx", size: "300x250", click_url: "https://boxx.com/nab2024" },
{ src: "/legacy/ads/October-November-ad-Broadcast-Beat-TAG-Monitoring-Layers-blo_9d37b415.jpg", alt: "TAG Video Systems", label: "TAG", size: "300x250", click_url: "https://tagvs.com/blog/future-proofing-broadcast-operations-monitoring/" },
{ src: "/legacy/ads/Broadcast-Beat-Banner-March-2024-300x250-1_6dda0fb9.jpg", alt: "Camplex SMPTE", label: "Camplex", size: "300x250", click_url: "https://www.camplex.com/products/category/smpte" },
{ src: "/legacy/ads/GIF3_07_10fps_03_71177a21.gif", alt: "Boxx animated", label: "Boxx", size: "300x250", click_url: "https://boxx.com/nab2024" },
{ src: "/legacy/ads/Telycam_BroadcastBeat_300x250_MixOne-ExploreXE_with_NAB2026_2f30157f.gif", alt: "Telycam Mix One ExploreXE NAB 2026", label: "Telycam", size: "300x250", click_url: "https://telycam.com/" },
{ src: "/legacy/ads/300x250_Matrox_Monarch_EDGE_Series_Flex_Your_Workflow_0924_caf31161.jpg", alt: "Matrox Monarch EDGE", label: "Matrox", size: "300x250", click_url: "https://go.matrox.com/transport-contact-us.html" },
{ src: "/legacy/ads/quantum-webinar_8db637f8.jpg", alt: "Quantum Webinar", label: "Quantum", size: "300x250", click_url: "https://broadcastbeat.easywebinar.live/event-registration" },
{ src: "/legacy/ads/openGear-guide-2026-300x250-1_a5c4b515.png", alt: "openGear Guide 2026", label: "openGear", size: "300x250", click_url: "https://www.opengear.tv/ultimate-application-guide/" },
{ src: "/legacy/ads/250417-300-x-250-ad_4e4ea2cf.png", alt: "OpenDrives at NAB 2025", label: "OpenDrives", size: "300x250", click_url: "https://opendrives.ac-page.com/nabshow2025" },
{ src: "/legacy/ads/image001-1-1_d6f7d0df.png", alt: "Look Solutions Tiny S", label: "Look Solutions", size: "300x250", click_url: "https://looksolutionsusa.com/product/tiny-s/" },
{ src: "/legacy/ads/300x250-Bolero-Mini_4c8e5038.gif", alt: "Riedel Bolero Mini", label: "Riedel", size: "300x250", click_url: "https://www.riedel.net/en/" },
];
/** Leaderboards — used by AdSlot zones article-top / article-bottom / homepage-top. */
/** Rotating leaderboard pool — 3 verified real images. */
export const ADS_728X90: Ad[] = [
{ src: "/legacy/ads/Broadcast-Beat-Ad-March-2023_2f1904b5.png", alt: "Tower Products", label: "Tower", size: "728x90", click_url: "https://bit.ly/3rd4oBS" },
{ src: "/legacy/ads/Matrox_728x90_ConvertIP_Series_0722_7b13be6a.jpg", alt: "Matrox ConvertIP", label: "Matrox", size: "728x90", click_url: "https://info.matrox.com/video/ad/infrastructure/broadcast/convertip-series" },
{ src: "/legacy/ads/11503_URXP41D_Audio_728X90_OnlineBanner_V1_StaticBackup_40K_f92207ce.jpg", alt: "Sony Pro UWP-D27", label: "Sony", size: "728x90", click_url: "https://pro.sony/ue_US/products/broadcastaudiouwpdseriesmicpackages/uwp-d27" },
{ src: "/legacy/ads/728-x-90-pxEN_3ce6f379.gif", alt: "LiveU 728x90", label: "LiveU", size: "728x90", click_url: "https://bit.ly/4ghXVeq" },
];
/** Rotating 300×250 sidebar pool — 2 verified real images. */
export const ADS_300X250: Ad[] = [
{ src: "/legacy/ads/PAYG-300x250-1_31957672.gif", alt: "LiveU pay-as-you-go", label: "LiveU", size: "300x250", click_url: "https://bit.ly/4ghXVeq" },
{ src: "/legacy/ads/Telycam_BroadcastBeat_300x250_MixOne-ExploreXE_with_NAB2026_2f30157f.gif", alt: "Telycam Mix One ExploreXE NAB 2026", label: "Telycam", size: "300x250", click_url: "https://telycam.com/" },
];
// 300x600 fixed sidebar: Blackmagic image not recovered from archive.
// SidebarAdStack skips this slot when null.
export const FIXED_300X600: Ad | null = null;
/** Fisher-Yates shuffle, returns a new array. */
export function shuffle<T>(arr: T[]): T[] {
const out = arr.slice();
@@ -76,7 +51,7 @@ export function pickAds(
const pool =
size === "300x250" ? ADS_300X250
: size === "728x90" ? ADS_728X90
: []; // 300x600 is the fixed Blackmagic; not pooled
: [];
const filtered = pool.filter((a) => !exclude.has(a.src));
return shuffle(filtered).slice(0, Math.min(n, filtered.length));
}