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}
+
+ );
+}