# Streaming

> Send the page in parts while it renders.

`renderStream` sends a page in parts while it renders. The browser can start loading styles and showing the top of the page while slower data is still loading.

```ts
const stream = await kiln.renderStream("pages/post", { post }, {
	signal: request.signal,
});

return new Response(stream, {
	headers: { "content-type": "text/html; charset=utf-8" },
});
```

- `renderStream` takes the same arguments as [`render`](https://kilnlang.com/docs/api/rendering/), and the parts join up to the same HTML, unless [islands stream](#islands).
- It returns a promise for a `ReadableStream` of UTF-8 bytes. Workers, Deno, Bun and Node's `Response` accept it as it is.
- Kiln sends what's ready each time the render has to wait for one of your async functions, filters or tests, your loader or your cache store. A template that never waits is sent in one part.
- Precompiled templates stream the same way.

With Node's `http` module, turn the stream into a Node stream:

```ts
import { Readable } from "node:stream";

const stream = await kiln.renderStream("pages/home", context);
response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
Readable.fromWeb(stream).pipe(response);
```

## Errors and status codes

The promise resolves once the first part of the page is ready. If the render fails before then, the promise rejects with the same error `render` would give, so you can still send an error page with the right status.

Once part of the page has been sent, its status and headers have gone too. A later error ends the stream with that error, and the browser keeps the part it already has. Your server reports the error as it would for any failed stream.

So load whatever decides the status at the top of the page. A page's top-level tags run before its layout outputs anything, so a missing page still rejects the promise:

```kiln
{% extends "layouts/base" %}
{% set page = document("page", slug: route.path) ?? notFound() %}

{% block content %}
	<h1>{{ page.title }}</h1>
	{% set related = documents("page", tag: page.tag) %}
	…
{% endblock %}
```

## Outlets

Content can be added to an [outlet](https://kilnlang.com/docs/tags/outlet/) until the render ends, so Kiln holds back the page from the first outlet onwards. A layout with an outlet in its `<head>` would send almost nothing early.

[`flush`](https://kilnlang.com/docs/tags/flush/) fixes this. It closes the outlets above it, so everything up to it can be sent. Put it after the head:

```kiln
<html>
	<head>
		<title>{{ title }}</title>
		{% outlet "head" %}
	</head>
	{% flush %}
	<body>
		{% block content %}{% endblock %}
		{% outlet "scripts" %}
	</body>
</html>
```

Here the head is sent as soon as the render first waits, and the body follows as it renders, up to the `scripts` outlet. That last part is sent when the render ends.

## Islands

A slow part of the page holds up everything after it. Make it an [`island`](https://kilnlang.com/docs/tags/island/) and pass `islands: streamIslands()`, and the page is sent with the island's fallback in its place. The island's HTML follows in the same response when it's ready. See [Streaming islands](https://kilnlang.com/docs/tags/island/#streaming-islands).

## Stopping a render

If the visitor leaves and the stream is cancelled, Kiln stops sending, but the render runs on until it finishes. Pass the request's `signal` so the render stops as well. When the signal aborts, the stream ends with an `aborted` error straight away, even while the page or an island waits for your code.

## Limits

`maxOutputLength` counts the whole page, as it does for `render`. See [Safety and limits](https://kilnlang.com/docs/api/safety/).
