From 1db0e2e190b9b2a01e43975466d42f775a714c62 Mon Sep 17 00:00:00 2001
From: "svelte-docs-bot[bot]"
<196124396+svelte-docs-bot[bot]@users.noreply.github.com>
Date: Fri, 1 May 2026 16:17:31 +0000
Subject: [PATCH] sync kit docs
---
.../20-core-concepts/60-remote-functions.md | 66 +++++++-
.../25-build-and-deploy/50-adapter-static.md | 2 +-
.../kit/30-advanced/40-service-workers.md | 2 +-
.../content/docs/kit/60-appendix/10-faq.md | 7 +-
.../docs/kit/98-reference/10-@sveltejs-kit.md | 154 +++++++++++++++---
.../docs/kit/98-reference/20-$app-server.md | 55 ++++++-
apps/svelte.dev/package.json | 2 +-
pnpm-lock.yaml | 64 ++++++--
8 files changed, 299 insertions(+), 53 deletions(-)
diff --git a/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md b/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md
index d87f175e0a..e1d9121970 100644
--- a/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md
+++ b/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md
@@ -275,6 +275,47 @@ export const getWeather = query.batch(v.string(), async (cityIds) => {
{/if}
```
+## query.live
+
+`query.live` is for accessing real-time data from the server. It behaves similarly to `query`, but the callback — typically an async [generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function*) — returns an `AsyncIterable`:
+
+```js
+import { query } from '$app/server';
+
+export const getTime = query.live(async function* () {
+ while (true) {
+ yield new Date();
+ await new Promise((f) => setTimeout(f, 1000));
+ }
+});
+```
+
+During server-side rendering, `await getTime()` returns the first yielded value then closes the iterator. This initial value is serialized and reused during hydration.
+
+On the client, the query stays connected while it's actively used in a component. Multiple instances share a connection. When there are no active uses left, the stream disconnects and server-side iteration is stopped.
+
+Live queries expose a `connected` property and `reconnect()` method:
+
+```svelte
+
+
+
{await time}
+
connected: {time.connected}
+
+```
+
+If the connection drops, `connected` becomes `false`. SvelteKit will attempt to reconnect passively, with exponential backoff, and actively if `navigator.onLine` goes from `false` to `true`.
+
+Unlike `query`, live queries do not have a `refresh()` method, as they are self-updating.
+
+As with `query` and `query.batch`, call `.run()` outside render when you need imperative access. For live queries, `run()` returns a `Promise>`.
+
+> [!NOTE] It's essential that you don't cache live query responses in a service worker, since the cloned response will continue streaming long after the page is closed. Make sure that your caching logic excludes any responses with a `Cache-Control` header that includes `no-store`.
+
## form
The `form` function makes it easy to write data to the server. It takes a callback that receives `data` constructed from the submitted [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)...
@@ -982,6 +1023,29 @@ export const updatePost = form(
Because queries are keyed based on their arguments, `await getPost(post.id).set(result)` on the server knows to look up the matching `getPost(id)` on the client to update it. The same goes for `getPosts().refresh()` -- it knows to look up `getPosts()` with no argument on the client.
+### Reconnecting live queries in mutations
+
+Single-flight mutations can also reconnect `query.live` instances. In a `form`/`command` handler, call `.reconnect()` on the live query resource you want to reconnect:
+
+```js
+import * as v from 'valibot';
+import { form, query } from '$app/server';
+
+export const getNotifications = query.live(v.string(), async function* (userId) {
+ while (true) {
+ yield await db.notifications(userId);
+ await wait(1000);
+ }
+});
+
+export const markAllRead = form(v.object({ userId: v.string() }), async ({ userId }) => {
+ // mutation logic...
+ +++getNotifications(userId).reconnect();+++
+});
+```
+
+This schedules a reconnect for the matching active client instances and applies it as part of the mutation response (i.e. in the same flight as the form/command result). You might need this if, for example, the command modifies a cookie that the live query needs to restart in order to capture.
+
### Client-requested refreshes
Unfortunately, life isn't always as simple as the preceding example. The server always knows which query _functions_ to update, but it may not know which specific query _instances_ to update. For example, if `getPosts({ filter: 'author:santa' })` is rendered on the client, calling `getPosts().refresh()` in the server handler won't update it. You'd need to call `getPosts({ filter: 'author:santa' }).refresh()` instead — but how could you know which specific combinations of filters are currently rendered on the client, especially if your query argument is more complicated than an object with just one key?
@@ -1199,7 +1263,7 @@ export const getStuff = query('unchecked', async ({ id }: { id: string }) => {
Inside `query`, `form` and `command` you can use [`getRequestEvent`]($app-server#getRequestEvent) to get the current [`RequestEvent`](@sveltejs-kit#RequestEvent) object. This makes it easy to build abstractions for interacting with cookies, for example:
```ts
-/// file: user.remote.ts
+/// file: user.remote.js
// @filename: ambient.d.ts
interface User {
name: string;
diff --git a/apps/svelte.dev/content/docs/kit/25-build-and-deploy/50-adapter-static.md b/apps/svelte.dev/content/docs/kit/25-build-and-deploy/50-adapter-static.md
index 9ff6db32dd..e39096e222 100644
--- a/apps/svelte.dev/content/docs/kit/25-build-and-deploy/50-adapter-static.md
+++ b/apps/svelte.dev/content/docs/kit/25-build-and-deploy/50-adapter-static.md
@@ -85,7 +85,7 @@ The directory to write static assets (the contents of `static`, plus client-side
To create a [single page app (SPA)](single-page-apps) you must specify the name of the fallback page to be generated by SvelteKit, which is used as the entry point for URLs that have not been prerendered. This is commonly `200.html`, but can vary depending on your deployment platform. You should avoid `index.html` where possible to avoid conflicting with a prerendered homepage.
-> This option has large negative performance and SEO impacts. It is only recommended in certain circumstances such as wrapping the site in a mobile app. See the [single page apps](single-page-apps) documentation for more details and alternatives.
+> [!NOTE] This option has large negative performance and SEO impacts. It is only recommended in certain circumstances such as wrapping the site in a mobile app. See the [single page apps](single-page-apps) documentation for more details and alternatives.
### precompress
diff --git a/apps/svelte.dev/content/docs/kit/30-advanced/40-service-workers.md b/apps/svelte.dev/content/docs/kit/30-advanced/40-service-workers.md
index 7ab5f0c5af..5cd52b6f4f 100644
--- a/apps/svelte.dev/content/docs/kit/30-advanced/40-service-workers.md
+++ b/apps/svelte.dev/content/docs/kit/30-advanced/40-service-workers.md
@@ -99,7 +99,7 @@ self.addEventListener('fetch', (event) => {
throw new Error('invalid response from fetch');
}
- if (response.status === 200) {
+ if (response.status === 200 && !response.headers.get('cache-control')?.includes('no-store')) {
cache.put(event.request, response.clone());
}
diff --git a/apps/svelte.dev/content/docs/kit/60-appendix/10-faq.md b/apps/svelte.dev/content/docs/kit/60-appendix/10-faq.md
index 530f54d4d6..e225380a67 100644
--- a/apps/svelte.dev/content/docs/kit/60-appendix/10-faq.md
+++ b/apps/svelte.dev/content/docs/kit/60-appendix/10-faq.md
@@ -155,12 +155,7 @@ export function GET({ params, url }) {
`adapter-node` builds a middleware that you can use with your own server for production mode. In dev, you can add middleware to Vite by using a Vite plugin. For example:
```js
-// @errors: 2322
-// @filename: ambient.d.ts
-declare module '@sveltejs/kit/vite'; // TODO this feels unnecessary, why can't it 'see' the declarations?
-
-// @filename: index.js
-// ---cut---
+/// file: vite.config.js
import { sveltekit } from '@sveltejs/kit/vite';
/** @type {import('vite').Plugin} */
diff --git a/apps/svelte.dev/content/docs/kit/98-reference/10-@sveltejs-kit.md b/apps/svelte.dev/content/docs/kit/98-reference/10-@sveltejs-kit.md
index 267f6b20ef..146e4af704 100644
--- a/apps/svelte.dev/content/docs/kit/98-reference/10-@sveltejs-kit.md
+++ b/apps/svelte.dev/content/docs/kit/98-reference/10-@sveltejs-kit.md
@@ -505,7 +505,7 @@ read?: (details: { config: any; route: { id: string } }) => boolean;
-- `details.config` The merged route config
+- `details.config` The merged adapter-specific route config exported from the route with `export const config`
@@ -1361,6 +1361,50 @@ type LessThan<
+## LiveQueryRequestedResult
+
+
+
+```dts
+type LiveQueryRequestedResult = Iterable<
+ LiveRequestedEntry
+> &
+ AsyncIterable> & {
+ /**
+ * Call `reconnect` on all live queries selected by this `requested` invocation.
+ * This is identical to:
+ * ```ts
+ * import { requested } from '$app/server';
+ *
+ * for await (const { query } of requested(liveQuery, ...)) {
+ * void query.reconnect();
+ * }
+ * ```
+ */
+ reconnectAll: () => Promise;
+ };
+```
+
+
+
+## LiveRequestedEntry
+
+A single entry yielded by [`requested`](/docs/kit/$app-server#requested)
+when called with a `query.live`. `arg` is the validated argument; `query` is a
+`RemoteLiveQuery` bound to the client's original cache key, so `reconnect()` targets
+the correct client subscription.
+
+
+
## Load
The generic form of `PageLoad` and `LayoutLoad`. You should import those from `./$types` (see [generated types](/docs/kit/types#Generated-types))
@@ -2349,6 +2393,32 @@ type PrerenderOption = boolean | 'auto';
+## QueryRequestedResult
+
+
+
+```dts
+type QueryRequestedResult = Iterable<
+ RequestedEntry
+> &
+ AsyncIterable> & {
+ /**
+ * Call `refresh` on all queries selected by this `requested` invocation.
+ * This is identical to:
+ * ```ts
+ * import { requested } from '$app/server';
+ *
+ * for await (const { query } of requested(getPost, ...)) {
+ * void query.refresh();
+ * }
+ * ```
+ */
+ refreshAll: () => Promise;
+ };
+```
+
+
+
## Redirect
The object returned by the [`redirect`](/docs/kit/@sveltejs-kit#redirect) function.
@@ -2387,7 +2457,7 @@ The location to redirect to.
## RemoteCommand
-The return value of a remote `command` function. See [Remote functions](/docs/kit/remote-functions#command) for full documentation.
+The type of a remote `command` function. See [Remote functions](/docs/kit/remote-functions#command) for full documentation.
@@ -2409,7 +2479,7 @@ type RemoteCommand = {
## RemoteForm
-The return value of a remote `form` function. See [Remote functions](/docs/kit/remote-functions#form) for full documentation.
+The type of a remote `form` function. See [Remote functions](/docs/kit/remote-functions#form) for full documentation.
@@ -2616,9 +2686,54 @@ path: Array;
+## RemoteLiveQuery
+
+
+
+```dts
+type RemoteLiveQuery = RemoteResource & {
+ /**
+ * Returns an async iterator with live updates.
+ * Unlike awaiting the resource directly, this can only be used _outside_ render
+ * (i.e. in load functions, event handlers and so on)
+ */
+ run(): AsyncGenerator;
+ /** `true` if the live stream is currently connected. */
+ readonly connected: boolean;
+ /** `true` once the current live stream iterator is done. */
+ readonly done: boolean;
+ /** Reconnects the live stream immediately. */
+ reconnect(): Promise;
+};
+```
+
+
+
+## RemoteLiveQueryFunction
+
+The type of a remote `query.live` function. See [Remote functions](/docs/kit/remote-functions#query.live) for full documentation.
+
+The optional `Validated` generic parameter represents the argument type *after* the
+query's schema has validated and (optionally) transformed it, and matches the type
+yielded by [`requested`](/docs/kit/$app-server#requested).
+
+
+
## RemotePrerenderFunction
-The return value of a remote `prerender` function. See [Remote functions](/docs/kit/remote-functions#prerender) for full documentation.
+The type of a remote `prerender` function. See [Remote functions](/docs/kit/remote-functions#prerender) for full documentation.
@@ -2727,7 +2842,9 @@ type RemoteQueryOverride = () => void;
```dts
type RemoteQueryUpdate =
| RemoteQuery
+ | RemoteLiveQuery
| RemoteQueryFunction
+ | RemoteLiveQueryFunction
| RemoteQueryOverride;
```
@@ -3061,10 +3178,11 @@ type RequestHandler<
## RequestedEntry
-A single entry yielded by [`requested`](/docs/kit/$app-server#requested).
-`arg` is the validated argument (the input *after* the query's schema validated and
-transformed it, if applicable); `query` is a `RemoteQuery` bound to the client's
-original cache key, so `refresh()` / `set()` will update the correct client entry.
+A single entry yielded by [`requested`](/docs/kit/$app-server#requested)
+when called with a regular `query`. `arg` is the validated argument (the input *after*
+the query's schema validated and transformed it, if applicable); `query` is a
+`RemoteQuery` bound to the client's original cache key, so `refresh()` / `set()` will
+update the correct client entry.
@@ -3082,23 +3200,9 @@ type RequestedEntry = {
```dts
-type RequestedResult = Iterable<
- RequestedEntry
-> &
- AsyncIterable> & {
- /**
- * Call `refresh` on all queries selected by this `requested` invocation.
- * This is identical to:
- * ```ts
- * import { requested } from '$app/server';
- *
- * for await (const { query } of requested(getPost, ...)) {
- * void query.refresh();
- * }
- * ```
- */
- refreshAll: () => Promise;
- };
+type RequestedResult =
+ | QueryRequestedResult
+ | LiveQueryRequestedResult;
```
diff --git a/apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md b/apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md
index 2e2c080c60..3ad230723a 100644
--- a/apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md
+++ b/apps/svelte.dev/content/docs/kit/98-reference/20-$app-server.md
@@ -34,7 +34,7 @@ See [Remote functions](/docs/kit/remote-functions#command) for full documentatio
```dts
function command