- 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>
Previous state: '/' was 307-redirected to '/home-page', and the
home-page route declared canonical='/home-page'. Net effect on
SEO: Google indexed '/home-page' as the canonical homepage and
treated '/' as a transient redirect (no link equity passed).
Changes:
- next.config.mjs: replace the source:'/' destination:'/home-page'
temporary redirect with source:'/home-page' destination:'/'
permanent (301). Any existing crawler entry for /home-page now
consolidates onto '/'.
- src/app/page.tsx (new): re-exports default + metadata from
./home-page/page so '/' serves the homepage directly. No file
moves required, no relative-import breakage in the home-page
component subtree.
- src/app/home-page/page.tsx: canonical and openGraph.url
'/home-page' → '/'. The page still builds at /home-page but
the 301 above will redirect any hit before render.
- src/app/sitemap.ts: drop the duplicate /home-page entry — Google
shouldn't be told about a URL that just redirects.
- layout.tsx: load Lora (serif) + Inter (sans) via next/font/google,
self-hosted at build time, exposed as --font-serif / --font-sans
CSS variables on <html>. No CDN fetch, no FOIT, no GDPR concern.
- tailwind.css: --font-heading and --font-body now reference the
next/font variables with Georgia / -apple-system fallbacks for the
brief window before the self-hosted face is ready. --font-mono
upgraded to IBM Plex Mono → ui-monospace → Courier New fallback
(DoubleTicker chips already specify IBM Plex Mono directly).
- ArticleFeed: drop the FEATURED filter chip (duplicates the
Staff Editorial section above), add publish date alongside the
byline on every card, lift the homepage feed cap from 200 → 5000.
- api/public/posts: lift MAX_LIMIT to 10000 so client-side
pagination + infinite-scroll see the full archive.
Earlier this evening I bumped the Staff Editorial header to a
font-serif 2xl/3xl bold — too loud, fought with The Latest section
header below it on the same page.
Reverted to the same shape The Latest uses:
<span class="section-label">Staff Editorial</span>
<div class="flex-1 h-px bg-[#2a2a2a]" />
<Link>All featured →</Link>
That's the global .section-label utility (font-body 13px,
font-weight:700, letter-spacing:0.08em, uppercase, color
accent-blue, with a 3px accent border on the left). Now the two
section headers on the homepage are visually consistent.
1. Remove SystemStatusBar from root layout. The "29,220 articles
indexed / 13 events tracked / [v2.0.0]" strip ate vertical space
above the fold without serving readers.
2. /api/newsletter/subscribe was returning 500 "Failed to save
subscription" because:
- The route used the anon-session client and tried to UPSERT on
bb.newsletter_subscribers, but the table's RLS only has an
INSERT policy for the public role. Upsert needs INSERT+UPDATE,
so the second branch failed RLS.
- Switched to createAdminClient (service-role) — bypasses RLS,
which is fine because this is a server-side endpoint with
server-side email validation.
- Welcome email now sends via nodemailer in a non-blocking
background task so a slow SMTP doesn't hold up the response.
Newer HTML template, brand-aligned, with a real CTA back to
/news.
Side work to wire SMTP (done out-of-band):
- Created newsletter@broadcastbeat.com mailbox in Mailcow via
the API (2GB quota, active, no force-pw-update).
- Set SMTP_HOST=mail.onsethost.com, SMTP_PORT=587,
SMTP_USER/PASS/FROM_EMAIL/FROM_NAME in Coolify env so the
welcome email actually fires after the next deploy.
3. FeaturedBentoFromDb section header: "Featured · staff editorial"
(small mono caps) → "Staff Editorial" (font-serif 2xl/3xl, bold,
with a thin metadata line "Selected by our newsroom" beside it
and a 2px bottom rule). Matches the editorial typography on the
article pages.
Renders on every page via root layout. Behavior:
- 5s delay after first paint so it doesn't slam the user.
- Animates from a pill into the full card (bb-modal-pop keyframe);
respects prefers-reduced-motion.
- Heading "Get the latest in broadcast & media", email field,
Subscribe + "Not now" + close (X).
- Subscribe POSTs to the existing /api/newsletter/subscribe route
(native system — newsletter_subscribers table + SMTP welcome
via Mailcow/SMTP2GO). Listmonk wasn't installed anywhere on the
infra; switching to it later is a one-line URL change.
- "Not now" + backdrop click + Escape + X all dismiss for 7 days
via localStorage["bb_newsletter_dismissed"].
- On success → "Check your email" panel + auto-close at 4s;
subscribed flag stored in localStorage so the modal never
re-prompts that visitor.
Styling matches the site's dark-navy + electric-blue palette
(NOT the neon ticker palette). No layout/page shifts — overlay
only.
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.
Manual fire of bb-company-coverage-scan tonight failed because the
8s connect timeout was tripping on llama3.1:70b cold-load when
another model was resident in VRAM on AI_001. Bumped to 30s so
the orchestrator can wait through a model swap.
Also bumped background request timeout 120s → 180s for the same
reason — story generation against the 70B can take >2 min on a
saturated GPU.
Coolify env OLLAMA_ENDPOINT was simultaneously flipped from
AI_001 (10.10.0.66) to AI_002 (10.10.0.67) since AI_002 is less
loaded — AI_001 is doing author enrichment and scrubber work.
The previous version used solid neon-green / neon-cyan blocks for
the "Live Wire" / "On Calendar" labels which read as too aggressive
against the otherwise dark-navy site. Replaced with a real news-wire
look:
- Pulse-dot indicator (animated breathing dot) + small-caps mono
label on the left, separated from the feed by a thin rule.
- Item codes (SONY / MTRX / NAB) become small bordered chips with
subtle neon background tint instead of bare colored text.
- Timestamps are mid-gray monospace; titles are clean Inter at
13px with slight letter-spacing.
- Top + bottom of each bar get a hairline gradient (neon→cyan
on row 1, dimmer cyan-only between rows) instead of a hard
border.
- Items are separated by faint vertical hairlines, padded
consistently.
- Marquee slowed slightly (110s / 170s) so titles are legible.
Same data sources (news + events), same scroll directions, just
better visual integration with the rest of the dark-navy site.
Bug: the index page only fetched threads when user was actively
searching, filtering by category, or sorting non-default. Default
load → setThreads([]) → forum looked empty even though 50+
threads existed in the DB.
Fix: always fetch on mount + filter changes (drop the
isSearchMode gate on the effect), and add a Recent Threads
section in the default view above the Browse Categories list,
showing the 12 most recent threads with author + reply count.
API + DB unchanged.
USER PROFILES (/forum/user/[username]):
- New API at /api/forum/user-by-username/[username] resolves by
username OR display_name (URL-encoded), since forum threads/replies
store author_name = display_name. Returns the persona's profile,
thread history (up to 50), and recent replies (up to 20).
- New page renders the persona card with archetype badge
(Audio Engineer / Colorist / etc.) + expertise level badge
(beginner/intermediate/senior) + role title, company, location,
years_experience, join date, and an expertise-tags chip row.
- Two columns underneath: "Threads started" and "Recent replies"
with proper deep-links into each thread.
- Author names in /forum, /forum/[slug], and /forum/thread/[id] are
now <Link> elements pointing to /forum/user/<displayname>, with
onClick=stopPropagation so the card-level click handler doesn't
also fire.
FAVICON:
- Hand-built neon pulse waveform — emerald→cyan→purple gradient on
dark navy background, designed to read at 16×16 to 256×256.
- Multi-resolution favicon.ico (16/32/48/64) + SVG + PNGs at
16/32/48/64/96/192/256 under /static/favicons/.
- layout.tsx icons block now references all sizes including the
apple-touch sizes (192, 256).
No env / DB changes here — pure deploy.
The schema has upvotes / downvotes / vote_score; API + UI were
querying/reading upvote_count / downvote_count (non-existent
columns). Threads existed in the DB but didn't render.
- /api/forum/threads route.ts:
- 'top-voted' sort: order by vote_score (was upvote_count)
- 'newest' default sort: forum_threads has no 'status' column,
so order pinned-first via is_pinned, then last_reply_at desc
- UI ForumThread interface + components: rename
upvote_count → upvotes, add downvotes + vote_score so the
vote display in the thread cards and the admin moderation
list pulls live data from the existing columns.
After this lands and the deploy completes, the 50 seeded
threads + the 9 ai-seeded new threads + 253 backfilled replies
already in the DB will all render at /forum.