SvelteKit • Core concepts

Loading data

On this page

Before a +page.svelte component (and its containing +layout.svelte components) can be rendered, we often need to get some data. This is done by defining load functions.

Page data

A +page.svelte file can have a sibling +page.js that exports a load function, the return value of which is available to the page via the data prop:

import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';

export const const load: PageLoadconst load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = ({ params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
}) => {
return {
post: {
    title: string;
    content: string;
}
post: {
    title: string;
    content: string;
}
post
: {
title: stringtitle: stringtitle: `Title for ${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.slug} goes here`,
content: stringcontent: stringcontent: `Content for ${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.slug} goes here`
} }; };
/** @type {import('./$types').PageLoad} */
export function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({ params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
}) {
return {
post: {
    title: string;
    content: string;
}
post: {
    title: string;
    content: string;
}
post
: {
title: stringtitle: stringtitle: `Title for ${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.slug} goes here`,
content: stringcontent: stringcontent: `Content for ${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.slug} goes here`
} }; }
<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>
Legacy mode

Before version 2.16.0, the props of a page and layout had to be typed individually:

import type { PageData } from './$types';

let { data }: { data: PageData } = $props();
/** @type {{ data: import('./$types').PageData }} */
let { data } = $props();

In Svelte 4, you’d use export let data instead.

Thanks to the generated $types module, we get full type safety.

A load function in a +page.js file runs both on the server and in the browser (unless combined with export const ssr = false, in which case it will only run in the browser). If your load function should always run on the server (because it uses private environment variables, for example, or accesses a database) then it would go in a +page.server.js instead.

A more realistic version of your blog post’s load function, that only runs on the server and pulls data from a database, might look like this:

// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(slug: stringslug: stringslug: string): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ title: stringtitle: stringtitle: string, content: stringcontent: stringcontent: string }>
} // @filename: index.ts // cut import * as module "$lib/server/database"db from '$lib/server/database'; import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types'; export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async ({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
}) => {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
.slug)
}; };
// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(slug: stringslug: stringslug: string): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ title: stringtitle: stringtitle: string, content: stringcontent: stringcontent: string }>
} // @filename: index.js // cut import * as module "$lib/server/database"db from '$lib/server/database'; /** @type {import('./$types').PageServerLoad} */ export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
}) {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
.slug)
}; }

Notice that the type changed from PageLoad to PageServerLoad, because server load functions can access additional arguments. To understand when to use +page.js and when to use +page.server.js, see Universal vs server.

Layout data

Your +layout.svelte files can also load data, via +layout.js or +layout.server.js.

// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
(): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<interface Array<T>interface Array<T>Array<{ title: stringtitle: stringtitle: string, slug: stringslug: stringslug: string }>>
} // @filename: index.ts // cut import * as module "$lib/server/database"db from '$lib/server/database'; import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async () => { return {
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; };
// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
(): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<interface Array<T>interface Array<T>Array<{ title: stringtitle: stringtitle: string, slug: stringslug: stringslug: string }>>
} // @filename: index.js // cut import * as module "$lib/server/database"db from '$lib/server/database'; /** @type {import('./$types').LayoutServerLoad} */ export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
() {
return {
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; }
<script lang="ts">
	import type { LayoutProps } from './$types';

	let { data, children }: LayoutProps = $props();
</script>

<main>
	<!-- +page.svelte is `@render`ed here -->
	{@render children()}
</main>

<aside>
	<h2>More posts</h2>
	<ul>
		{#each data.posts as post}
			<li>
				<a href="/blog/{post.slug}">
					{post.title}
				</a>
			</li>
		{/each}
	</ul>
</aside>
<script>
	/** @type {import('./$types').LayoutProps} */
	let { data, children } = $props();
</script>

<main>
	<!-- +page.svelte is `@render`ed here -->
	{@render children()}
</main>

<aside>
	<h2>More posts</h2>
	<ul>
		{#each data.posts as post}
			<li>
				<a href="/blog/{post.slug}">
					{post.title}
				</a>
			</li>
		{/each}
	</ul>
</aside>
Legacy mode

LayoutProps was added in 2.16.0. In earlier versions, properties had to be typed individually:

import type { LayoutData } from './$types';

let { data, children }: { data: LayoutData, children: Snippet } = $props();
/** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
let { data, children } = $props();

Data returned from layout load functions is available to child +layout.svelte components and the +page.svelte component as well as the layout that it ‘belongs’ to.

<script lang="ts">
	import { page } from '$app/state';

	/** @type {import('./$types').PageProps} */
	let { data } = $props();

	// we can access `data.posts` because it's returned from
	// the parent layout `load` function
	let index = $derived(data.posts.findIndex(post => post.slug === page.params.slug));
	let next = $derived(data.posts[index + 1]);
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

{#if next}
	<p>Next post: <a href="/blog/{next.slug}">{next.title}</a></p>
{/if}
<script>
	import { page } from '$app/state';

	/** @type {import('./$types').PageProps} */
	let { data } = $props();

	// we can access `data.posts` because it's returned from
	// the parent layout `load` function
	let index = $derived(data.posts.findIndex(post => post.slug === page.params.slug));
	let next = $derived(data.posts[index + 1]);
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

{#if next}
	<p>Next post: <a href="/blog/{next.slug}">{next.title}</a></p>
{/if}

If multiple load functions return data with the same key, the last one ‘wins’ — the result of a layout load returning { a: 1, b: 2 } and a page load returning { b: 3, c: 4 } would be { a: 1, b: 3, c: 4 }.

page.data

The +page.svelte component, and each +layout.svelte component above it, has access to its own data plus all the data from its parents.

In some cases, we might need the opposite — a parent layout might need to access page data or data from a child layout. For example, the root layout might want to access a title property returned from a load function in +page.js or +page.server.js. This can be done with page.data:

<script lang="ts">
	import { const page: Page<Record<string, string>, string | null>

A read-only reactive object with information about the current page, serving several use cases:

  • retrieving the combined data of all pages/layouts anywhere in your component tree (also see loading data)

  • retrieving the current value of the form prop anywhere in your component tree (also see form actions)

  • retrieving the page state that was set through goto, pushState or replaceState (also see goto and shallow routing)

  • retrieving metadata such as the URL you're on, the current route and its parameters, and whether or not there was an error

<!--- file: +layout.svelte --->
<script>
	import { page } from '$app/state';
</script>

<p>Currently at {page.url.pathname}</p>

{#if page.error}
	<span class="red">Problem detected</span>
{:else}
	<span class="small">All systems operational</span>
{/if}

Changes to page are available exclusively with runes. (The legacy reactivity syntax will not reflect any changes)

<!--- file: +page.svelte --->
<script>
	import { page } from '$app/state';
	const id = $derived(page.params.id); // This will correctly update id for usage on this page
	$: badId = page.params.id; // Do not use; will never update after initial load
</script>

On the server, values can only be read during rendering (in other words not in e.g. load functions). In the browser, the values can be read at any time.

page
} from '$app/state';
</script> <svelte:head> <title>{const page: Page<Record<string, string>, string | null>

A read-only reactive object with information about the current page, serving several use cases:

  • retrieving the combined data of all pages/layouts anywhere in your component tree (also see loading data)

  • retrieving the current value of the form prop anywhere in your component tree (also see form actions)

  • retrieving the page state that was set through goto, pushState or replaceState (also see goto and shallow routing)

  • retrieving metadata such as the URL you're on, the current route and its parameters, and whether or not there was an error

<!--- file: +layout.svelte --->
<script>
	import { page } from '$app/state';
</script>

<p>Currently at {page.url.pathname}</p>

{#if page.error}
	<span class="red">Problem detected</span>
{:else}
	<span class="small">All systems operational</span>
{/if}

Changes to page are available exclusively with runes. (The legacy reactivity syntax will not reflect any changes)

<!--- file: +page.svelte --->
<script>
	import { page } from '$app/state';
	const id = $derived(page.params.id); // This will correctly update id for usage on this page
	$: badId = page.params.id; // Do not use; will never update after initial load
</script>

On the server, values can only be read during rendering (in other words not in e.g. load functions). In the browser, the values can be read at any time.

page
.Page<Record<string, string>, string | null>.data: App.PageData & Record<string, any>

The merged result of all data from all load functions on the current page. You can type a common denominator through App.PageData.

data
.title}</title>
</svelte:head>
<script>
	import { const page: Page<Record<string, string>, string | null>

A read-only reactive object with information about the current page, serving several use cases:

  • retrieving the combined data of all pages/layouts anywhere in your component tree (also see loading data)

  • retrieving the current value of the form prop anywhere in your component tree (also see form actions)

  • retrieving the page state that was set through goto, pushState or replaceState (also see goto and shallow routing)

  • retrieving metadata such as the URL you're on, the current route and its parameters, and whether or not there was an error

<!--- file: +layout.svelte --->
<script>
	import { page } from '$app/state';
</script>

<p>Currently at {page.url.pathname}</p>

{#if page.error}
	<span class="red">Problem detected</span>
{:else}
	<span class="small">All systems operational</span>
{/if}

Changes to page are available exclusively with runes. (The legacy reactivity syntax will not reflect any changes)

<!--- file: +page.svelte --->
<script>
	import { page } from '$app/state';
	const id = $derived(page.params.id); // This will correctly update id for usage on this page
	$: badId = page.params.id; // Do not use; will never update after initial load
</script>

On the server, values can only be read during rendering (in other words not in e.g. load functions). In the browser, the values can be read at any time.

page
} from '$app/state';
</script> <svelte:head> <title>{const page: Page<Record<string, string>, string | null>

A read-only reactive object with information about the current page, serving several use cases:

  • retrieving the combined data of all pages/layouts anywhere in your component tree (also see loading data)

  • retrieving the current value of the form prop anywhere in your component tree (also see form actions)

  • retrieving the page state that was set through goto, pushState or replaceState (also see goto and shallow routing)

  • retrieving metadata such as the URL you're on, the current route and its parameters, and whether or not there was an error

<!--- file: +layout.svelte --->
<script>
	import { page } from '$app/state';
</script>

<p>Currently at {page.url.pathname}</p>

{#if page.error}
	<span class="red">Problem detected</span>
{:else}
	<span class="small">All systems operational</span>
{/if}

Changes to page are available exclusively with runes. (The legacy reactivity syntax will not reflect any changes)

<!--- file: +page.svelte --->
<script>
	import { page } from '$app/state';
	const id = $derived(page.params.id); // This will correctly update id for usage on this page
	$: badId = page.params.id; // Do not use; will never update after initial load
</script>

On the server, values can only be read during rendering (in other words not in e.g. load functions). In the browser, the values can be read at any time.

page
.Page<Record<string, string>, string | null>.data: App.PageData & Record<string, any>

The merged result of all data from all load functions on the current page. You can type a common denominator through App.PageData.

data
.title}</title>
</svelte:head>

Type information for page.data is provided by App.PageData.

Legacy mode

$app/state was added in SvelteKit 2.12. If you’re using an earlier version or are using Svelte 4, use $app/stores instead. It provides a page store with the same interface that you can subscribe to, e.g. $page.data.title.

Universal vs server

As we’ve seen, there are two types of load function:

  • +page.js and +layout.js files export universal load functions that run both on the server and in the browser
  • +page.server.js and +layout.server.js files export server load functions that only run server-side

Conceptually, they’re the same thing, but there are some important differences to be aware of.

When does which load function run?

Server load functions always run on the server.

By default, universal load functions run on the server during SSR when the user first visits your page. They will then run again during hydration, reusing any responses from fetch requests. All subsequent invocations of universal load functions happen in the browser. You can customize the behavior through page options. If you disable server-side rendering, you’ll get an SPA and universal load functions always run on the client.

If a route contains both universal and server load functions, the server load runs first.

A load function is invoked at runtime, unless you prerender the page — in that case, it’s invoked at build time.

Input

Both universal and server load functions have access to properties describing the request (params, route and url) and various functions (fetch, setHeaders, parent, depends and untrack). These are described in the following sections.

Server load functions are called with a ServerLoadEvent, which inherits clientAddress, cookies, locals, platform and request from RequestEvent.

Universal load functions are called with a LoadEvent, which has a data property. If you have load functions in both +page.js and +page.server.js (or +layout.js and +layout.server.js), the return value of the server load function is the data property of the universal load function’s argument.

Output

A universal load function can return an object containing any values, including things like custom classes and component constructors.

A server load function must return data that can be serialized with devalue — anything that can be represented as JSON plus things like BigInt, Date, Map, Set and RegExp, or repeated/cyclical references — so that it can be transported over the network. Your data can include promises, in which case it will be streamed to browsers. If you need to serialize/deserialize custom types, use transport hooks.

When to use which

Server load functions are convenient when you need to access data directly from a database or filesystem, or need to use private environment variables.

Universal load functions are useful when you need to fetch data from an external API and don’t need private credentials, since SvelteKit can get the data directly from the API rather than going via your server. They are also useful when you need to return something that can’t be serialized, such as a Svelte component constructor.

In rare cases, you might need to use both together — for example, you might need to return an instance of a custom class that was initialised with data from your server. When using both, the server load return value is not passed directly to the page, but to the universal load function (as the data property):

import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types';

export const const load: PageServerLoadconst load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async () => {
	return {
		serverMessage: stringserverMessage: stringserverMessage: 'hello from server load function'
	};
};
/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
() {
return { serverMessage: stringserverMessage: stringserverMessage: 'hello from server load function' }; }
import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';
export const const load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = async ({ data: Record<string, any> | null

Contains the data returned by the route's server load function (in +layout.server.js or +page.server.js), if any.

data
}) => {
return { serverMessage: anyserverMessage: data.serverMessage,
'data' is possibly 'null'.
universalMessage: stringuniversalMessage: 'hello from universal load function' }; };
/** @type {import('./$types').PageLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({ data: Record<string, any> | null

Contains the data returned by the route's server load function (in +layout.server.js or +page.server.js), if any.

data
}) {
return { serverMessage: anyserverMessage: data.serverMessage,
'data' is possibly 'null'.
universalMessage: stringuniversalMessage: 'hello from universal load function' }; }

Using URL data

Often the load function depends on the URL in one way or another. For this, the load function provides you with url, route and params.

url

An instance of URL, containing properties like the origin, hostname, pathname and searchParams (which contains the parsed query string as a URLSearchParams object). url.hash cannot be accessed during load, since it is unavailable on the server.

In some environments this is derived from request headers during server-side rendering. If you’re using adapter-node, for example, you may need to configure the adapter in order for the URL to be correct.

route

Contains the name of the current route directory, relative to src/routes:

import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';

export const const load: PageLoadconst load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = ({ 
route: {
    id: string | null;
}

Info about the current route

route: {
    id: string | null;
}

Info about the current route

route
}) => {
var console: Consolevar console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(
route: {
    id: string | null;
}

Info about the current route

route: {
    id: string | null;
}

Info about the current route

route
.id: string | null

The ID of the current route - e.g. for src/routes/blog/[slug], it would be /blog/[slug]. It is null when no route is matched.

id: string | null

The ID of the current route - e.g. for src/routes/blog/[slug], it would be /blog/[slug]. It is null when no route is matched.

id
); // '/a/[b]/[...c]'
};
/** @type {import('./$types').PageLoad} */
export function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({
route: {
    id: string | null;
}

Info about the current route

route: {
    id: string | null;
}

Info about the current route

route
}) {
var console: Consolevar console: Consoleconsole.Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(
route: {
    id: string | null;
}

Info about the current route

route: {
    id: string | null;
}

Info about the current route

route
.id: string | null

The ID of the current route - e.g. for src/routes/blog/[slug], it would be /blog/[slug]. It is null when no route is matched.

id: string | null

The ID of the current route - e.g. for src/routes/blog/[slug], it would be /blog/[slug]. It is null when no route is matched.

id
); // '/a/[b]/[...c]'
}

params

params is derived from url.pathname and route.id.

Given a route.id of /a/[b]/[...c] and a url.pathname of /a/x/y/z, the params object would look like this:

{
	"b": "x",
	"c": "y/z"
}

Making fetch requests

To get data from an external API or a +server.js handler, you can use the provided fetch function, which behaves identically to the native fetch web API with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text, json and arrayBuffer methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders.
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request - if you received a warning in your browser console when using the browser fetch instead of the load fetch, this is why.
import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';

export const const load: PageLoadconst load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = async ({ 
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
}) => {
const const res: Responseconst res: Responseres = await fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(`/api/items/${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.id}`);
const const item: anyconst item: anyitem = await const res: Responseconst res: Responseres.Body.json(): Promise<any>Body.json(): Promise<any>json(); return { item: anyitem: anyitem }; };
/** @type {import('./$types').PageLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
}) {
const const res: Responseconst res: Responseres = await fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(`/api/items/${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.id}`);
const const item: anyconst item: anyitem = await const res: Responseconst res: Responseres.Body.json(): Promise<any>Body.json(): Promise<any>json(); return { item: anyitem: anyitem }; }

Cookies

A server load function can get and set cookies.

// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
getUser
(sessionid: string | undefinedsessionid: string | undefinedsessionid: string | undefined): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ name: stringname: stringname: string, avatar: stringavatar: stringavatar: string }>
} // @filename: index.ts // cut import * as module "$lib/server/database"db from '$lib/server/database'; import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
}) => {
const const sessionid: string | undefinedsessionid = cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get: (name: string, opts?: CookieParseOptions) => string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie@paramopts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options)
get
('sessionid');
return {
user: {
    name: string;
    avatar: string;
}
user
: await module "$lib/server/database"db.
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
getUser
(const sessionid: string | undefinedsessionid)
}; };
// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
getUser
(sessionid: string | undefinedsessionid: string | undefinedsessionid: string | undefined): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ name: stringname: stringname: string, avatar: stringavatar: stringavatar: string }>
} // @filename: index.js // cut import * as module "$lib/server/database"db from '$lib/server/database'; /** @type {import('./$types').LayoutServerLoad} */ export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ cookies: Cookies

Get or set cookies related to the current request

cookies
}) {
const const sessionid: string | undefinedsessionid = cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get: (name: string, opts?: CookieParseOptions) => string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie@paramopts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options)
get
('sessionid');
return {
user: {
    name: string;
    avatar: string;
}
user
: await module "$lib/server/database"db.
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
getUser
(const sessionid: string | undefinedsessionid)
}; }

Cookies will only be passed through the provided fetch function if the target host is the same as the SvelteKit application or a more specific subdomain of it.

For example, if SvelteKit is serving my.domain.com:

  • domain.com WILL NOT receive cookies
  • my.domain.com WILL receive cookies
  • api.domain.com WILL NOT receive cookies
  • sub.my.domain.com WILL receive cookies

Other cookies will not be passed when credentials: 'include' is set, because SvelteKit does not know which domain which cookie belongs to (the browser does not pass this information along), so it’s not safe to forward any of them. Use the handleFetch hook to work around it.

Headers

Both server and universal load functions have access to a setHeaders function that, when running on the server, can set headers for the response. (When running in the browser, setHeaders has no effect.) This is useful if you want the page to be cached, for example:

import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';
export const const load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = async ({ 
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, setHeaders: (headers: Record<string, string>) => void

If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:

/// file: src/routes/blog/+page.js
export async function load({ fetch, setHeaders }) {
	const url = `https://cms.example.com/articles.json`;
	const response = await fetch(url);

	setHeaders({
		age: response.headers.get('age'),
		'cache-control': response.headers.get('cache-control')
	});

	return response.json();
}

Setting the same header multiple times (even in separate load functions) is an error — you can only set a given header once.

You cannot add a set-cookie header with setHeaders — use the cookies API in a server-only load function instead.

setHeaders has no effect when a load function runs in the browser.

setHeaders
}) => {
const const url: "https://cms.example.com/products.json"url = `https://cms.example.com/products.json`; const const response: Responseresponse = await fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(const url: "https://cms.example.com/products.json"url); // Headers are only set during SSR, caching the page's HTML // for the same length of time as the underlying data. setHeaders: (headers: Record<string, string>) => void

If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:

/// file: src/routes/blog/+page.js
export async function load({ fetch, setHeaders }) {
	const url = `https://cms.example.com/articles.json`;
	const response = await fetch(url);

	setHeaders({
		age: response.headers.get('age'),
		'cache-control': response.headers.get('cache-control')
	});

	return response.json();
}

Setting the same header multiple times (even in separate load functions) is an error — you can only set a given header once.

You cannot add a set-cookie header with setHeaders — use the cookies API in a server-only load function instead.

setHeaders has no effect when a load function runs in the browser.

setHeaders
({
age: const response: Responseresponse.Response.headers: Headers

The headers read-only property of the Response interface contains the Headers object associated with the response.

MDN Reference

headers
.Headers.get(name: string): string | null

The get() method of the Headers interface returns a byte string of all the values of a header within a Headers object with a given name. If the requested header doesn't exist in the Headers object, it returns null.

MDN Reference

get
('age'),
Type 'string | null' is not assignable to type 'string'. Type 'null' is not assignable to type 'string'.
'cache-control': const response: Responseresponse.Response.headers: Headers

The headers read-only property of the Response interface contains the Headers object associated with the response.

MDN Reference

headers
.Headers.get(name: string): string | null

The get() method of the Headers interface returns a byte string of all the values of a header within a Headers object with a given name. If the requested header doesn't exist in the Headers object, it returns null.

MDN Reference

get
('cache-control')
Type 'string | null' is not assignable to type 'string'. Type 'null' is not assignable to type 'string'.
}); return const response: Responseresponse.Body.json(): Promise<any>json(); };
/** @type {import('./$types').PageLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, setHeaders: (headers: Record<string, string>) => void

If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:

/// file: src/routes/blog/+page.js
export async function load({ fetch, setHeaders }) {
	const url = `https://cms.example.com/articles.json`;
	const response = await fetch(url);

	setHeaders({
		age: response.headers.get('age'),
		'cache-control': response.headers.get('cache-control')
	});

	return response.json();
}

Setting the same header multiple times (even in separate load functions) is an error — you can only set a given header once.

You cannot add a set-cookie header with setHeaders — use the cookies API in a server-only load function instead.

setHeaders has no effect when a load function runs in the browser.

setHeaders
}) {
const const url: "https://cms.example.com/products.json"url = `https://cms.example.com/products.json`; const const response: Responseresponse = await fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(const url: "https://cms.example.com/products.json"url); // Headers are only set during SSR, caching the page's HTML // for the same length of time as the underlying data. setHeaders: (headers: Record<string, string>) => void

If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:

/// file: src/routes/blog/+page.js
export async function load({ fetch, setHeaders }) {
	const url = `https://cms.example.com/articles.json`;
	const response = await fetch(url);

	setHeaders({
		age: response.headers.get('age'),
		'cache-control': response.headers.get('cache-control')
	});

	return response.json();
}

Setting the same header multiple times (even in separate load functions) is an error — you can only set a given header once.

You cannot add a set-cookie header with setHeaders — use the cookies API in a server-only load function instead.

setHeaders has no effect when a load function runs in the browser.

setHeaders
({
age: const response: Responseresponse.Response.headers: Headers

The headers read-only property of the Response interface contains the Headers object associated with the response.

MDN Reference

headers
.Headers.get(name: string): string | null

The get() method of the Headers interface returns a byte string of all the values of a header within a Headers object with a given name. If the requested header doesn't exist in the Headers object, it returns null.

MDN Reference

get
('age'),
Type 'string | null' is not assignable to type 'string'. Type 'null' is not assignable to type 'string'.
'cache-control': const response: Responseresponse.Response.headers: Headers

The headers read-only property of the Response interface contains the Headers object associated with the response.

MDN Reference

headers
.Headers.get(name: string): string | null

The get() method of the Headers interface returns a byte string of all the values of a header within a Headers object with a given name. If the requested header doesn't exist in the Headers object, it returns null.

MDN Reference

get
('cache-control')
Type 'string | null' is not assignable to type 'string'. Type 'null' is not assignable to type 'string'.
}); return const response: Responseresponse.Body.json(): Promise<any>json(); }

Setting the same header multiple times (even in separate load functions) is an error. You can only set a given header once using the setHeaders function. You cannot add a set-cookie header with setHeaders — use cookies.set(name, value, options) instead.

Using parent data

Occasionally it’s useful for a load function to access data from a parent load function, which can be done with await parent():

import type { type LayoutLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type LayoutLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutLoad } from './$types';

export const const load: LayoutLoadconst load: LayoutLoadload: type LayoutLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type LayoutLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutLoad = () => {
	return { a: numbera: numbera: 1 };
};
/** @type {import('./$types').LayoutLoad} */
export function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutLoad}
function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutLoad}
load
() {
return { a: numbera: numbera: 1 }; }
import type { type LayoutLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type LayoutLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutLoad } from './$types';

export const const load: LayoutLoadconst load: LayoutLoadload: type LayoutLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type LayoutLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutLoad = async ({ parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) => {
const { const a: anyconst a: anya } = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { b: anyb: anyb: const a: anyconst a: anya + 1 }; };
/** @type {import('./$types').LayoutLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutLoad}
function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutLoad}
load
({ parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) {
const { const a: anyconst a: anya } = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { b: anyb: anyb: const a: anyconst a: anya + 1 }; }
import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';

export const const load: PageLoadconst load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = async ({ parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) => {
const { const a: anyconst a: anya, const b: anyconst b: anyb } = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { c: anyc: anyc: const a: anyconst a: anya + const b: anyconst b: anyb }; };
/** @type {import('./$types').PageLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({ parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) {
const { const a: anyconst a: anya, const b: anyconst b: anyb } = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { c: anyc: anyc: const a: anyconst a: anya + const b: anyconst b: anyb }; }
<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();
</script>

<!-- renders `1 + 2 = 3` -->
<p>{data.a} + {data.b} = {data.c}</p>
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();
</script>

<!-- renders `1 + 2 = 3` -->
<p>{data.a} + {data.b} = {data.c}</p>

Notice that the load function in +page.js receives the merged data from both layout load functions, not just the immediate parent.

Inside +page.server.js and +layout.server.js, parent returns data from parent +layout.server.js files.

In +page.js or +layout.js it will return data from parent +layout.js files. However, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will also return data from parent +layout.server.js files that are not ‘shadowed’ by a +layout.js file

Take care not to introduce waterfalls when using await parent(). Here, for example, getData(params) does not depend on the result of calling parent(), so we should call it first to avoid a delayed render.

import type { PageLoad } from './$types';
// @filename: ambient.d.ts
declare function getData(params: Record<string, string>): Promise<{ meta: any }>

// @filename: index.ts
// cut

export const load: PageLoad = async ({ params, parent }) => {
	const parentData = await parent();
	const data = await getData(params);
	const parentData = await parent();

	return {
		...data,
		meta: { ...parentData.meta, ...data.meta }
	};
};
// @filename: ambient.d.ts
declare function 
function getData(params: Record<string, string>): Promise<{
    meta: any;
}>
function getData(params: Record<string, string>): Promise<{
    meta: any;
}>
getData
(params: Record<string, string>params: Record<string, string>params: type Record<K extends keyof any, T> = { [P in K]: T; }

Construct a type with a set of properties K of type T

type Record<K extends keyof any, T> = { [P in K]: T; }

Construct a type with a set of properties K of type T

Record
<string, string>): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ meta: anymeta: anymeta: any }>
// @filename: index.js // cut /** @type {import('./$types').PageLoad} */ export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({ params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
, parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) {
const parentData = await parent(); const
const data: {
    meta: any;
}
data
= await
function getData(params: Record<string, string>): Promise<{
    meta: any;
}>
getData
(params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
);
const const parentData: Record<string, any>parentData = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files. Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { ...
const data: {
    meta: any;
}
data
,
meta: anymeta: { ...const parentData: Record<string, any>parentData.meta, ...
const data: {
    meta: any;
}
data
.meta: anymeta }
}; }

Errors

If an error is thrown during load, the nearest +error.svelte will be rendered. For expected errors, use the error helper from @sveltejs/kit to specify the HTTP status code and an optional message:

// @filename: ambient.d.ts
declare namespace App {
	interface interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

Locals
{
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
user
?: {
name: stringname: stringname: string; isAdmin: booleanisAdmin: booleanisAdmin: boolean; } } } // @filename: index.ts // cut import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.@throws{HttpError} This error instructs SvelteKit to initiate HTTP error handling.@throws{Error} If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = ({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) => {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
user
) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.@throws{HttpError} This error instructs SvelteKit to initiate HTTP error handling.@throws{Error} If the provided status is invalid (not between 400 and 599).
error
(401, 'not logged in');
} if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
}
user
.isAdmin: booleanisAdmin) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.@throws{HttpError} This error instructs SvelteKit to initiate HTTP error handling.@throws{Error} If the provided status is invalid (not between 400 and 599).
error
(403, 'not an admin');
} };
// @filename: ambient.d.ts
declare namespace App {
	interface interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

Locals
{
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
user
?: {
name: stringname: stringname: string; isAdmin: booleanisAdmin: booleanisAdmin: boolean; } } } // @filename: index.js // cut import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.@throws{HttpError} This error instructs SvelteKit to initiate HTTP error handling.@throws{Error} If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
/** @type {import('./$types').LayoutServerLoad} */ export function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
user
) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.@throws{HttpError} This error instructs SvelteKit to initiate HTTP error handling.@throws{Error} If the provided status is invalid (not between 400 and 599).
error
(401, 'not logged in');
} if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
}
user
.isAdmin: booleanisAdmin) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.@throws{HttpError} This error instructs SvelteKit to initiate HTTP error handling.@throws{Error} If the provided status is invalid (not between 400 and 599).
error
(403, 'not an admin');
} }

Calling error(...) will throw an exception, making it easy to stop execution from inside helper functions.

If an unexpected error is thrown, SvelteKit will invoke handleError and treat it as a 500 Internal Error.

[In SvelteKit 1.x](migrating-to-sveltekit-2#redirect-and-error-are-no-longer-thrown-by-you) you had to throw the error yourself

Redirects

To redirect users, use the redirect helper from @sveltejs/kit to specify the location to which they should be redirected alongside a 3xx status code. Like error(...), calling redirect(...) will throw an exception, making it easy to stop execution from inside helper functions.

// @filename: ambient.d.ts
declare namespace App {
	interface interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

Locals
{
App.Locals.user?: {
    name: string;
} | undefined
App.Locals.user?: {
    name: string;
} | undefined
user
?: {
name: stringname: stringname: string; } } } // @filename: index.ts // cut import { function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)

  • 307 Temporary Redirect: redirect will keep the request method

  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.@paramlocation The location to redirect to.@throws{Redirect} This error instructs SvelteKit to redirect to the specified location.@throws{Error} If the provided status is invalid or the location cannot be used as a header value.
redirect
} from '@sveltejs/kit';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = ({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) => {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
} | undefined
user
) {
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)

  • 307 Temporary Redirect: redirect will keep the request method

  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.@paramlocation The location to redirect to.@throws{Redirect} This error instructs SvelteKit to redirect to the specified location.@throws{Error} If the provided status is invalid or the location cannot be used as a header value.
redirect
(307, '/login');
} };
// @filename: ambient.d.ts
declare namespace App {
	interface interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

Locals
{
App.Locals.user?: {
    name: string;
} | undefined
App.Locals.user?: {
    name: string;
} | undefined
user
?: {
name: stringname: stringname: string; } } } // @filename: index.js // cut import { function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)

  • 307 Temporary Redirect: redirect will keep the request method

  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.@paramlocation The location to redirect to.@throws{Redirect} This error instructs SvelteKit to redirect to the specified location.@throws{Error} If the provided status is invalid or the location cannot be used as a header value.
redirect
} from '@sveltejs/kit';
/** @type {import('./$types').LayoutServerLoad} */ export function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
} | undefined
user
) {
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)

  • 307 Temporary Redirect: redirect will keep the request method

  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.@paramlocation The location to redirect to.@throws{Redirect} This error instructs SvelteKit to redirect to the specified location.@throws{Error} If the provided status is invalid or the location cannot be used as a header value.
redirect
(307, '/login');
} }

Don’t use redirect() inside a try {...} block, as the redirect will immediately trigger the catch statement.

In the browser, you can also navigate programmatically outside of a load function using goto from $app.navigation.

[In SvelteKit 1.x](migrating-to-sveltekit-2#redirect-and-error-are-no-longer-thrown-by-you) you had to throw the redirect yourself

Streaming with promises

When using a server load, promises will be streamed to the browser as they resolve. This is useful if you have slow, non-essential data, since you can start rendering the page before all the data is available:

import type { PageServerLoad } from './$types';
// @filename: ambient.d.ts
declare global {
	const loadPost: (slug: string) => Promise<{ title: string, content: string }>;
	const loadComments: (slug: string) => Promise<{ content: string }>;
}

export {};

// @filename: index.ts
// cut

export const load: PageServerLoad = async ({ params }) => {
	return {
		// make sure the `await` happens at the end, otherwise we
		// can't start loading comments until we've loaded the post
		comments: loadComments(params.slug),
		post: await loadPost(params.slug)
	};
};
// @filename: ambient.d.ts
declare global {
	const 
const loadPost: (slug: string) => Promise<{
    title: string;
    content: string;
}>
const loadPost: (slug: string) => Promise<{
    title: string;
    content: string;
}>
loadPost
: (slug: stringslug: stringslug: string) => interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ title: stringtitle: stringtitle: string, content: stringcontent: stringcontent: string }>;
const
const loadComments: (slug: string) => Promise<{
    content: string;
}>
const loadComments: (slug: string) => Promise<{
    content: string;
}>
loadComments
: (slug: stringslug: stringslug: string) => interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ content: stringcontent: stringcontent: string }>;
} export {}; // @filename: index.js // cut /** @type {import('./$types').PageServerLoad} */ export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
}) {
return { // make sure the `await` happens at the end, otherwise we // can't start loading comments until we've loaded the post
comments: Promise<{
    content: string;
}>
comments
:
const loadComments: (slug: string) => Promise<{
    content: string;
}>
loadComments
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
.slug),
post: {
    title: string;
    content: string;
}
post
: await
const loadPost: (slug: string) => Promise<{
    title: string;
    content: string;
}>
loadPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
.slug)
}; }

This is useful for creating skeleton loading states, for example:

<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

{#await data.comments}
	Loading comments...
{:then comments}
	{#each comments as comment}
		<p>{comment.content}</p>
	{/each}
{:catch error}
	<p>error loading comments: {error.message}</p>
{/await}
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

{#await data.comments}
	Loading comments...
{:then comments}
	{#each comments as comment}
		<p>{comment.content}</p>
	{/each}
{:catch error}
	<p>error loading comments: {error.message}</p>
{/await}

When streaming data, be careful to handle promise rejections correctly. More specifically, the server could crash with an “unhandled promise rejection” error if a lazy-loaded promise fails before rendering starts (at which point it’s caught) and isn’t handling the error in some way. When using SvelteKit’s fetch directly in the load function, SvelteKit will handle this case for you. For other promises, it is enough to attach a noop-catch to the promise to mark it as handled.

import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types';

export const const load: PageServerLoadconst load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = ({ 
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here.

fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here.

fetch
}) => {
const const ok_manual: Promise<never>const ok_manual: Promise<never>ok_manual = var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.@returnsA new rejected Promise.
PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.@returnsA new rejected Promise.
reject
();
const ok_manual: Promise<never>const ok_manual: Promise<never>ok_manual.Promise<never>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@paramonrejected The callback to execute when the Promise is rejected.@returnsA Promise for the completion of the callback.
Promise<never>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@paramonrejected The callback to execute when the Promise is rejected.@returnsA Promise for the completion of the callback.
catch
(() => {});
return { ok_manual: Promise<never>ok_manual: Promise<never>ok_manual, ok_fetch: Promise<Response>ok_fetch: Promise<Response>ok_fetch: fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch('/fetch/that/could/fail'), dangerous_unhandled: Promise<never>dangerous_unhandled: Promise<never>dangerous_unhandled: var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.@returnsA new rejected Promise.
PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.@returnsA new rejected Promise.
reject
()
}; };
/** @type {import('./$types').PageServerLoad} */
export function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here.

fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here.

fetch
}) {
const const ok_manual: Promise<never>const ok_manual: Promise<never>ok_manual = var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.@returnsA new rejected Promise.
PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.@returnsA new rejected Promise.
reject
();
const ok_manual: Promise<never>const ok_manual: Promise<never>ok_manual.Promise<never>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@paramonrejected The callback to execute when the Promise is rejected.@returnsA Promise for the completion of the callback.
Promise<never>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@paramonrejected The callback to execute when the Promise is rejected.@returnsA Promise for the completion of the callback.
catch
(() => {});
return { ok_manual: Promise<never>ok_manual: Promise<never>ok_manual, ok_fetch: Promise<Response>ok_fetch: Promise<Response>ok_fetch: fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch('/fetch/that/could/fail'), dangerous_unhandled: Promise<never>dangerous_unhandled: Promise<never>dangerous_unhandled: var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.@returnsA new rejected Promise.
PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.@returnsA new rejected Promise.
reject
()
}; }

On platforms that do not support streaming, such as AWS Lambda or Firebase, responses will be buffered. This means the page will only render once all promises resolve. If you are using a proxy (e.g. NGINX), make sure it does not buffer responses from the proxied server.

Streaming data will only work when JavaScript is enabled. You should avoid returning promises from a universal load function if the page is server rendered, as these are not streamed — instead, the promise is recreated when the function reruns in the browser.

The headers and status code of a response cannot be changed once the response has started streaming, therefore you cannot setHeaders or throw redirects inside a streamed promise.

[In SvelteKit 1.x](migrating-to-sveltekit-2#Top-level-promises-are-no-longer-awaited) top-level promises were automatically awaited, only nested promises were streamed.

Parallel loading

When rendering (or navigating to) a page, SvelteKit runs all load functions concurrently, avoiding a waterfall of requests. During client-side navigation, the result of calling multiple server load functions are grouped into a single response. Once all load functions have returned, the page is rendered.

Rerunning load functions

SvelteKit tracks the dependencies of each load function to avoid rerunning it unnecessarily during navigation.

For example, given a pair of load functions like these…

// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(slug: stringslug: stringslug: string): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ title: stringtitle: stringtitle: string, content: stringcontent: stringcontent: string }>
} // @filename: index.ts // cut import * as module "$lib/server/database"db from '$lib/server/database'; import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types'; export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async ({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
}) => {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
.slug)
}; };
// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(slug: stringslug: stringslug: string): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<{ title: stringtitle: stringtitle: string, content: stringcontent: stringcontent: string }>
} // @filename: index.js // cut import * as module "$lib/server/database"db from '$lib/server/database'; /** @type {import('./$types').PageServerLoad} */ export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
}) {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

params
.slug)
}; }
// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
(): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<interface Array<T>interface Array<T>Array<{ title: stringtitle: stringtitle: string, slug: stringslug: stringslug: string }>>
} // @filename: index.ts // cut import * as module "$lib/server/database"db from '$lib/server/database'; import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async () => { return {
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; };
// @filename: ambient.d.ts
declare module '$lib/server/database' {
	export function 
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
(): interface Promise<T>

Represents the completion of an asynchronous operation

interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<interface Array<T>interface Array<T>Array<{ title: stringtitle: stringtitle: string, slug: stringslug: stringslug: string }>>
} // @filename: index.js // cut import * as module "$lib/server/database"db from '$lib/server/database'; /** @type {import('./$types').LayoutServerLoad} */ export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
() {
return {
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; }

…the one in +page.server.js will rerun if we navigate from /blog/trying-the-raw-meat-diet to /blog/i-regret-my-choices because params.slug has changed. The one in +layout.server.js will not, because the data is still valid. In other words, we won’t call db.getPostSummaries() a second time.

A load function that calls await parent() will also rerun if a parent load function is rerun.

Dependency tracking does not apply after the load function has returned — for example, accessing params.x inside a nested promise will not cause the function to rerun when params.x changes. (Don’t worry, you’ll get a warning in development if you accidentally do this.) Instead, access the parameter in the main body of your load function.

Search parameters are tracked independently from the rest of the url. For example, accessing event.url.searchParams.get("x") inside a load function will make that load function re-run when navigating from ?x=1 to ?x=2, but not when navigating from ?x=1&y=1 to ?x=1&y=2.

Untracking dependencies

In rare cases, you may wish to exclude something from the dependency tracking mechanism. You can do this with the provided untrack function:

import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';

export const const load: PageLoadconst load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = async ({ untrack: <T>(fn: () => T) => T

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

/// file: src/routes/+page.server.js
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack: <T>(fn: () => T) => T

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

/// file: src/routes/+page.server.js
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack
, url: URL

The URL of the current page

url: URL

The URL of the current page

url
}) => {
// Untrack url.pathname so that path changes don't trigger a rerun if (untrack: <boolean>(fn: () => boolean) => boolean

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

/// file: src/routes/+page.server.js
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack: <boolean>(fn: () => boolean) => boolean

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

/// file: src/routes/+page.server.js
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack
(() => url: URL

The URL of the current page

url: URL

The URL of the current page

url
.URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.

MDN Reference

URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.

MDN Reference

pathname
=== '/')) {
return { message: stringmessage: stringmessage: 'Welcome!' }; } };
/** @type {import('./$types').PageLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({ untrack: <T>(fn: () => T) => T

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

/// file: src/routes/+page.server.js
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack: <T>(fn: () => T) => T

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

/// file: src/routes/+page.server.js
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack
, url: URL

The URL of the current page

url: URL

The URL of the current page

url
}) {
// Untrack url.pathname so that path changes don't trigger a rerun if (untrack: <boolean>(fn: () => boolean) => boolean

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

/// file: src/routes/+page.server.js
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack: <boolean>(fn: () => boolean) => boolean

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

/// file: src/routes/+page.server.js
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack
(() => url: URL

The URL of the current page

url: URL

The URL of the current page

url
.URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.

MDN Reference

URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.

MDN Reference

pathname
=== '/')) {
return { message: stringmessage: stringmessage: 'Welcome!' }; } }

Manual invalidation

You can also rerun load functions that apply to the current page using invalidate(url), which reruns all load functions that depend on url, and invalidateAll(), which reruns every load function. Server load functions will never automatically depend on a fetched url to avoid leaking secrets to the client.

A load function depends on url if it calls fetch(url) or depends(url). Note that url can be a custom identifier that starts with [a-z]::

import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';

export const const load: PageLoadconst load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = async ({ 
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won't need this, as fetch calls depends on your behalf — it's only necessary if you're using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

/// file: src/routes/+page.js
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
/// file: src/routes/+page.svelte
<script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
</script>

<p>{data.count}<p>
<button on:click={increase}>Increase Count</button>
depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won't need this, as fetch calls depends on your behalf — it's only necessary if you're using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

/// file: src/routes/+page.js
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
/// file: src/routes/+page.svelte
<script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
</script>

<p>{data.count}<p>
<button on:click={increase}>Increase Count</button>
depends
}) => {
// load reruns when `invalidate('https://api.example.com/random-number')` is called... const const response: Responseconst response: Responseresponse = await fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch('https://api.example.com/random-number'); // ...or when `invalidate('app:random')` is called depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won't need this, as fetch calls depends on your behalf — it's only necessary if you're using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

/// file: src/routes/+page.js
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
/// file: src/routes/+page.svelte
<script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
</script>

<p>{data.count}<p>
<button on:click={increase}>Increase Count</button>
depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won't need this, as fetch calls depends on your behalf — it's only necessary if you're using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

/// file: src/routes/+page.js
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
/// file: src/routes/+page.svelte
<script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
</script>

<p>{data.count}<p>
<button on:click={increase}>Increase Count</button>
depends
('app:random');
return { number: anynumber: anynumber: await const response: Responseconst response: Responseresponse.Body.json(): Promise<any>Body.json(): Promise<any>json() }; };
/** @type {import('./$types').PageLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.

  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).

  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.

  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders

  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won't need this, as fetch calls depends on your behalf — it's only necessary if you're using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

/// file: src/routes/+page.js
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
/// file: src/routes/+page.svelte
<script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
</script>

<p>{data.count}<p>
<button on:click={increase}>Increase Count</button>
depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won't need this, as fetch calls depends on your behalf — it's only necessary if you're using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

/// file: src/routes/+page.js
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
/// file: src/routes/+page.svelte
<script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
</script>

<p>{data.count}<p>
<button on:click={increase}>Increase Count</button>
depends
}) {
// load reruns when `invalidate('https://api.example.com/random-number')` is called... const const response: Responseconst response: Responseresponse = await fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch('https://api.example.com/random-number'); // ...or when `invalidate('app:random')` is called depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won't need this, as fetch calls depends on your behalf — it's only necessary if you're using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

/// file: src/routes/+page.js
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
/// file: src/routes/+page.svelte
<script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
</script>

<p>{data.count}<p>
<button on:click={increase}>Increase Count</button>
depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won't need this, as fetch calls depends on your behalf — it's only necessary if you're using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

/// file: src/routes/+page.js
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
/// file: src/routes/+page.svelte
<script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
</script>

<p>{data.count}<p>
<button on:click={increase}>Increase Count</button>
depends
('app:random');
return { number: anynumber: anynumber: await const response: Responseconst response: Responseresponse.Body.json(): Promise<any>Body.json(): Promise<any>json() }; }
<script lang="ts">
	import { invalidate, invalidateAll } from '$app/navigation';
	import type { PageProps } from './$types';
	let { data }: PageProps = $props();

	function rerunLoadFunction() {
		// any of these will cause the `load` function to rerun
		invalidate('app:random');
		invalidate('https://api.example.com/random-number');
		invalidate(url => url.href.includes('random-number'));
		invalidateAll();
	}
</script>

<p>random number: {data.number}</p>
<button onclick={rerunLoadFunction}>Update random number</button>
<script>
	import { invalidate, invalidateAll } from '$app/navigation';

	/** @type {import('./$types').PageProps} */
	let { data } = $props();

	function rerunLoadFunction() {
		// any of these will cause the `load` function to rerun
		invalidate('app:random');
		invalidate('https://api.example.com/random-number');
		invalidate(url => url.href.includes('random-number'));
		invalidateAll();
	}
</script>

<p>random number: {data.number}</p>
<button onclick={rerunLoadFunction}>Update random number</button>

When do load functions rerun?

To summarize, a load function will rerun in the following situations:

  • It references a property of params whose value has changed
  • It references a property of url (such as url.pathname or url.search) whose value has changed. Properties in request.url are not tracked
  • It calls url.searchParams.get(...), url.searchParams.getAll(...) or url.searchParams.has(...) and the parameter in question changes. Accessing other properties of url.searchParams will have the same effect as accessing url.search.
  • It calls await parent() and a parent load function reran
  • A child load function calls await parent() and is rerunning, and the parent is a server load function
  • It declared a dependency on a specific URL via fetch (universal load only) or depends, and that URL was marked invalid with invalidate(url)
  • All active load functions were forcibly rerun with invalidateAll()

params and url can change in response to a <a href=".."> link click, a <form> interaction, a goto invocation, or a redirect.

Note that rerunning a load function will update the data prop inside the corresponding +layout.svelte or +page.svelte; it does not cause the component to be recreated. As a result, internal state is preserved. If this isn’t what you want, you can reset whatever you need to reset inside an afterNavigate callback, and/or wrap your component in a {#key ...} block.

Implications for authentication

A couple features of loading data have important implications for auth checks:

  • Layout load functions do not run on every request, such as during client side navigation between child routes. (When do load functions rerun?)
  • Layout and page load functions run concurrently unless await parent() is called. If a layout load throws, the page load function runs, but the client will not receive the returned data.

There are a few possible strategies to ensure an auth check occurs before protected code.

To prevent data waterfalls and preserve layout load caches:

  • Use hooks to protect multiple routes before any load functions run
  • Use auth guards directly in +page.server.js load functions for route specific protection

Putting an auth guard in +layout.server.js requires all child pages to call await parent() before protected code. Unless every child page depends on returned data from await parent(), the other options will be more performant.

Using getRequestEvent

When running server load functions, the event object passed to the function as an argument can also be retrieved with getRequestEvent. This allows shared logic (such as authentication guards) to access information about the current request without it needing to be passed around.

For example, you might have a function that requires users to be logged in, and redirects them to /login if not:

// @filename: ambient.d.ts
interface User {
	User.name: stringUser.name: stringname: string;
}

declare namespace App {
	interface interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

interface App.Locals

The interface that defines event.locals, which can be accessed in server hooks (handle, and handleError), server-only load functions, and +server.js files.

Locals
{
App.Locals.user?: User | undefinedApp.Locals.user?: User | undefineduser?: User; } } // @filename: index.ts // cut import { function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)

  • 307 Temporary Redirect: redirect will keep the request method

  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.@paramlocation The location to redirect to.@throws{Redirect} This error instructs SvelteKit to redirect to the specified location.@throws{Error} If the provided status is invalid or the location cannot be used as a header value.
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)

  • 307 Temporary Redirect: redirect will keep the request method

  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.@paramlocation The location to redirect to.@throws{Redirect} This error instructs SvelteKit to redirect to the specified location.@throws{Error} If the provided status is invalid or the location cannot be used as a header value.
redirect
} from '@sveltejs/kit';
import { function getRequestEvent(): RequestEvent

Returns the current RequestEvent. Can be used inside server hooks, server load functions, actions, and endpoints (and functions called by them).

In environments without AsyncLocalStorage, this must be called synchronously (i.e. not after an await).

@since2.20.0
function getRequestEvent(): RequestEvent

Returns the current RequestEvent. Can be used inside server hooks, server load functions, actions, and endpoints (and functions called by them).

In environments without AsyncLocalStorage, this must be called synchronously (i.e. not after an await).

@since2.20.0
getRequestEvent
} from '$app/server';
export function function requireLogin(): Userfunction requireLogin(): UserrequireLogin() { const { const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
, const url: URL

The requested URL.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

const url: URL

The requested URL.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

url
} = function getRequestEvent(): RequestEvent

Returns the current RequestEvent. Can be used inside server hooks, server load functions, actions, and endpoints (and functions called by them).

In environments without AsyncLocalStorage, this must be called synchronously (i.e. not after an await).

@since2.20.0
function getRequestEvent(): RequestEvent

Returns the current RequestEvent. Can be used inside server hooks, server load functions, actions, and endpoints (and functions called by them).

In environments without AsyncLocalStorage, this must be called synchronously (i.e. not after an await).

@since2.20.0
getRequestEvent
();
// assume `locals.user` is populated in `handle` if (!const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.App.Locals.user?: User | undefinedApp.Locals.user?: User | undefineduser) {
const const redirectTo: stringconst redirectTo: stringredirectTo = const url: URL

The requested URL.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

const url: URL

The requested URL.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

url
.URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.

MDN Reference

URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.

MDN Reference

pathname
+ const url: URL

The requested URL.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

const url: URL

The requested URL.

In the context of a remote function request initiated by the client, this relates to the page the remote function was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.

url
.URL.search: string

The search property of the URL interface is a search string, also called a query string, that is a string containing a "?" followed by the parameters of the URL. If the URL does not have a search query, this property contains an empty string, "".

MDN Reference

URL.search: string

The search property of the URL interface is a search string, also called a query string, that is a string containing a "?" followed by the parameters of the URL. If the URL does not have a search query, this property contains an empty string, "".

MDN Reference

search
;
const const params: URLSearchParamsconst params: URLSearchParamsparams = new var URLSearchParams: new (init?: string[][] | Record<string, string> | string | URLSearchParams) => URLSearchParams

The URLSearchParams interface defines utility methods to work with the query string of a URL.

MDN Reference

var URLSearchParams: new (init?: string[][] | Record<string, string> | string | URLSearchParams) => URLSearchParams

The URLSearchParams interface defines utility methods to work with the query string of a URL.

MDN Reference

URLSearchParams
({ redirectTo: stringredirectTo: stringredirectTo });
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)

  • 307 Temporary Redirect: redirect will keep the request method

  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.@paramlocation The location to redirect to.@throws{Redirect} This error instructs SvelteKit to redirect to the specified location.@throws{Error} If the provided status is invalid or the location cannot be used as a header value.
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)

  • 307 Temporary Redirect: redirect will keep the request method

  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.@paramlocation The location to redirect to.@throws{Redirect} This error instructs SvelteKit to redirect to the specified location.@throws{Error} If the provided status is invalid or the location cannot be used as a header value.
redirect
(303, `/login?${const params: URLSearchParamsconst params: URLSearchParamsparams}`);
} return const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.App.Locals.user?: UserApp.Locals.user?: Useruser;
}

Now, you can call requireLogin in any load function (or form action, for example) to guarantee that the user is logged in:

// @filename: ambient.d.ts

declare module '$lib/server/auth' {
	interface User {
		User.name: stringUser.name: stringname: string;
	}

	export function function requireLogin(): Userfunction requireLogin(): UserrequireLogin(): User;
}

// @filename: index.ts
// cut
import { function requireLogin(): Userfunction requireLogin(): UserrequireLogin } from '$lib/server/auth';

export function 
function load(): {
    message: string;
}
function load(): {
    message: string;
}
load
() {
const const user: Userconst user: Useruser = function requireLogin(): Userfunction requireLogin(): UserrequireLogin(); // `user` is guaranteed to be a user object here, because otherwise // `requireLogin` would throw a redirect and we wouldn't get here return { message: stringmessage: stringmessage: `hello ${const user: Userconst user: Useruser.User.name: stringUser.name: stringname}!` }; }

Further reading