skills/spences10/skills/sveltekit-remote-functions

sveltekit-remote-functions

Installation
SKILL.md

SvelteKit Remote Functions

Current Status

Remote functions are experimental in SvelteKit 2.58. Enable them in svelte.config.js:

export default {
	kit: { experimental: { remoteFunctions: true } },
	compilerOptions: { experimental: { async: true } } // only for await in components
};

Quick Start

File naming: export remote functions from *.remote.ts or *.remote.js. Remote files can live anywhere under src except src/lib/server.

Which function?

  • Dynamic reads → query()
  • Progressive forms → form()
  • Event-handler mutations → command()
  • Build-time/static reads → prerender()

Example

// posts.remote.ts
import { command, query, requested } from '$app/server';
import * as v from 'valibot';

export const getPosts = query(v.object({ tag: v.optional(v.string()) }), async (filter) => {
	return db.posts.find(filter);
});

export const createPost = command(v.object({ title: v.string() }), async (data) => {
	await db.posts.create(data);

	for (const { query } of requested(getPosts, 5)) {
		void query.refresh();
	}
});

Client:

<script lang="ts">
	import { createPost, getPosts } from './posts.remote';

	const posts = $derived(await getPosts({ tag: 'svelte' }));
</script>

<button onclick={() => createPost({ title: 'New' }).updates(getPosts)}>
	Create
</button>

Current Rules

  • Remote functions always run on the server, even when called from the browser.
  • Args/returns use devalue; avoid functions, class instances, symbols, circular refs, and RegExp.
  • Validate exposed inputs with Standard Schema (valibot, zod, arktype, etc.) or use .unchecked/'unchecked' deliberately.
  • query.batch() batches calls from the same macrotask to solve n+1 reads.
  • form().enhance() submit() returns true when submission is valid/successful and false for validation failures.
  • .updates() is client-requested; server handlers must opt in with requested(queryFn, limit).
  • requested() now yields { arg, query }; call query.refresh()/query.set(...) on the bound instance.
  • limit is required for requested() to cap client-controlled refresh requests.
  • Inside command/form handlers, use void query.refresh()/void query.set(value); SvelteKit awaits and serializes the updates.
  • Prefer form() over command() where progressive enhancement matters.
  • Use prerender() for data that changes at most once per deployment.
  • Last verified: SvelteKit 2.58.0, 2026-04-24

Reference Files

Weekly Installs
2
First Seen
Today