Async-generator streaming

Async generators yielding JSX flow as chunks through bext's renderToStream. Each yielded fragment hits the wire as soon as it's produced — open the network tab to watch the response trickle in over ~1s.

Tip
Declare renderingMode = "streaming" when the root component is sync but its children are async generators — the auto-classifier doesn't see nested generators. If your page imports <Suspense>, that import alone activates streaming without any explicit declaration.

Live stream

starting…

chunk 1 @ 04:03:59

chunk 2 @ 04:04:00

chunk 3 @ 04:04:00

chunk 4 @ 04:04:00

done.

src/app/examples/streaming/page.tsxTSX
// Async generator yields JSX chunks. When the JSX
// runtime sees an AsyncIterable in a child position it
// streams each chunk to the response without buffering.

// Explicit opt-in: root component is sync so the auto-classifier
// doesn't fire — generators in child position aren't detected.
export const renderingMode = "streaming";

// Site default is ISR — opt out so every request streams fresh
// (otherwise the streamed body is cached and served buffered).
export const dynamic = "force-dynamic";

async function* slowChunks() {
  yield <p>starting…</p>;
  for (let i = 1; i <= 4; i++) {
    await new Promise(r => setTimeout(r, 200));
    yield <p>chunk {i} @ {new Date().toISOString().slice(11, 19)}</p>;
  }
  yield <p>done.</p>;
}

export default function Page() {
  return (
    <div>
      <h2>Live stream</h2>
      <div>{slowChunks()}</div>
    </div>
  );
}