Harness-engineering svelte-load-functions

Svelte Load Functions

install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/svelte-load-functions" ~/.claude/skills/intense-visions-harness-engineering-svelte-load-functions && rm -rf "$T"
manifest: agents/skills/claude-code/svelte-load-functions/SKILL.md
source content

Svelte Load Functions

Fetch route data before rendering using SvelteKit's load functions — server-only, universal, streaming, and invalidation patterns

When to Use

  • You need to fetch data before a page renders (and show it server-side)
  • You are choosing between
    +page.ts
    (universal) and
    +page.server.ts
    (server-only)
  • You need access to database clients, cookies, or session data in your load function
  • You want to stream slow data to the browser without blocking the initial render
  • You need to invalidate and re-fetch data after a form action or user interaction

Instructions

Server load (+page.server.ts):

  1. Use
    +page.server.ts
    when you need secrets, database access, cookies, or server-only APIs. This function never runs in the browser:
// src/routes/users/[id]/+page.server.ts
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ params, locals, cookies }) => {
  const user = await locals.db.user.findUnique({
    where: { id: params.id },
  });

  if (!user) throw error(404, 'User not found');

  return { user };
};
  1. Access the authenticated session via
    locals
    (set in
    hooks.server.ts
    ):
export const load: PageServerLoad = async ({ locals }) => {
  if (!locals.user) redirect(303, '/login');
  return { user: locals.user };
};

Universal load (+page.ts):

  1. Use
    +page.ts
    for load functions that can run on both server (initial request) and client (navigation). Use the provided
    fetch
    — it is enhanced by SvelteKit for deduplication and credentials:
// src/routes/posts/+page.ts
import type { PageLoad } from './$types';

export const load: PageLoad = async ({ fetch, params }) => {
  const res = await fetch(`/api/posts?page=${params.page ?? 1}`);
  const posts = await res.json();
  return { posts };
};

Accessing load data in the page:

  1. Receive
    data
    as a prop (Svelte 5 with
    $props
    ) or as
    export let data
    (Svelte 4):
<!-- +page.svelte -->
<script lang="ts">
  import type { PageData } from './$types'
  let { data }: { data: PageData } = $props()
</script>

{#each data.posts as post}
  <article>{post.title}</article>
{/each}

Error handling:

  1. Throw
    error
    or
    redirect
    from
    @sveltejs/kit
    to trigger the error page or redirect:
import { error, redirect } from '@sveltejs/kit';

export const load: PageServerLoad = async ({ params }) => {
  const post = await getPost(params.slug);
  if (!post) throw error(404, { message: 'Post not found' });
  if (post.status === 'draft') redirect(303, '/');
  return { post };
};

Layout loads:

  1. Add a
    +layout.server.ts
    to provide data to all pages in a route segment. Layout data is merged with page data:
// src/routes/(app)/+layout.server.ts
export const load: LayoutServerLoad = async ({ locals }) => {
  return { currentUser: locals.user };
};

Streaming with promises:

  1. Return a promise for slow data to stream it to the client without blocking the initial render. Wrap the slow part in
    {#await}
    :
// +page.server.ts
export const load: PageServerLoad = async ({ params }) => {
  // fast — included in initial HTML
  const product = await getProduct(params.id);

  // slow — streamed after initial render
  const reviews = getReviews(params.id); // not awaited

  return { product, reviews };
};
<!-- +page.svelte -->
{#await data.reviews}
  <p>Loading reviews...</p>
{:then reviews}
  {#each reviews as review}<Review {review} />{/each}
{/await}

Invalidation:

  1. Use
    depends('app:tag')
    to declare a custom dependency; call
    invalidate('app:tag')
    to re-run the load function:
// load function
export const load: PageLoad = async ({ fetch, depends }) => {
  depends('app:cart');
  const cart = await fetch('/api/cart').then((r) => r.json());
  return { cart };
};

// After updating cart:
import { invalidate } from '$app/navigation';
await invalidate('app:cart');
  1. Use
    invalidateAll()
    to re-run all load functions on the current page.

Details

Server vs. universal load — decision matrix:

NeedUse
Database access
+page.server.ts
Cookies / session
+page.server.ts
Secret env vars
+page.server.ts
Works without JS
+page.server.ts
Runs on CDN edge
+page.ts
Client-side navigation data
+page.ts
Public API, no secretsEither

Data merging:

When a route has both

+layout.server.ts
and
+page.server.ts
, SvelteKit merges the returned data. If both return a key with the same name, the page-level value wins.

Type generation:

SvelteKit generates types for

PageData
,
PageServerLoad
,
LayoutLoad
, and
LayoutServerLoad
in
.svelte-kit/types/
. Always import from
./$types
to get the correct inferred types.

The

parent
function:

Load functions can await parent layout data via

parent()
:

export const load: PageLoad = async ({ parent }) => {
  const { user } = await parent();
  return { greeting: `Hello, ${user.name}` };
};

Fetch in load vs. $fetch:

Always use the

fetch
provided by SvelteKit's load function — it:

  • Includes credentials (cookies) when fetching same-origin
  • Deduplicates identical requests within the same render cycle
  • Works correctly on both server and client

Do not use the global

fetch
directly inside load functions.

Source

https://kit.svelte.dev/docs/load

Process

  1. Read the instructions and examples in this document.
  2. Apply the patterns to your implementation, adapting to your specific context.
  3. Verify your implementation against the details and edge cases listed above.

Harness Integration

  • Type: knowledge — this skill is a reference document, not a procedural workflow.
  • No tools or state — consumed as context by other skills and agents.

Success Criteria

  • The patterns described in this document are applied correctly in the implementation.
  • Edge cases and anti-patterns listed in this document are avoided.