diff --git a/apps/web/app/(marketing)/page.tsx b/apps/web/app/(marketing)/page.tsx
index 5314520..42706d6 100644
--- a/apps/web/app/(marketing)/page.tsx
+++ b/apps/web/app/(marketing)/page.tsx
@@ -1,5 +1,5 @@
-import { CodeBlock } from '@/components/code-block';
import { JsonLd } from '@/components/json-ld';
+import { StaticCodeBlock } from '@/components/static-code-block';
import { FAQ, faqJsonLd } from '@/lib/seo';
import Link from 'next/link';
@@ -134,9 +134,9 @@ export default function Landing() {
diff --git a/apps/web/components/static-code-block.tsx b/apps/web/components/static-code-block.tsx
new file mode 100644
index 0000000..c1d947e
--- /dev/null
+++ b/apps/web/components/static-code-block.tsx
@@ -0,0 +1,37 @@
+import { cn } from '@/lib/cn';
+
+export interface StaticCodeBlockProps {
+ code: string;
+ language?: string;
+ label?: string;
+ className?: string;
+}
+
+/**
+ * Server-only variant of CodeBlock — no copy button, no client hydration.
+ *
+ * Use this for above-the-fold marketing content where every kilobyte of
+ * JS hurts LCP. The interactive CodeBlock pulls in lucide-react icons and
+ * a useState boundary that forces an entire client chunk to load before
+ * Lighthouse considers the element "rendered". This static variant is
+ * pure SSR markup and lets the browser paint as soon as the HTML arrives.
+ *
+ * CodeBlock (with copy button) stays in use for dashboard pages where
+ * users actually want to copy snippets.
+ */
+export function StaticCodeBlock({ code, language, label, className }: StaticCodeBlockProps) {
+ return (
+
+ {(label || language) && (
+
+
+ {label ?? language}
+
+
+ )}
+
+ {code}
+
+
+ );
+}