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
This commit is contained in:
Claude
2026-06-02 15:32:56 +00:00
parent dd93a74bdf
commit d43f78b161
137 changed files with 4728 additions and 4541 deletions

View File

@@ -52,8 +52,8 @@ export default function ContactPage() {
<div className="lg:grid lg:grid-cols-[1fr,300px] lg:gap-10">
<main>
<header className="mb-8 border-b border-[#252525] pb-6">
<div className="text-[10px] font-mono uppercase tracking-[0.22em] text-[var(--color-text-info,#E67E22)] mb-2">
AV Beat · Where AV Meets IT
<div className="text-[10px] font-mono uppercase tracking-[0.22em] text-[var(--color-text-info,#60a5fa)] mb-2">
AV Beat
</div>
<h1 className="font-serif text-4xl md:text-5xl font-bold tracking-tight">Contact</h1>
<p className="mt-3 text-[#9ca3af] text-base">

View File

@@ -4,7 +4,7 @@ import SidebarAdStack from "@/components/SidebarAdStack";
export const metadata = {
title: "About AV Beat",
description: "AV Beat is an independent industry publication covering the convergence of pro AV and IT — broadcast, live production, streaming, and post-production technology.",
description: "AV Beat is an independent industry publication covering broadcast, production, and post-production technology.",
};
export default function AboutPage() {
@@ -15,12 +15,12 @@ export default function AboutPage() {
<div className="lg:grid lg:grid-cols-[1fr,300px] lg:gap-10">
<main>
<header className="mb-8 border-b border-[#252525] pb-6">
<div className="text-[10px] font-mono uppercase tracking-[0.22em] text-[var(--color-text-info,#E67E22)] mb-2">
AV Beat · Where AV Meets IT
<div className="text-[10px] font-mono uppercase tracking-[0.22em] text-[var(--color-text-info,#60a5fa)] mb-2">
AV Beat
</div>
<h1 className="font-serif text-4xl md:text-5xl font-bold tracking-tight">About</h1>
<p className="mt-3 text-[#9ca3af] text-base max-w-2xl">
An independent trade publication covering the convergence of pro AV and IT broadcast, live production, streaming, and post-production technology.
An independent trade publication covering broadcast, live production, streaming, and post-production technology.
</p>
</header>
@@ -32,11 +32,11 @@ export default function AboutPage() {
<section className="space-y-6 text-[#d1d5db] text-[15px] leading-relaxed">
<Block title="What we cover">
AV Beat reports on the equipment, services, and people that
move the professional AV and IT-converged video industry
forward. We follow product launches, executive moves,
acquisitions, and the live production / IP / cloud workflows
reshaping how content gets made and delivered.
AV Beat reports on the equipment, services, and people
that move the professional video industry forward. We follow
product launches, executive moves, acquisitions, and the live
production / IP / cloud workflows reshaping how content gets
made and delivered.
</Block>
<Block title="Where we go">
@@ -57,9 +57,9 @@ export default function AboutPage() {
</Block>
<Block title="Get involved">
For editorial pitches: <a className="text-[var(--color-text-info,#E67E22)] hover:underline" href="mailto:editor@avbeat.com">editor@avbeat.com</a>.
{" "}For advertising: <a className="text-[var(--color-text-info,#E67E22)] hover:underline" href="/about/advertise">see the media kit</a>.
{" "}For our team: <a className="text-[var(--color-text-info,#E67E22)] hover:underline" href="/about/team">meet the editorial team</a>.
For editorial pitches: <a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:editor@avbeat.com">editor@avbeat.com</a>.
{" "}For advertising: <a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="/about/advertise">see the media kit</a>.
{" "}For our team: <a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="/about/team">meet the editorial team</a>.
</Block>
</section>
</main>

View File

@@ -13,23 +13,23 @@ export default function PressKitPage() {
<section>
<h2 className="font-mono text-xs uppercase tracking-wider text-[#6b7280] mb-2">Logos</h2>
<ul className="space-y-1">
<li><a className="text-[var(--color-text-info,#E67E22)] hover:underline" href="/assets/images/logo.png" download>AV Beat logo (PNG)</a></li>
<li><a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="/assets/images/logo.png" download>AV Beat logo (PNG)</a></li>
</ul>
</section>
<section>
<h2 className="font-mono text-xs uppercase tracking-wider text-[#6b7280] mb-2">Boilerplate</h2>
<p className="text-[#d1d5db] leading-relaxed">
AV Beat is an independent trade publication covering the convergence
of pro AV and IT broadcast, live production, streaming, and
post-production technology. Founded to bring engineering-rigor
reporting to industry coverage, AV Beat publishes daily on the
equipment, services, and people moving professional video forward.
AV Beat is an independent trade publication covering broadcast,
live production, streaming, and post-production technology. Founded
to bring engineering-rigor reporting to industry coverage, AV Beat
publishes daily on the equipment, services, and people that move
professional video forward.
</p>
</section>
<section>
<h2 className="font-mono text-xs uppercase tracking-wider text-[#6b7280] mb-2">Media contact</h2>
<p>
<a className="text-[var(--color-text-info,#E67E22)] hover:underline" href="mailto:ryan.salazar@relevantmediaproperties.com">ryan.salazar@relevantmediaproperties.com</a>
<a className="text-[var(--color-text-info,#60a5fa)] hover:underline" href="mailto:ryan.salazar@relevantmediaproperties.com">ryan.salazar@relevantmediaproperties.com</a>
</p>
</section>
</div>

View File

@@ -9,7 +9,7 @@ export const revalidate = 600;
export const metadata = {
title: "Our team — AV Beat",
description: "Meet the AV Beat team — editorial staff plus accounts and support, covering the convergence of pro AV and IT.",
description: "Meet the AV Beat team — editorial staff plus accounts and support, covering broadcast, streaming, and post-production.",
};
interface Persona {
@@ -63,7 +63,7 @@ export default async function TeamPage() {
.from("personas")
.select("id, display_name, role, email, phone, extension, avatar_url")
.eq("active", true)
.in("id", ["chloe", "jeff", "riley"]);
.in("id", ["chloe", "jeff", "riley", "brian", "avery"]);
const ops = (opsData || []) as OpsPersona[];
const displayBeat = (p: Persona) =>
@@ -98,10 +98,10 @@ export default async function TeamPage() {
<main>
{/* Hero */}
<header className="relative overflow-hidden rounded-xl mb-10 border border-[#1a1f2a] bg-gradient-to-br from-[#0d1118] via-[#0b0f17] to-[#0d1118]">
<div className="absolute inset-0 opacity-[0.04] bg-[radial-gradient(ellipse_at_top_right,#E67E22,transparent_60%)]" aria-hidden />
<div className="absolute inset-0 opacity-[0.04] bg-[radial-gradient(ellipse_at_top_right,#d60701,transparent_60%)]" aria-hidden />
<div className="relative px-6 py-10 sm:px-10 sm:py-14">
<div className="inline-flex items-center gap-2 text-[10px] font-mono uppercase tracking-[0.22em] text-[#F0B07A] mb-3">
<span className="w-6 h-px bg-[#E67E22]" />
<div className="inline-flex items-center gap-2 text-[10px] font-mono uppercase tracking-[0.22em] text-[#ff5a55] mb-3">
<span className="w-6 h-px bg-[#d60701]" />
AV Beat &middot; editorial
</div>
<h1 className="font-serif text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight leading-tight">
@@ -129,10 +129,10 @@ export default async function TeamPage() {
return (
<li
key={p.slug}
className="group relative rounded-xl border border-[#1a1f2a] bg-[#0b0f17] p-5 hover:border-[#E67E22]/50 hover:shadow-[0_0_0_1px_rgba(230,126,34,0.15)] transition-all"
className="group relative rounded-xl border border-[#1a1f2a] bg-[#0b0f17] p-5 hover:border-[#d60701]/50 hover:shadow-[0_0_0_1px_rgba(214,7,1,0.15)] transition-all"
>
{/* Top accent */}
<div className="absolute top-0 left-5 right-5 h-px bg-gradient-to-r from-transparent via-[#E67E22]/40 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" aria-hidden />
<div className="absolute top-0 left-5 right-5 h-px bg-gradient-to-r from-transparent via-[#d60701]/40 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" aria-hidden />
<div className="flex items-start gap-4">
{p.avatar_url ? (
@@ -142,7 +142,7 @@ export default async function TeamPage() {
alt={p.name}
width={96}
height={96}
className="w-24 h-24 rounded-full border-2 border-[#1a1f2a] group-hover:border-[#E67E22]/40 transition-colors object-cover"
className="w-24 h-24 rounded-full border-2 border-[#1a1f2a] group-hover:border-[#d60701]/40 transition-colors object-cover"
/>
</a>
) : (
@@ -155,7 +155,7 @@ export default async function TeamPage() {
<h3 className="font-serif text-xl font-bold leading-tight">{p.name}</h3>
</a>
{(p.beat || p.slug === "ryan-salazar") && (
<div className="inline-block mt-1.5 px-2 py-0.5 rounded-sm bg-[#E67E22]/10 border border-[#E67E22]/25 text-[10px] font-mono uppercase tracking-[0.12em] text-[#F0B07A]">
<div className="inline-block mt-1.5 px-2 py-0.5 rounded-sm bg-[#d60701]/10 border border-[#d60701]/25 text-[10px] font-mono uppercase tracking-[0.12em] text-[#ff6b66]">
{displayBeat(p)}
</div>
)}
@@ -173,11 +173,11 @@ export default async function TeamPage() {
<ObfuscatedEmail
user={e.user}
domain={e.domain}
className="text-[#aab1bd] hover:text-[#F0B07A] font-mono"
className="text-[#aab1bd] hover:text-[#ff6b66] font-mono"
/>
<a
href={`/authors/${p.slug}`}
className="text-[10px] font-mono uppercase tracking-[0.12em] text-[#6c7686] hover:text-[#F0B07A]"
className="text-[10px] font-mono uppercase tracking-[0.12em] text-[#6c7686] hover:text-[#ff6b66]"
>
View
</a>
@@ -209,7 +209,7 @@ export default async function TeamPage() {
{ops.map((p) => (
<li
key={p.id}
className="rounded-xl border border-[#1a1f2a] bg-[#0b0f17] p-5 flex gap-4 hover:border-[#E67E22]/40 transition-colors"
className="rounded-xl border border-[#1a1f2a] bg-[#0b0f17] p-5 flex gap-4 hover:border-[#d60701]/40 transition-colors"
>
{p.avatar_url ? (
<img
@@ -235,13 +235,13 @@ export default async function TeamPage() {
if (!e) return null;
return (
<div className="font-mono">
<ObfuscatedEmail user={e.user} domain={e.domain} className="hover:text-[#F0B07A]" />
<ObfuscatedEmail user={e.user} domain={e.domain} className="hover:text-[#ff6b66]" />
</div>
);
})()}
{p.phone && (
<div>
<a href={`tel:${p.phone.replace(/[^\d+]/g, '')}`} className="hover:text-[#F0B07A] font-mono">
<a href={`tel:${p.phone.replace(/[^\d+]/g, '')}`} className="hover:text-[#ff6b66] font-mono">
{p.phone}{p.extension ? ` ext. ${p.extension}` : ''}
</a>
</div>