- Standardize "NAB Show" / "2026 NAB Show" across badges, filter chips,
and headings; never bare "NAB" in user-facing copy.
- /manufacturers/[slug]: normalize show name at render, strip
randomstring suffix on booth, hide booth unless the show is within 90
days, filter single-letter junk out of category display.
- News filter "NAB Show" chip loose-matches any nab-tagged article so
legacy "NAB 2026" tags still surface.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Was: top bar → main nav (sticky) → browse bar
Now: main nav (sticky) → secondary bar → hairline → browse bar
Result: the tagline / language flag / sign-in / join / email subscribe
row no longer eats vertical space above the logo + main nav. It scrolls
off naturally once the user starts reading (main nav stays sticky).
Hairline `h-px bg-[#2a2a2a]` separator below mirrors the divider
pattern used next to "Staff Editorial" elsewhere on the site.
Identical contents — the entire block was relocated, no behavior or
text changed.
Feature 1 — sidebar
Adds a "Companies in this story" panel on every news article that
surfaces every directory company my linker matched in the body. Each
tile shows logo, name, Sponsor / NAB 26 / IBC badges, and a one-sentence
bio. Tiles link to /manufacturers/<slug> and carry data-company-slug so
the global hover card pops on hover too.
Extends company-mentions.ts with linkifyAndExtractMentions() that
returns both the linked HTML and the ordered list of matched slugs in
one pass, so /news/[slug] doesn't re-scan the body for the sidebar.
Feature 2 — unified typeahead
/api/search/suggest now returns { companies, items } — companies are
matched against bb.tracked_companies (directory_visible=true), capped
at 6, ordered by featured → mention_count, then bumped if they're an
active advertiser on broadcastbeat (adv schema lookup).
Header search dropdown renders a "Companies" section at the top with
logo, name, Sponsor badge (active advertiser) or NAB 26 badge, above
the existing "Stories" results. Each company link carries
data-company-slug so the hover card works in the dropdown too.
Adds a neon-green horizontal line across the very top of the site,
spanning from the left vertical rail to the right vertical rail, so
the header reads as a closed bracket instead of two floating lines.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- SVG logo at public/brand/logo.svg with pink-magenta BROADCAST,
cyan BEAT, cyan heartbeat waveform underline, ™ mark, and
"THE PULSE OF PRODUCTION INTELLIGENCE" tagline
- PNG renders at 1x (1200x320), 2x (2400x640), small (600x160)
- Header swapped from /assets/images/logo.png to /brand/logo.svg
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New DualSpeedTicker component (CSS keyframes, GPU-accelerated,
pause on hover, 28px rows, 17s BEAT / 40s FORUM, refresh 5min)
- /api/ticker/beat-news: last 7 days from bb.native_articles
- /api/ticker/forum-posts: latest threads + replies interleaved
- Mounted at the bottom of Header so every page gets it
- Scoped .bb-neon palette on homepage root: section heads +
text-shadow glow, neon-tinted card borders, emerald→cyan button
gradient, cyan hover state on links, subscribe boxes neon-bordered
- CSS-only — no layout changes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- API: require auth on thread+reply POST (401 if !user); lazy-create
forum_user_profile via service-role; author_name = display_name
- UI: surface API errors (kill silent catch); auto-redirect to login
on 401; gate new-thread + reply forms with "Sign in to post" CTA
- /forum/login + /forum/register: forum-themed Supabase Auth pages
with ?next= redirect support
- /forum/profile/edit + /api/forum/profile/me: edit own forum profile
(username, display_name, bio, role, company, location, avatar)
- Header: logout button + sign-in/join links when not authed
- forum/user/[username]: show Edit Profile button when viewing own
Fixes posting bug: RLS rejected anon inserts with cryptic message
that the UI silently swallowed; now blocked with friendly 401 + redirect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PLACEHOLDER: "Search broadcast news…" → "Search articles, gear,
vendors". Drops the weird ellipsis and the "we're a broadcast site
so 'broadcast news' is redundant" feel.
API (/api/search/suggest):
- Match expanded from {title, author_name} to
{title, excerpt, content, author_name} — surfaces hits when the
phrase lives deep in the article body.
- Returns a snippet object {text, matchStart, matchEnd} sliced
from the first hit (HTML-stripped), with ~80 chars of context on
either side and "…" markers when truncated.
- Returns matched_in: 'title' | 'excerpt' | 'content' | 'author' so
the UI can show "match in article body" / "match in byline".
- Returns date + author_name on each result.
UI dropdown (Header.tsx):
- Each suggestion now renders three rows:
1) Title (bold) + category chip
2) Snippet with the matched substring wrapped in <mark>
3) Author byline + date + (if match wasn't in title) a tag
showing where the match occurred
- Vertical stacking with a colored left-border on hover so the
active suggestion is visible.
CSS:
- Stack item layout, snippet with -webkit-line-clamp:2 so long
matches don't overflow.
- <mark> background uses the accent blue at 28% so the highlight
reads against the dark card.
- searchLegacyArticles() default limit: 50 → 5000. /search page
explicitly passes 5000 too. ilike on title/excerpt/author is fast
enough on the 29k-row archive that returning everything is fine.
- New API route /api/search/suggest?q=...&limit=8 returns the top
matching article titles + category + slug, with a 30-second CDN
cache + 60-second stale-while-revalidate.
- The search input in the Browse bar now debounces (150ms) and
fires that API per keystroke once 2+ chars are typed. Matches
appear in a styled dropdown below the input — click to navigate
directly to /news/<slug>, or press Enter to fall through to the
full /search page. "See all results for …" link in the dropdown
footer.
- Keyboard: Escape closes the dropdown; aria-autocomplete + role
listbox/option for accessibility.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Footer bottom: replace the plain "Broadcast Beat" text wordmark
with the same logo image used in the top-left header (so footer
matches header brand mark).
- Move the site-wide search input out of the top sticky row and
into the Browse bar that sits below the 728x90 leaderboard. Top
row is now just logo / reading-list / notification bell.
- Browse bar redesign for personality + alignment:
* 48px tall, dark navy gradient with a 2px accent-blue bottom
border and a horizontal sheen across the top edge
* Search input (pill shape, focus-glow ring) sits flush left
* Menu items (Events ▾, Newsletter, Forum, About ▾) are now
right-aligned via flex justify-between
* Each menu item is uppercase + tracked, hover lights an
accent-blue underline that scales in from the left
* EventsDropdown and AboutDropdown buttons now use the same
.bb-browse-item class — fixes the vertical alignment issue
where they were rendering at the old 60px nav-link-bb height
while the new bar is 48px.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The main sticky top row now holds only the logo, Reading List icon,
notification bell, and search box. The Events dropdown, navLinks
(Newsletter, Forum), and About dropdown were lifted out of the top
row and re-rendered in a new "Browse bar" that sits directly below
the header leaderboard banner.
Visual result:
[ top utility bar (account / admin) ]
[ logo 📑🔔🔍 ]
[ 728x90 leaderboard ]
[ Events ▾ Newsletter Forum About ▾ ] ← new Browse bar
[ LIVE WIRE ···· ]
[ RECENT FORUM POSTS ···· ]
The mobile hamburger drawer is unchanged — it already keeps all the
nav items consolidated for small screens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the four accent-family hex codes site-wide with the teal palette
(keeps the dark theme; only swaps the accent family, not the dark base):
#3b82f6 (accent primary CTA) → #5B7C8D (teal) [839×]
#2563eb (accent-dark / hover) → #4A6473 (darker teal) [44×]
#60a5fa (info link, lighter) → #8FB0C3 (mid teal) [68×]
#1e3a5f (accent-muted bg) → #2F4F5F (navy) [44×]
tailwind.config.js tokens updated to match (accent/accent-dark/accent-muted).
Sweep also covers tailwind.css. 108 files touched. The dark base (#0d0d0d,
#111, #161616, #1a1a1a etc.) is intentionally untouched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Header.tsx: bare linkedin/instagram/facebook URLs → /broadcastbeat handles; remove TwitterXIcon from social bar + import (Footer retains TwitterXIcon per "DO NOT OVERRIDE" marker)
- AboutDropdown.tsx: drop "Press kit" item (the page itself stays at /about/press-kit, just delisted from menu)
- SystemStatusBar.tsx: remove "Index online" pulse-dot and "N wire sources" span (keep articles count + events count + build version)
- /about, /about/team, /about/press-kit: wrap in Header+Footer (previously rendered bare <main>)
- /newsletter/page.tsx (new): redirect to /newsletter/archive — Header was 404'ing on /newsletter
- /rss/route.ts (new): dynamic RSS feed reading from legacy-source news section; replaces 404 at /rss
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Header.tsx: remove "SIGN IN" and "REGISTER" buttons from the top
utility bar and the mobile drawer. Auth for PR firms / writers lives
at distribution.relevantmediaproperties.com now; the local /client-login
and /register routes are no longer the right entry point.
- src/middleware.ts (new): 301-redirect /wp-login, /wp-login.php,
/wp-admin, /wp-admin/*, /login, /client-login, and /register to
https://distribution.relevantmediaproperties.com/login so existing
bookmarks and old WP-era links land somewhere useful instead of 404.
- Newsletter signup form, social icons, country selector all retained.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deploy-1 build failed because NewsPageClient now calls useSearchParams.
- src/app/news/page.tsx: wrap NewsPageClient in <Suspense> so static
generation can bail out to client rendering cleanly.
P0-6 (Featured carousel arrows):
- FeaturedBento: brighten arrow buttons (text-[#ccc] over bg-[#1a1a1a]
with #3a3a3a border; previously near-invisible #666 over the same
background), enlarge to w-8 h-8, hover fills to blue. Wrap the
arrow group with role/aria + Left/Right keyboard nav.
P0-7 (728x90 reposition):
- Header: move the leaderboard block from above the main nav to AFTER
the sticky nav, so it sits between the nav and The Beat ticker.
P0-8 (remove Latest search box):
- ArticleFeed: drop the in-section search input + clear button. The
top-right header search is now the sole search UI. searchQuery state
remains since the active-filter chip code still references it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P0-3 (category page crash):
- Add src/app/error.tsx and src/app/global-error.tsx so any future render
error shows a real ref id instead of the bare client-exception toast.
- NewsPageClient: null-guard every field accessed during search/category/
sort filtering and article render (title, excerpt, author, tags,
category, date, image, alt). The user-visible link
/news?category=live-production now also hydrates filter state from
?category= and ?search= search-params, so the dropdown actually filters.
P0-4 (/articles/[slug] 404s):
- /articles/[slug] and /news/[slug]: on slug miss, redirect("/news")
instead of notFound(). Dead links from the hardcoded NewsTicker /
FeaturedBento / ArticleFeed arrays now land on the news index instead
of dead-ending on 404.
- legacy-source: add searchLegacyArticles() (title/excerpt/author ilike).
P0-5 (header search):
- Header: wire Enter on the desktop and mobile search inputs and make
both search icons clickable buttons. Submits to /search?q=<query>.
- New /search route: server component that runs searchLegacyArticles
and renders results in the same card style as /news.
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>
Top-bar nav changes:
- Authenticated user previously saw two separate links 'My Account' (-> /account)
and 'My Profile' (-> /profile/{userId}). Replaced with a single 'My Profile'
link -> /account.
- Admin block previously rendered 14 inline links (WP Import, Articles, Editorial,
Users, Analytics, Audit Log, Notifications, Newsletter, Forum Seed, Company
Tracker, Show Calendar, AI Console, Banned Terms, Dashboard) which sprawled
horizontally past the available width. 9 of those are now grouped under a
single TOOLS hover dropdown matching the existing NEWS/GEAR/SHOW
COVERAGE/TECHNOLOGY pattern (Tailwind group-hover + group-focus-within for
keyboard accessibility, role=menu / menuitem, aria-haspopup=true).
- Inline admin links retained per spec: WP Import, Articles, Editorial,
Newsletter.
- TOOLS submenu: Users, Analytics, Audit Log, Notifications, Forum Seed,
Company Tracker, Show Calendar, AI Console, Banned Terms.
The whole admin tier (inline + dropdown) remains gated by the existing isAdmin
check, so anonymous and non-admin users see nothing.
Reorganize the navigation:
- navLinks now carries an optional dropdown[] per section. NEWS / GEAR &
REVIEWS / SHOW COVERAGE / TECHNOLOGY get sub-items pulled from the old
flat categoryLinks list.
- Desktop main nav renders each top-level item as a hover-triggered
dropdown (CSS-only via Tailwind group-hover + group-focus-within for
keyboard accessibility). aria-haspopup advertises the popup; the panel
is role=menu with menuitem children.
- Mobile drawer's category list now groups by parent section instead of
showing a flat list.
- Removed the secondary category sub-nav row that previously sat below
the main nav (its content is in the dropdowns now).
- Added a site-wide 728x90 ad slot between the top utility bar and the
main nav (md+ only). Uses <AdSlot zone='homepage-top'> so the existing
ad-rotation pool serves it.
Net: 566 → ~600 lines (markup heavier than what was removed because the
dropdown panels are inline).
Desktop nav (and mobile drawer) now show different account-related
links depending on auth state:
- Anonymous: Sign In (-> /client-login) + Register
- Authenticated: My Account + My Profile
- Admin-tier (administrator/admin/super_admin/editor/support): plus the
full admin block (already gated by isAdmin from earlier commit)
Previously a single 'Sign In / My Account' link pointed at /account
regardless of auth state, which forced anonymous users through a
server-side bounce to the login page. Now Sign In links straight to the
canonical /client-login.
- src/app/home-page/components/LeaderboardAd.tsx: drop the hardcoded
img.rocket.new image (rocket_gen_img_1bebfd3c7) at the top of the
homepage. Replaced with <AdSlot zone='homepage-top' size='728x90' />
to keep the slot for the eventual ad-server wiring while removing the
rocket.new dependency entirely.
- src/components/Header.tsx: re-add the isAdmin gate that was reverted
in 0d51dad. Reads bb.user_profiles.role and only renders the desktop
admin nav block (WP Import, Articles, Editorial, Users, Analytics,
Audit Log, Notifications, Newsletter, Forum Seed, Company Tracker,
Show Calendar, AI Console, Banned Terms, Dashboard) and the mobile WP
Import link when role is in (administrator, admin, super_admin,
editor, support). 'support' is admin-tier per the new RBAC matrix.
Page-level auth checks on each /admin/* route remain authoritative;
this only suppresses menu visibility for non-admin/anonymous.
Header was rendering all admin links unconditionally to every visitor
(including unauthenticated). Add an isAdmin state derived from
user_profiles.role (administrator|admin|super_admin) and wrap both the
desktop admin block and the mobile WP Import link in the guard.
Note: page-level auth checks on each /admin/* route remain authoritative;
this only suppresses menu visibility.