Commit Graph

246 Commits

Author SHA1 Message Date
6e9a163cfd fix(contrast,brand): full audit sweep — white-on-white + cross-component renames
- forum/page.tsx: text-white → navy on TopThreads, Following feed, Discover feed cards, search input, select, category grid, Community Guidelines; greys lightened where applicable for new white surface
- forum/[slug]/page.tsx: same sweep for category page (h1, h2, thread rows, new-thread form, search/sort bar) + hover:bg-[#1e2a3a] → slate-200
- forum/user/[username]/page.tsx: text-[#cccccc]/[#bfbfbf]/[#e0e0e0] + bg-[#222] tag chip + #9ca3af labels → readable on white card
- authors/[slug]/page.tsx: profile contact/facts cards readable
- search/page.tsx: h1 + h2 navy + hover slate
- news/[slug]/NewsArticleDetailClient.tsx: toast color
- news/NewsPageClient.tsx: import cleanExcerpt, strip HTML from listing excerpts
- privacy/terms/page.tsx: h1 + h2 + body greys to readable navy/slate
- error.tsx: page-level text to navy + button border slate
- about/page.tsx: page body text + Stat/Block cards to white surface w/ navy text
- Header.tsx: mobile hamburger + dropdown links → readable navy + slate border
- NotificationCenter.tsx: hover + unread bg flipped to light blue
- AISuggestedArticles.tsx: hover bg → slate-200
- Footer.tsx: link greys to #475569 + #DCE6F2 borders
- AskBBAI.tsx: copy rename 'BB AI' → 'AV Beat AI' (greeting, button, header, aria)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 22:13:42 +00:00
2826f0b566 ui(avbeat): industry-news card hover from near-black #1c1c1c → slate-200 #e2e8f0
src/styles/tailwind.css:195 .article-card:hover background-color was #1c1c1c (near-black, leftover from the dark theme). On the white page that made the card go black on hover and the text disappear into it. Swapped to #e2e8f0 (Tailwind slate-200) so the hover reads as a clean dark-gray distinct from the white surface while keeping the navy article title + slate excerpt fully readable.
2026-06-03 21:40:34 +00:00
a5d4c50186 fix(contrast,brand): secondary-page H1/subtitle white-on-white + rename 'The Crew Lounge' → 'The Integration Room'
CONTRAST (white-on-white on light surfaces, mirrors the prior article-body pass):
  - show-coverage/page.tsx:72  <main> wrapper text-[#e5e7eb] → text-[#0F172A]
  - show-coverage/page.tsx:76  '0 upcoming / 0 past / 0 total' subtitle text-[#9ca3af] → text-[#475569]
  - manufacturers/page.tsx:79  H1 'AV Integration Manufacturers' text-[#e0e0e0] → text-[#0F172A]
  - manufacturers/page.tsx:82  '… manufacturers' subtitle text-[#e0e0e0]/70 → text-[#475569]
  - forum/page.tsx:294 hero H1 text-white → text-[#0F172A]
  - forum/page.tsx:296 hero intro 'Connect with pro AV integrators…' text-[#aab4c4] → text-[#475569]
  - forum/page.tsx:116 'Top Performing Threads' H2 text-white → text-[#0F172A]
  - forum/page.tsx:581 'Browse Categories' H2 text-white → text-[#0F172A]

  Skipped per direct exclusion: forum/page.tsx:591 (per-category card titles).

  Homepage featured grid checked, no edit needed: FeaturedBento 2x2 h3 is already text-[#0F172A] on bg-#FFFFFF; FeaturedBentoFromDb hero is white on a dark image gradient (correct overlay pattern).

BRAND RENAME: forum is renamed everywhere user-visible.
  - forum/page.tsx hero img alt + H1 text 'The Crew Lounge' → 'The Integration Room'
  - forum/layout.tsx — all 7 occurrences (title, description, openGraph, twitter, JSON-LD WebPage name, breadcrumb item)
  - components/crew-lounge/CrewLoungeLogo.tsx — img alt
  - forum/user/[username]/page.tsx — '← Back to The Crew Lounge' link

  Logo SVG filename (/logos/crew-lounge-logo.svg) and React component name (CrewLoungeLogo) intentionally NOT renamed — they're internal asset paths and would cascade through unrelated imports; only user-visible brand strings touched.
2026-06-03 20:14:23 +00:00
93db296380 ui(avbeat): /advertise 'Request Media Kit' CTA → media-kit page on relevantmediaproperties.com
src/app/advertise/page.tsx:55 — hero CTA was pointing at the in-page
anchor '#contact'. Swapped to absolute URL
https://relevantmediaproperties.com/av-beat---media-kit (the AV Beat
media-kit landing). target=_blank + rel=noopener so the article tab
isn't replaced.
2026-06-03 20:07:18 +00:00
43d2bdd106 ui(avbeat): rename Industry News promoted-coverage badge 'Advertiser' → 'HIGHLIGHT'
src/app/home-page/components/ArticleFeed.tsx:597 — the article-card badge
shown when promoted==='client' said '◆ Advertiser' with a title tooltip
'Advertiser coverage: <name>'. Both copies now say 'HIGHLIGHT' / 'Highlight: <name>'.

Visual treatment (diamond glyph, blue token, uppercase tracking) preserved.
The ★ Featured badge for promoted==='premium' is untouched.

Note: BB still has the original 'Advertiser' label; this change is avbeat-only
unless Ryan asks for it mirrored on BB.
2026-06-03 18:15:49 +00:00
334115068b fix(contrast,typography): article header section — match body font (font-serif) + color (#1e293b)
Top-of-article block (above the featured image) used Inter (font-heading)
and inconsistent colors (H1 navy, dek light-grey #999, author name
near-white #e0e0e0). With the body section now in Georgia-style serif
on slate-800 (#1e293b), the header read as a separate visual zone.

Unified both detail routes:

src/app/news/[slug]/NewsArticleDetailClient.tsx
  - H1   :309 font-heading text-[#0F172A] → font-serif text-[#1e293b]
  - Dek  :315 font-body text-[#999]        → font-serif text-[#1e293b]   (this is the lead summary line that was reading as 'white' on the Magewell article — same near-white #999 on white surface)
  - Author name link :332 font-heading text-[#e0e0e0] → font-serif text-[#1e293b]

src/app/articles/[slug]/ArticleDetailClient.tsx
  - H1   :255 same swap as above
  - Author name link :274 same swap as above

Secondary meta (category eyebrow #1D4ED8 blue, read-time/date/author-title #777) intentionally kept at their muted shades — those are subordinate text and read fine on the light surface.
2026-06-03 16:59:12 +00:00
1a6b9d4333 fix(contrast): article-body white-on-white — body/dropcap/h2/h3/blockquote/links to navy + slate, drop prose-invert
Article detail pages (/news/[slug] and /articles/[slug]) inherited a dark-theme
prose color palette via the .bb-article-prose ruleset + Tailwind's
prose-invert utility. With the new light surface, every text element in
the article body rendered near-white on white, while the H1 (fixed in
the prior commit) was already navy. Bringing the body in line:

src/styles/tailwind.css:
  - .bb-article-prose wrapper           #d6d4d0  -> #1e293b !important  (slate-800 for long-form body)
  - .bb-article-prose p:first-of-type   #e8e6e0  -> #1e293b
  - .bb-article-prose first-letter      #f0eee8  -> #0F172A             (drop-cap full navy)
  - .bb-article-prose h2                #f5f3ee  -> #0F172A             (in-body subhead matches the page H1)
  - .bb-article-prose h3                #ece9e2  -> #0F172A
  - .bb-article-prose blockquote        #e8e6e0  -> #1e293b
  - .bb-article-prose a (BASE)          #d6d4d0  -> #1D4ED8             (inline links visibly blue at rest, no longer invisible-until-hover; hover unchanged)

src/app/news/[slug]/NewsArticleDetailClient.tsx
src/app/articles/[slug]/ArticleDetailClient.tsx
  - Drop 'prose-invert' from the wrapper className on both routes so any
    descendant the bb-article-prose rules don't explicitly color (lists,
    strong, em, captions) falls back to Tailwind Typography's default
    light-page slate-700 palette.
2026-06-03 16:49:48 +00:00
ecebc9b3b4 ui(avbeat): shrink featured-story hero excerpt ~50%
FeaturedBentoFromDb.tsx:119 — hero excerpt size ramp halved:
  text-base md:text-lg  (16 / 18 px)
  → text-xs md:text-sm  (12 / 14 px)

Restores a clear size gap below the (already-shrunk) hero headline; the
excerpt was visually competing with the title at the same breakpoint.
2026-06-03 16:27:37 +00:00
d5b54d077b ui(avbeat): rename homepage 'Staff Editorial' section label to 'Featured Editorial' 2026-06-03 16:25:40 +00:00
802fa05631 ui(avbeat): shrink featured-story hero headline ~50%
FeaturedBentoFromDb.tsx:115 — hero h3 size ramp halved:
  text-2xl  md:text-4xl  lg:text-5xl   (24 / 36 / 48 px)
  → text-base md:text-lg  lg:text-2xl  (16 / 18 / 24 px)

leading-tight and the rest of the class string preserved.
2026-06-03 16:18:03 +00:00
aeff448448 revert: typography phase-1 — back out body smoothing block + hero serif tightening
Reverts the two typography-aesthetic edits from f1ecfe3:
  - src/styles/tailwind.css body rule: restore the 'smoothing intentionally NOT overridden' state (drops -webkit-font-smoothing antialiased, -moz-osx-font-smoothing grayscale, text-rendering optimizeLegibility, font-feature-settings, letter-spacing -0.005em).
  - src/components/FeaturedBentoFromDb.tsx:115 cinematic hero headline: restore text-2xl md:text-4xl lg:text-5xl leading-tight (drops text-[40px]/[48px]/[56px], leading-[1.05], tracking-[-0.02em], font-bold).

Intentionally kept from f1ecfe3:
  - NewsArticleDetailClient.tsx + ArticleDetailClient.tsx H1 navy fix (#0F172A) — readability bug, not typography aesthetic.
  - ArticleFeed.tsx Topics chip row removal — separate UI direction.
2026-06-03 16:12:33 +00:00
f1ecfe3176 feat(avbeat): typography phase-1 slice + drop homepage Topics chip row
Typography (approved Phase 1 slice only — utility classes + other reclasses deferred):
- src/styles/tailwind.css body rule: re-add smoothing now that the surface palette is locked in — -webkit-font-smoothing antialiased, -moz-osx-font-smoothing grayscale, text-rendering optimizeLegibility, font-feature-settings 'kern','liga', global letter-spacing -0.005em.
- src/components/FeaturedBentoFromDb.tsx:115 cinematic hero headline: text-2xl md:text-4xl lg:text-5xl leading-tight → text-[40px] md:text-[48px] lg:text-[56px] leading-[1.05] tracking-[-0.02em] font-bold. Confident editorial display per the avinteractive reference.
- src/app/news/[slug]/NewsArticleDetailClient.tsx:309 and src/app/articles/[slug]/ArticleDetailClient.tsx:255 article H1: text-[#f0f0f0] → text-[#0F172A]. Fixes the leftover white-on-white readability bug on article pages.

UI:
- src/app/home-page/components/ArticleFeed.tsx: removed the 'Topics:' chip row from Industry News per current design direction; all stories now show without per-topic filter.
2026-06-03 15:57:40 +00:00
25abc55da1 feat(avbeat): point forum + auth at av schema, swap newsletter chips to AV verticals
Schema wiring — AV Beat was inheriting a 'bb' default schema from the
original fork. Fixed three call sites so the AV Beat app reads/writes
the av schema unless an explicit NEXT_PUBLIC_SUPABASE_SCHEMA override
is set:
  - src/lib/supabase/client.tsx:8 default 'bb' -> 'av'
  - src/lib/supabase/server.tsx:11 default 'bb' -> 'av'
  - src/app/api/auth/lookup-email/route.ts :31 + :42 hardcoded
    .schema('bb') -> .schema('av') so signup lookup hits the
    AV-side subscriber tables, not BB's.

Newsletter signup — homepage chips were the BB taxonomy ('Broadcast',
'Post Production', 'Animation', 'AI & Automation', 'Live Production',
'NAB Show'). Swapped for pro-AV verticals that align with the new
forum categories: Conference Rooms & UC, Digital Signage, Live Events
& Staging, Displays & LED, Audio, AV over IP, InfoComm & ISE.
Default selected flipped from 'Broadcast' to 'Conference Rooms & UC'
so the form doesn't pre-select a non-existent value.
2026-06-03 14:39:12 +00:00
190d374bb1 fix(avbeat): drop antialiased/grayscale font-smoothing on light theme
-webkit-font-smoothing: antialiased and -moz-osx-font-smoothing: grayscale
were set on body and the Tailwind 'antialiased' utility was applied on
<body>. Both pair correctly with the prior dark theme (light text on
dark surfaces), but on the new white surface they render Inter + Lora
thinner and harsher — strokes lose weight, edges read as jagged.

Removed from src/styles/tailwind.css:59-60 (body rule) and from the
<body className="... antialiased"> utility in src/app/layout.tsx:143.
OS default smoothing (subpixel on Windows / older macOS, 'auto' on modern)
gives Inter + Lora their intended weight and roundness.
2026-06-03 13:34:02 +00:00
0e9d3c570e fix(avbeat): noStore() on homepage so hero actually re-renders
dynamic='force-dynamic' + revalidate=0 on the page weren't enough because
FeaturedBentoFromDb -> pickAds() -> fetch in src/lib/ads.ts:98 sets
next:{revalidate:30}. Next.js takes the lowest positive revalidate from
the render tree and opts the whole route into 30-second ISR (visible in
.next/prerender-manifest.json: '/' initialRevalidateSeconds: 30), masking
the page-level force-dynamic directive.

unstable_noStore() called at the top of the HomePage component body
forces an unambiguous, child-tree-overriding opt-out so the Telycam
hero swap (and any future DB-driven hero change) renders on every
request. lib/ads.ts caching is left alone — its revalidate is fine for
ad rotation; we just stop it from poisoning the page-level cache.
2026-06-03 13:29:54 +00:00
1977e077f8 fix(avbeat): 3 homepage bugs — invisible AI sidebar titles, dark tagline on blue header, literal <p> in excerpts
(A) src/components/AISuggestedArticles.tsx :186 + :287 — 'AI Suggested Articles' card titles
    used text-[#e0e0e0] on now-white card surfaces, making the title invisible until
    group-hover flipped it to #1D4ED8. Both occurrences changed to text-[#0F172A].
    (ArticleFeed.tsx:627 and NewsPageClient.tsx:276 were already navy from the
    prior contrast-fix deploy and cover both pagination + infinite-scroll variants.)

(B) src/components/AvBeatLogo.tsx :99 — header tagline 'Inside the Future of Pro AV'
    was rendered in --brand-text-muted (#475569 slate) on a now-blue nav (#1D4ED8),
    near-invisible. Changed to rgba(255,255,255,0.85) so it reads against the blue
    while sitting visually subordinate to the wordmark above it.

(C) src/lib/articles/excerpt.ts — cleanExcerpt now strips HTML tags (<p>, <br>, <em>, etc.)
    and decodes common entities (&nbsp;, &amp;, &lt;, &gt;, &quot;, &#039;, &apos;) at
    render time, then collapses whitespace before the existing trailing-junk/last-word
    logic runs. Display-layer only — stored excerpts are not mutated, matching the
    'fix at the DISPLAY layer' instruction.
2026-06-03 13:20:32 +00:00
a1148e213b fix(contrast): white-on-white text bug — homepage 2x2 titles, .nav-link-bb, /news date inputs
The 2026 rebrand swept surface hexes from dark to light but left near-white text colors baked into components. Three approved fixes:

- FeaturedBento.tsx:255 — 2x2 grid card titles base color #e0e0e0 -> #0F172A (brand-navy). Hover stays #1D4ED8.
- tailwind.css .nav-link-bb — base color #cccccc -> var(--brand-text). Hover unchanged.
- ArticleFeed.tsx :375 + :385 — date input text #888 -> #475569 (brand-text-muted) and dropped [color-scheme:dark] so Chrome stops rendering the dark date-picker chrome on a now-white input.

Findings #2, #3, #6 in the audit were not touched — Ryan flagged them as unverified.
2026-06-03 13:11:57 +00:00
de82125999 feat(avbeat): brand-blue nav, navy card text, tagline rename, hide Industry News dates + Topics row, force-dynamic homepage
- Main nav background → brand-blue #1D4ED8 (sampled from logo emblem).
- Nav link text → white with darker-blue hover bg so contrast holds.
- Article card title fixed from #e0e0e0 to navy #0F172A (was unreadable on the new white surface).
- Industry News card date row removed.
- /news Topics filter chip row removed.
- /news article hover from stark #111 to light-blue #EFF6FF tint matching the brand.
- Tagline 'News & Intelligence for Pro AV, Live Production & Display Tech' renamed to 'Pro AV, Display and Live Production Tech' across Header, RSS feed, newsletter welcome template, root layout title, page title, OG/Twitter tags.
- Homepage page.tsx now has `export const dynamic = 'force-dynamic'` + `revalidate = 0` so the hero (FeaturedBentoFromDb) actually re-renders against the live supabase row (previously the page was being statically prerendered which masked DB-driven hero swaps).
2026-06-03 12:50:55 +00:00
8042024c4a feat(brand): AV BEAT 2026 rebrand — blue/navy/white identity
- New AvBeatLogo inline-SVG component (rounded-square emblem with
  forward-leaning AV monogram + horizontal beam detail) at
  src/components/AvBeatLogo.tsx, three variants (full/wordmark/icon).
- Header.tsx now uses the responsive AV BEAT logo lockup in the
  top-left, links to /, full lockup on desktop (emblem+wordmark+tagline),
  emblem+wordmark on tablet, emblem-only on mobile.
- Removed DualSpeedTicker (the 'RECENT FORUM POSTS' ticker strip);
  the news ticker / glow chrome does not match the new aesthetic and the
  forum row was the explicit removal target.
- Tailwind theme + globals.css now expose the AV BEAT 2026 palette as
  semantic tokens: --brand-blue (#1D4ED8), --brand-blue-bright (#38BDF8),
  --brand-navy (#0F172A), --brand-bg (#F8FAFC), --brand-surface, --brand-border,
  --brand-text, --brand-text-muted. Legacy --color-* aliases re-point to the
  new tokens so any inline-styled component re-themes for free.
- Site-wide hex sweep migrates 2,769 hardcoded color literals across 144
  files from the old dark-broadcast palette to the new tokens (orange
  -> blue, dark-brown -> white surface / navy text, cream -> navy).
- Layout body class flipped from 'bb-neon' to 'bg-brand-bg text-brand-text'
  so the dark glow chrome no longer leaks through the new light theme.
2026-06-03 12:07:18 +00:00
39d2bf9073 AV: recolor email templates (blue palette inside template literals + NAB/IBC marketing phrasing → AV palette + InfoComm/ISE) 2026-06-03 01:53:01 +00:00
4bcd841c53 AV deep sweep: account / news / marketplace placeholders + newsletter default tag + admin overview text + content-status & dashboard adops slug mappings (broadcast-beat → avbeat) 2026-06-03 00:50:46 +00:00
2876ac6ecd AV: precise recolor to spec — warm dark backgrounds (#1c1815/#231d18/#26201a/#15110e) + gold #F0A623 / orange #D85A30 accents + warm text (#FBEFE0/#C9BBA8/#8a7e6e). 138 component files + 36 token swaps. 2026-06-02 23:46:00 +00:00
01c1abf99d AV: remove Studio Hero banner (BB-specific creative not relevant to pro AV) 2026-06-02 23:37:59 +00:00
10ecf723dc AV launch: global color scheme to match logo — gold #ffb800 primary, red #d60701 secondary, warm dark bars (1a1208 / 161310) replacing the inherited BB blue palette. Swapped 21 root tokens + 112 component files. 2026-06-02 23:24:54 +00:00
54117c34d3 AV launch: transparent SVG logo (drop black bg rect) + Header logo 200% bigger (h-12→h-24, 320→640w, 48→96h) + rename Production Industry Manufacturers → AV Integration Manufacturers 2026-06-02 23:22:59 +00:00
8695b338d2 AV round 3: body copy on /about /technology /advertise /marketplace — broadcast→pro AV (about description, technology category descs, advertise H1+sample, marketplace category+meta) 2026-06-02 23:11:39 +00:00
1cb6e3ec01 AV round 2: per-page metadata on /advertise /about /about-team /show-coverage /gear /technology /forum — broadcast→pro AV 2026-06-02 23:05:03 +00:00
3dbe7545d8 AV: catch home-page/page.tsx own metadata + H1 + NewsletterSignup heading + marketplace title (layout-level sweep missed these per-page overrides) 2026-06-02 23:04:18 +00:00
b96c424476 AV launch: comprehensive copy sweep — broadcast/NAB-to-IBC → pro AV/InfoComm-to-ISE across layout/header/forum/marketplace/search/advertise/AI prompts/newsletter/RSS; bump header logo h-7→h-12 + footer h-6→h-9 2026-06-02 22:35:51 +00:00
9bb04fb373 AV launch: rewrite newsletter signup + home description for pro AV industry (InfoComm/ISE), not broadcast (NAB/IBC) 2026-06-02 22:32:57 +00:00
4fd6a88158 AV launch: swap header/footer/schema.org logo to AV Beat SVG + install devDeps so Coolify NODE_ENV=production does not strip autoprefixer 2026-06-02 21:20:36 +00:00
Claude
d43f78b161 av: clone broadcastbeat sources + AV Beat rebrand (Phase 1)
- Replaces the prior Rocket scaffold (saved on pre-bb-clone-rollback branch)
- Domain: broadcastbeat.com -> avbeat.com
- Brand: Broadcast Beat -> AV Beat
- Slug: broadcastbeat -> avbeat (package, identifiers)
- Schema fallback: bb -> av (env var name unchanged)
- Placeholder AV BEAT logo (gold->red gradient) at /assets/logos/av.svg
- All BB/RMP logo references repointed

Outstanding before public DNS swap:
  - Supabase av schema bootstrap (mirror of bb tables)
  - WordPress archive import (avbeat-com -> av.articles)
  - Coolify env vars
  - dev-avbeat.onsethost.com staging deploy + visual review
2026-06-02 15:32:56 +00:00
Ryan Salazar
dd93a74bdf Brand cleanup: swap remaining user-facing BB strings + accent blue → AV orange
Hit pages we didn't get the first pass: rss, gear, show-coverage,
articles/[slug], contributor, manufacturers, login, client-login, terms,
dashboard/show-calendar, and team-page derive helpers (domain + comment).
2026-06-01 15:39:09 +00:00
Ryan Salazar
d67a2bd48d AV Beat rebrand: theme swap (orange #E67E22 / near-black), logo, schema default → avb
- public/assets/images/logo.png + public/brand/logo*.png replaced with the 1320x310 AV Beat logo
- public/assets/logos/avbeat.png added as the canonical source
- tailwind.config.js + src/styles/tailwind.css + src/styles/redesign-tokens.css palette swapped (primary #0F0E0E, secondary #1D1A1A, accent #E67E22 orange, foreground #F0EBE6 warm white)
- Layout / robots / sitemap / home-page / about / contact / press-kit / team / global-error metadata switched to AV Beat (Where AV Meets IT)
- Bulk replaced 'Broadcast Beat'/'BroadcastBeat.com'/'broadcastbeat.com' across user-facing news/forum/marketplace/advertise/search/newsletter pages
- src/lib/supabase/{admin,server,client} now default to schema 'avb' (was 'bb') — overridable via NEXT_PUBLIC_SUPABASE_SCHEMA
- package.json renamed to 'avbeat'
- Single d60701 reference in about/team swapped to E67E22

Design-only replica — no article content migrated.
2026-06-01 15:30:16 +00:00
claude-code
6a48473905 news filter row: add items-center so sort dropdown aligns horizontally with date-range box 2026-06-01 02:03:57 +00:00
Claude Code
6b9251ca9b Modernize /about/team layout + add 9 SD-generated persona portraits + dot-form email helper
Automated persistence of 2026-05-30 session changes. See infrastructure_audit/ for context.
2026-05-30 13:57:13 +00:00
Ryan Salazar
e6095dd803 fix(article): remove duplicate excerpt rendering above the article body
Excerpt was rendered both as a standalone <p> at the top of the article
header AND as the first paragraph of the body content (because PR
submissions paste the lede into both fields). Drop the header copy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 23:55:15 +00:00
Ryan Salazar
445a11a1ee fix(img-proxy): retry transient 5xx, no-store on failure, dynamic route
Bug: a single transient Supabase storage 5xx was being permanently cached
because the route was force-static + force-cache, and the wrapping page
has s-maxage=31536000. Result: real image (still in bucket) showed as
broken on production article pages.

Fix:
- dynamic = force-dynamic, revalidate = 0 (no build-time pinning)
- fetch with no-store + 3-try retry with backoff for 5xx
- failures emit cache-control: no-store so they don't pin

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 19:34:24 +00:00
Ryan Salazar
891f2dd341 auth: forgot/reset password + magic link + Google/MS/LinkedIn buttons
Forgot-password flow at /forum/forgot-password (Supabase resetPassword)
plus /forum/reset-password that catches the recovery session and lets
the user set a new password. 'Forgot password?' link added to the login
form.

SocialAuthButtons component drops onto both login + register pages with
three OAuth providers (Google, Microsoft / Azure, LinkedIn — Apple
skipped per Ryan, can add later when iOS app ships) plus a
no-password magic-link option that works zero-config via Supabase OTP.

Register page now detects already-known subscribers via the new
/api/auth/lookup-email endpoint and sends a magic-link login instead of
forcing them to pick a password. They can set a password later from
their account if they want.

Provider-side setup required: register OAuth apps in Google Cloud
Console / Microsoft Entra / LinkedIn Developers, paste client IDs +
secrets into Supabase dashboard → Authentication → Providers, set
redirect URL to https://broadcastbeat.com/auth/callback. Code is wired
to receive them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 19:22:14 +00:00
Ryan Salazar
0ede78fd35 articles: discussion threads + Related Forum Posts sidebar
ArticleComments component renders under every news + articles detail
page. Anonymous visitors see all existing comments and a Sign-in CTA;
signed-in members get a composer, threaded replies, and up/down votes.
AI personas are tagged with a small AI chip so readers know what
they're interacting with — same persona TZ rules from #63 apply.

Schema extensions on bb.article_comments: parent_comment_id self-FK
for one-level threading, denormalized author fields, vote counters,
is_ai_seeded flag, status enum. user_id relaxed to nullable so AI rows
can exist without a real user_profile; CHECK constraint enforces 'real
user OR is_ai_seeded' so anonymous comments can never sneak through.
forum_votes.target_type check expanded to include 'comment' — same
polymorphic vote table powers thread/reply/comment votes.

New Related Forum Posts sidebar on both /articles/[slug] and
/news/[slug]. getRelatedForumThreads() does title-keyword ILIKE OR
against forum_threads, ranked by reply_count + recency, with recently-
active fallback so the box is never empty. 6 threads per article.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 16:25:19 +00:00
Ryan Salazar
39e9777e0a forum: image attachments on threads + replies, AVIF picture render
New ImageAttachButton drops onto any composer textarea: file picker
upload → /api/upload/image (the universal pipeline) → markdown
![alt](primaryUrl) appended to the body. New thread + reply composers
both gain the button with a 'Auto-optimized, never > 20 MB' caption.

RichBody is the read-path companion: parses body markdown for image
syntax and renders each as a <picture> element with the AVIF source
first (derived from the .webp sibling on our bb-media bucket), then the
WebP, then the original-format fallback img. Prose around images still
runs through LinkifyPlainText so company auto-links still work.

Forum users now have a way to include screenshots, gear photos, NAB
booth shots, etc. in their posts — every image flows through the same
optimization that gives <10% of original byte weight at visually
identical quality.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 16:08:59 +00:00
Ryan Salazar
e24d78cd15 images: unified server-side optimization pipeline + /api/upload/image
Single shared sharp-based pipeline (src/lib/images/optimize.ts) used by
every upload surface going forward — PR submissions, contributor
articles, featured-story admin, forum composer attachments, avatars.
Resizes to 4096px longest side max, emits AVIF + WebP + format-preserving
fallback (JPEG/PNG) + 320px thumbnail, all at perceptual-lossless q=82.

POST /api/upload/image is the universal endpoint: auth-gated (signed-in
Supabase user required), 20MB input cap, MIME-validated, processes the
buffer, uploads every derivative to the bb-media bucket under
<user_id>/<yyyy>/<mm>/<random>.{webp,avif,jpg,png} with year-long
immutable caching. Returns dimensions + all derivative URLs + a
primaryUrl convenience field for simple <img src=> embedding.

Bucket reconfigured: file_size_limit bumped 10MB → 25MB and image/avif
added to allowed_mime_types so AVIF derivatives accept.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 15:43:04 +00:00
Ryan Salazar
976c979e54 forum register/login: rebrand as Broadcast Beat membership
Page heading 'Create a Forum Account' read like a single-purpose signup
buried under the forum, which it no longer is. Refreshed to 'Join
Broadcast Beat' with a left-column benefits rail (forum, newsletter
preferences, saved articles, reply notifications) so the user understands
the same account covers everything we'll add over time. Sign-in page
gets the matching 'Sign in to Broadcast Beat' header with the same dark
gradient + branded copy.

PR-firm distinction is signposted explicitly below the rail: contributors
who want to publish press releases need a separate application — they
shouldn't accidentally sign up as a regular member and expect to post
news. Submission-receive auth gate already enforces this; the message
just makes the path visible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 15:39:02 +00:00
Ryan Salazar
a045d6c558 manufacturer hover popup + smart back link
Content Partners (and any other) company-hover preview previously used
text-ink / bg-ink / brand-primary utilities that aren't defined in our
Tailwind config, so the popup rendered as white background with no text
color (inheriting near-white text from the dark theme parent). Replaced
every undefined utility with concrete dark-theme colors matching the rest
of the site: #111827 panel, #2a3a50 borders, #e8e8e8 body text, #60a5fa
links, real semi-transparent chip badges.

Manufacturer profile back-link now uses BackLink, a client component that
calls router.back() when we have same-origin history — so clicking the
breadcrumb from the homepage Content Partners hover returns the user to
the homepage instead of dumping them at /manufacturers. Falls through to
the directory link for new-tab opens, search-engine entries, and no-JS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 15:34:54 +00:00
Ryan Salazar
cbdf61073f manufacturers: never-empty image cascade for coverage cards
Recent Coverage cards used to show a gray box when an article had no
featured_image (common for older WP imports). Now cascade:
article.featured_image → company.logo_url → /assets/images/article-placeholder.svg
so the card never goes blank.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 15:28:48 +00:00
Ryan Salazar
dd2a8c8da7 bento: lock left column to 600px so 3-up rail bottom aligns w/ 300x600
Previously the rail row could drift past the bottom of the Blackmagic
banner by ~17px depending on title length. Left column is now pinned to
lg:h-[600px] (matching the right column 300x600), and the rail grid uses
flex-1 min-h-0 to absorb the remaining vertical space after the hero
takes its natural aspect-ratio height. Each card switches to a flex
column with the image flex-shrink-0 and the text area flex-1
overflow-hidden so the bottom edge lines up perfectly regardless of
title/category length.

Also tightened the title clamp from line-clamp-3 to line-clamp-2 since
the card height is now bounded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 13:31:46 +00:00
Ryan Salazar
cc76c21c24 homepage bento: hero shrinks into 1fr+300px grid w/ banner at top right
The 21:9 hero used to span full width and the Blackmagic 300x600 sat
next to the 3-up rail beneath it. Layout request: shrink the hero
horizontally (keep aspect ratio — height shrinks proportionally) so the
300x600 lifts up alongside the hero itself, with the 3-up rail still
under the hero in the left column. Same outer grid, just hero+rail now
live together in the left column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 13:21:04 +00:00
Ryan Salazar
6a2d3af336 homepage + NAB: rename 'Coverage Partners' → 'Content Partners' sitewide
SponsorLogoStrip section heading, the section aria-label, the home-page
section comment, and the NAB-2026 page heading + comment all swap to the
new label. No external API or schema references the old phrase, so this
is a pure copy change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 12:16:21 +00:00
Ryan Salazar
bf9e838ea9 news/featured: broaden filter back to category=featured w/ pinned-first sort
featured=true alone only matches 1 row right now, which would leave the
Featured Editorial page nearly empty. Broader category match keeps the
page full while featured DESC still bubbles editorial pins to the top.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 11:07:11 +00:00
Ryan Salazar
07966f556f news/featured: own header + tighter pool, hide AI suggestions sidebar
NewsPageClient now accepts kicker / heading / subtitle / hideAiSuggestions
props so the curated Featured Editorial view can speak with its own voice
instead of borrowing 'Industry News' copy. Featured fetch tightened from
'category ILIKE featured' (63 rows incl. PR-tagged content) to
'featured=true' (editorial pins only), so the page no longer trails into
generic news cards under the lead group.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 11:06:00 +00:00