Svelte logo

SvelteKit by Example: Page Scripts

Page scripts fetch or prepare data before the page component is rendered. A +page.js load function is universal: by default, it runs on the server for the first render, then again in the browser during hydration. Later client-side navigation runs it in the browser when its data needs to be loaded again.

For prerendered pages, the initial server run happens at build time. Use the fetch provided by SvelteKit so hydration can reuse responses from the initial render without another network request.

In this example, we'll pass an array of todos retrieved from an API to a page component.

Export a load function from +page.js to prepare data. Here, /api/lists stands for your own JSON API, returning an array of lists with id and name fields.

src/routes/lists/+page.js
/** @type {import('./$types').PageLoad} */
export async function load({ fetch }) {
  const response = await fetch('/api/lists');

  return {
    lists: await response.json(),
  };
}

The returned data is passed to the page's data prop.

src/routes/lists/+page.svelte
<script>
  let { data } = $props();
</script>

<h1>Lists</h1>
<ul>
  {#each data.lists as list}
    <li>
      <a href={`/lists/${list.id}`}>
        {list.name}
      </a>
    </li>
  {/each}
</ul>

The load function receives a context argument to access route parameters and other data. Here, pages.json is your own array of pages with a slug field.

error stops loading and sets an HTTP error status. It throws for you, so there's no need to write throw error(...).

src/routes/[page]/+page.js
import pages from "./pages.json";
import { error } from '@sveltejs/kit';

export function load({ params }) {
  const page = pages
    .find((page) => page.slug === params.page);




  if (! page) {
    error(404, 'Page not found');
  }

  return { page };
}

The load function can be typed with JSDoc. SvelteKit generates the route's types in ./$types.

/** @type {import('./$types').PageLoad} */
export function load({ params }) {
  // …
}

In TypeScript, type the function with PageLoad, not its context argument.

src/routes/[page]/+page.ts
import type { PageLoad } from './$types';

export const load: PageLoad = ({ params }) => {
  // …
};

Use PageProps to type the page's props with JSDoc.

src/routes/[page]/+page.svelte
<script>
  /** @type {import('./$types').PageProps} */
  let { data } = $props();
</script>

Or use TypeScript in the page component.

src/routes/[page]/+page.svelte
<script lang="ts">
  import type { PageProps } from './$types';

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