From 2267daadd48245d05e6b546865ca7919c668883f Mon Sep 17 00:00:00 2001 From: Marco Sadjadi Date: Tue, 26 May 2026 23:30:41 +0200 Subject: [PATCH] perf(web): server-only StaticCodeBlock for above-the-fold marketing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PageSpeed Insights mobile reported LCP element render delay of 2.3s on the hero — the largest visible element is the build.log
 with
"> Generating spec... OK ..." text. TTFB is 0ms (CF cache hit), so the
delay was pure client-side: Lighthouse waited for the JS bundle to
parse and the 'use client' CodeBlock boundary to hydrate before it
considered the element "rendered."

CodeBlock pulls in lucide-react (Copy/Check icons) plus a useState
boundary just for the copy button. Above the fold on marketing, none
of that is needed — the user just needs to see the snippet.

Split:
- New `static-code-block.tsx`: server component, no 'use client',
  no icons, no copy button. Pure SSR markup that paints with the HTML.
- Marketing landing now uses StaticCodeBlock for all three hero
  snippets (prompt.txt / build.log / claude_desktop_config.json).
- Interactive CodeBlock stays in use for dashboard pages where users
  actually want to copy snippets.

Co-Authored-By: Claude Opus 4.7 (1M context) 
---
 apps/web/app/(marketing)/page.tsx         |  8 ++---
 apps/web/components/static-code-block.tsx | 37 +++++++++++++++++++++++
 2 files changed, 41 insertions(+), 4 deletions(-)
 create mode 100644 apps/web/components/static-code-block.tsx

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