Cursor timing (~4 blinks each side); rewrite perf post to the real fix

- Monitor terminal: ~4 blinks, type 'such', backspace, ~4 blinks, fade.
- Rewrite the blog post so it tells the accurate story end to end (not an update):
  the LCP breakdown showed render delay with TTFB 0 and a free main thread, so it
  was neither the network nor JavaScript. It was render-blocking CSS, fixed by
  inlining the stylesheet. Server components / dropping framer are kept as honest
  supporting steps, not the gate. Swap the architecture figure for a CSS
  critical-path figure; mobile now a steady 100.
This commit is contained in:
jwinterm
2026-06-07 17:32:21 -04:00
parent 89c086398d
commit d2d4ff997f
4 changed files with 88 additions and 101 deletions
@@ -0,0 +1,25 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 300" role="img"
aria-label="Two request timelines. Before: the HTML arrives, then the browser makes a second request for the stylesheet and waits for it, then the logo paints late. After: the HTML arrives with the CSS inlined, and the logo paints immediately.">
<rect x="2" y="2" width="756" height="296" rx="16" fill="#f8fafc" stroke="#e2e8f0"/>
<text x="100" y="40" font-family="ui-sans-serif, system-ui, sans-serif" font-size="19" font-weight="700" fill="#1e293b">Why the logo painted late: a second request</text>
<!-- Before -->
<text x="100" y="96" font-family="ui-sans-serif, system-ui, sans-serif" font-size="14" font-weight="600" fill="#334155">Before: separate stylesheet (render-blocking)</text>
<rect x="100" y="108" width="150" height="22" rx="3" fill="#e2e8f0"/>
<text x="175" y="123" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="11" fill="#475569">HTML (+ logo)</text>
<rect x="250" y="108" width="330" height="22" rx="3" fill="#fde68a" stroke="#d97706"/>
<text x="415" y="123" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="11" font-weight="600" fill="#b45309">fetch + wait for CSS</text>
<line x1="580" y1="100" x2="580" y2="138" stroke="#dc2626" stroke-width="2"/>
<circle cx="580" cy="119" r="5" fill="#dc2626"/>
<text x="580" y="154" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="11" font-weight="600" fill="#dc2626">logo paints (late)</text>
<!-- After -->
<text x="100" y="208" font-family="ui-sans-serif, system-ui, sans-serif" font-size="14" font-weight="600" fill="#334155">After: CSS inlined in the HTML</text>
<rect x="100" y="220" width="170" height="22" rx="3" fill="#d1fae5" stroke="#059669"/>
<text x="185" y="235" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="11" fill="#047857">HTML (+ logo + CSS)</text>
<line x1="270" y1="212" x2="270" y2="250" stroke="#059669" stroke-width="2"/>
<circle cx="270" cy="231" r="5" fill="#059669"/>
<text x="284" y="235" font-family="ui-sans-serif, system-ui, sans-serif" font-size="11" font-weight="600" fill="#047857">logo paints (early)</text>
<text x="100" y="282" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" fill="#64748b">Same logo, ready instantly either way. The wait was the CSS round-trip, not the image.</text>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,33 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 360" role="img"
aria-label="Before: page.tsx is one client component holding the splash, header, hero, sections, and contact form, all of which ship and run as JavaScript, so the page paints late. After: page.tsx is a Server Component; only a small client island (splash, header, nav, background) ships JavaScript, while the hero and sections are server HTML, so the page paints early.">
<rect x="2" y="2" width="756" height="356" rx="16" fill="#f8fafc" stroke="#e2e8f0"/>
<text x="40" y="40" font-family="ui-sans-serif, system-ui, sans-serif" font-size="18" font-weight="700" fill="#1e293b">One client component vs. server HTML plus an island</text>
<!-- Before -->
<text x="60" y="82" font-family="ui-sans-serif, system-ui, sans-serif" font-size="15" font-weight="700" fill="#334155">Before</text>
<rect x="40" y="92" width="300" height="206" rx="10" fill="none" stroke="#94a3b8" stroke-width="1.5"/>
<text x="54" y="114" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" font-weight="600" fill="#475569">page.tsx &#8212; "use client"</text>
<g font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" fill="#b45309" text-anchor="middle">
<rect x="54" y="124" width="272" height="28" rx="5" fill="#fde68a" stroke="#d97706"/><text x="190" y="142">Splash</text>
<rect x="54" y="158" width="272" height="28" rx="5" fill="#fde68a" stroke="#d97706"/><text x="190" y="176">Header + nav</text>
<rect x="54" y="192" width="272" height="28" rx="5" fill="#fde68a" stroke="#d97706"/><text x="190" y="210">Hero + tagline</text>
<rect x="54" y="226" width="272" height="28" rx="5" fill="#fde68a" stroke="#d97706"/><text x="190" y="244">Sections</text>
<rect x="54" y="260" width="272" height="28" rx="5" fill="#fde68a" stroke="#d97706"/><text x="190" y="278">Contact form</text>
</g>
<text x="190" y="322" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" fill="#b45309">all of it ships and runs as JavaScript</text>
<text x="190" y="342" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" font-weight="600" fill="#dc2626">&#8594; the page paints late</text>
<!-- After -->
<text x="420" y="82" font-family="ui-sans-serif, system-ui, sans-serif" font-size="15" font-weight="700" fill="#334155">After</text>
<rect x="400" y="92" width="320" height="206" rx="10" fill="none" stroke="#94a3b8" stroke-width="1.5"/>
<text x="414" y="114" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" font-weight="600" fill="#475569">page.tsx &#8212; Server Component</text>
<rect x="414" y="124" width="292" height="44" rx="5" fill="#fde68a" stroke="#d97706"/>
<text x="560" y="142" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" font-weight="600" fill="#b45309">client island</text>
<text x="560" y="159" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="10" fill="#b45309">splash &#183; header &#183; nav &#183; background</text>
<rect x="414" y="176" width="292" height="40" rx="5" fill="#d1fae5" stroke="#059669"/>
<text x="560" y="200" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" fill="#047857">Hero + tagline &#8212; server HTML</text>
<rect x="414" y="224" width="292" height="40" rx="5" fill="#d1fae5" stroke="#059669"/>
<text x="560" y="248" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" fill="#047857">Sections &#8212; server HTML</text>
<text x="560" y="322" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" fill="#059669">only the island ships JavaScript</text>
<text x="560" y="342" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="12" font-weight="600" fill="#047857">&#8594; the page paints early</text>
</svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB