diff --git a/src/app/news/[slug]/NewsArticleDetailClient.tsx b/src/app/news/[slug]/NewsArticleDetailClient.tsx index 0d8e42e..d407ae9 100644 --- a/src/app/news/[slug]/NewsArticleDetailClient.tsx +++ b/src/app/news/[slug]/NewsArticleDetailClient.tsx @@ -4,6 +4,7 @@ import Link from "next/link"; import AppImage from "@/components/ui/AppImage"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; +import AdSlot from "@/components/AdSlot"; import { createClient } from "@/lib/supabase/client"; import type { Article } from "@/lib/articles/sampleArticles"; @@ -280,6 +281,11 @@ export default function NewsArticleDetailClient({ + {/* Top leaderboard */} +
+ +
+ {/* Article */}
@@ -444,6 +450,9 @@ export default function NewsArticleDetailClient({ {/* Sidebar */}
+ {/* Bottom leaderboard */} +
+ +
+ {/* Related Articles Carousel */} {relatedArticles.length > 0 && (
diff --git a/src/components/AdSlot.tsx b/src/components/AdSlot.tsx new file mode 100644 index 0000000..397e35f --- /dev/null +++ b/src/components/AdSlot.tsx @@ -0,0 +1,49 @@ +import { ReactElement } from "react"; + +type IabSize = "728x90" | "300x250" | "300x600" | "160x600" | "970x250" | "320x50"; +type Zone = + | "article-top" + | "article-bottom" + | "article-sidebar-top" + | "article-sidebar-mid" + | "article-inline" + | "homepage-top" + | "homepage-bottom"; + +const SIZE_MAP: Record = { + "728x90": { w: 728, h: 90 }, + "300x250": { w: 300, h: 250 }, + "300x600": { w: 300, h: 600 }, + "160x600": { w: 160, h: 600 }, + "970x250": { w: 970, h: 250 }, + "320x50": { w: 320, h: 50 }, +}; + +interface AdSlotProps { + zone: Zone; + size: IabSize; + className?: string; +} + +/** + * Banner ad slot. Server component (no client JS). + * + * Renders a labeled placeholder until populated. The eventual implementation + * will query bb.ad_placements (server-side) and render an for the + * winning campaign + record an impression. + */ +export default function AdSlot({ zone, size, className = "" }: AdSlotProps): ReactElement { + const { w, h } = SIZE_MAP[size]; + return ( +
+ Ad · {size} +
+ ); +}