HTML Stream eo4pzj

This is not a React page. It is a raw GET Route Handler (app/api/html-stream/route.ts) that returns a ReadableStream of HTML.

Chunk 1 <head> + opening body, up until this <div>, sent.
The CSS <link> tag in the head was discovered and fetched immediately. The stylesheet is render-blocking, so the browser won't paint until it arrives, but it keeps parsing HTML in the background. Check your server logs: the CSS request arrives while the HTML is still streaming.
Chunk 2 Arrived after ~1.5s. The CSS was already loaded by now, so this chunk is styled the moment it appears.
Chunk 3 Final chunk after ~3s. The document is now complete.
Side quest: why does fetch() need two awaits?

An HTTP response arrives in two phases. First the headers (status code, content-type, etc.), then the body which can stream over time. The Fetch API mirrors this:

// First await: resolves when the server sends headers.
// The body hasn't arrived yet — it's still streaming.
const res = await fetch("/api/html-stream");
console.log(res.status); // 200

// Second await: reads the body as it streams in, chunk by chunk.
const reader = res.body.getReader();
const dec = new TextDecoder();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  console.log(dec.decode(value));
}

This is exactly what you saw on this page: the server committed to 200 OK with the very first byte, then streamed three chunks over ~3 seconds. If something went wrong mid-stream, the status code couldn't change — it was already sent. The same applies to Next.js streaming: once the first Suspense fallback is flushed, the 200 is locked in. Before that point, the server can still respond with a real 404 or 302 if it hits a notFound() or redirect().

Convenience methods like res.json() and res.text() hide the second await by buffering the entire body internally. The ReadableStream reader above gives you access to each chunk as it arrives — try it in the console while this page is open.