initial commit: rocket.new export of broadcastbeat
This commit is contained in:
198
src/app/home-page/page.tsx
Normal file
198
src/app/home-page/page.tsx
Normal file
@@ -0,0 +1,198 @@
|
||||
import React, { Suspense } from "react";
|
||||
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";
|
||||
import ScrollRevealSection from "@/components/ScrollRevealSection";
|
||||
import NewsletterSignup from "./components/NewsletterSignup";
|
||||
import AISuggestedArticles from "@/components/AISuggestedArticles";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'BroadcastBeat — Broadcast Engineering News & Insights',
|
||||
description: 'The digital platform for broadcast engineering professionals. Breaking news, deep-dive features, and industry spotlights from NAB to IBC and beyond.',
|
||||
alternates: {
|
||||
canonical: '/home-page',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'BroadcastBeat — Broadcast News',
|
||||
description: 'Breaking news and insights for broadcast engineering professionals.',
|
||||
url: '/home-page',
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url: '/assets/images/og-image.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'BroadcastBeat — Broadcast Engineering News & Insights',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'BroadcastBeat — Broadcast News',
|
||||
description: 'Breaking news and insights for broadcast engineering professionals.',
|
||||
images: ['/assets/images/og-image.png'],
|
||||
},
|
||||
};
|
||||
|
||||
/* ── Skeleton placeholders ─────────────────────────────── */
|
||||
function TickerSkeleton() {
|
||||
return (
|
||||
<div className="w-full h-8 skeleton" style={{ borderRadius: 0 }} />
|
||||
);
|
||||
}
|
||||
|
||||
function LeaderboardSkeleton() {
|
||||
return (
|
||||
<div className="max-w-container mx-auto px-4 py-3">
|
||||
<div className="skeleton h-[90px] w-full rounded-sm" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function BentoSkeleton() {
|
||||
return (
|
||||
<section className="max-w-container mx-auto px-4 py-4 md:py-6">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="skeleton h-4 w-20 rounded-sm" />
|
||||
<div className="flex-1 h-px bg-[#2a2a2a]" />
|
||||
</div>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-3 md:gap-4">
|
||||
<div className="lg:col-span-7 skeleton rounded-sm h-[260px] sm:h-[320px] md:h-[380px]" />
|
||||
<div className="lg:col-span-5 grid grid-cols-2 gap-3 md:gap-4">
|
||||
{[...Array(4)]?.map((_, i) => (
|
||||
<div key={i} className="skeleton-card">
|
||||
<div className="skeleton h-[110px] sm:h-[130px]" />
|
||||
<div className="p-2 space-y-1.5">
|
||||
<div className="skeleton h-3 w-16 rounded-sm" />
|
||||
<div className="skeleton h-4 w-full rounded-sm" />
|
||||
<div className="skeleton h-4 w-3/4 rounded-sm" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function CarouselSkeleton() {
|
||||
return (
|
||||
<div className="py-6 px-4">
|
||||
<div className="max-w-container mx-auto">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="skeleton h-4 w-24 rounded-sm" />
|
||||
<div className="flex-1 h-px bg-[#2a2a2a]" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{[...Array(4)]?.map((_, i) => (
|
||||
<div key={i} className="skeleton-card">
|
||||
<div className="skeleton h-[140px]" />
|
||||
<div className="p-3 space-y-2">
|
||||
<div className="skeleton h-3 w-16 rounded-sm" />
|
||||
<div className="skeleton h-4 w-full rounded-sm" />
|
||||
<div className="skeleton h-4 w-2/3 rounded-sm" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FeedSkeleton() {
|
||||
return (
|
||||
<section className="max-w-container mx-auto px-4 py-4 md:py-6">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6 lg:gap-8">
|
||||
<div className="lg:col-span-8 space-y-1">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="skeleton h-4 w-20 rounded-sm" />
|
||||
<div className="flex-1 h-px bg-[#2a2a2a]" />
|
||||
</div>
|
||||
{[...Array(5)]?.map((_, i) => (
|
||||
<div key={i} className="flex gap-4 py-4 border-b border-[#222]">
|
||||
<div className="skeleton flex-shrink-0 w-[140px] h-[95px] rounded-sm" />
|
||||
<div className="flex-1 space-y-2">
|
||||
<div className="skeleton h-3 w-24 rounded-sm" />
|
||||
<div className="skeleton h-5 w-full rounded-sm" />
|
||||
<div className="skeleton h-5 w-4/5 rounded-sm" />
|
||||
<div className="skeleton h-3 w-32 rounded-sm" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="lg:col-span-4 space-y-4">
|
||||
<div className="skeleton h-[250px] rounded-sm" />
|
||||
<div className="skeleton h-[200px] rounded-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
{/* Sticky top bar + nav */}
|
||||
<Header />
|
||||
|
||||
{/* H1 Hero Heading */}
|
||||
<div className="sr-only">
|
||||
<h1>BroadcastBeat — Broadcast Engineering News & Insights</h1>
|
||||
</div>
|
||||
|
||||
{/* Scrolling news ticker */}
|
||||
<div className="section-enter section-enter-1">
|
||||
<Suspense fallback={<TickerSkeleton />}>
|
||||
<NewsTicker />
|
||||
</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 />}>
|
||||
<FeaturedBento />
|
||||
</Suspense>
|
||||
</ScrollRevealSection>
|
||||
|
||||
{/* Spotlight carousel — dark navy band */}
|
||||
<ScrollRevealSection className="section-enter section-enter-4" delay={1}>
|
||||
<Suspense fallback={<CarouselSkeleton />}>
|
||||
<SpotlightCarousel />
|
||||
</Suspense>
|
||||
</ScrollRevealSection>
|
||||
|
||||
{/* AI Suggested Articles */}
|
||||
<ScrollRevealSection className="section-enter section-enter-5" delay={1}>
|
||||
<AISuggestedArticles variant="compact" />
|
||||
</ScrollRevealSection>
|
||||
|
||||
{/* Article feed + sidebar */}
|
||||
<ScrollRevealSection className="section-enter section-enter-5" delay={2}>
|
||||
<Suspense fallback={<FeedSkeleton />}>
|
||||
<ArticleFeed />
|
||||
</Suspense>
|
||||
</ScrollRevealSection>
|
||||
|
||||
{/* Newsletter signup */}
|
||||
<ScrollRevealSection className="section-enter section-enter-5">
|
||||
<NewsletterSignup />
|
||||
</ScrollRevealSection>
|
||||
|
||||
{/* Footer */}
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user