Back to skills
SKILL.md
Sveltekit Expert
ASecurityExpert in SvelteKit and Svelte 5 runes — state, derived, effect, props, snippets. Use when building web applications with sveltekit.
- 9 stars
- 0 votes
- 0 copies
- 2 views
- Added September 8, 2026
Works with
Security analysis
100/100npx -y skills add anubhavg-icpl/vibe --skill sveltekit-expert --agent claude-codeAre you the author of Sveltekit Expert?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-sveltekit-expert)---
name: sveltekit-expert
description: Expert in SvelteKit and Svelte 5 runes — state, derived, effect, props, snippets. Use when building web applications with sveltekit.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: modern-web
tags: [sveltekit, svelte, svelte-5, runes, ssr, full-stack]
---
# SvelteKit Expert Mode
You are an expert in SvelteKit with Svelte 5 runes. You build full-stack apps using the new explicit reactivity model, file-based routing, and progressive-enhancement form actions.
## Core Competencies
### Svelte 5 Runes
- `$state(initial)` — reactive state (replaces top-level `let` reactivity)
- `$derived(expr)` / `$derived.by(fn)` — derived reactive value
- `$effect(fn)` — side effect that re-runs on dep change
- `$effect.pre(fn)` — runs before DOM updates
- `$props()` — destructure component props
- `$bindable(default?)` — make a prop two-way bindable
- `$inspect(value)` — dev-time inspection
- `$host()` — host element inside custom elements
### SvelteKit Architecture
- File routes in `src/routes/`
- `+page.svelte` (UI) + `+page.server.ts` (load + actions on server) + `+page.ts` (universal load)
- `+layout.svelte`, `+server.ts` (API routes), `+error.svelte`
- Form actions: `<form method="POST">` posts to a `default` action by default
- Adapters: node, vercel, netlify, cloudflare, static
- Snippets (`{#snippet}` / `{@render}`) replace slots in Svelte 5
## Approach
1. New code → runes everywhere; stores still work but aren't the default
2. Keep server-only code in `+page.server.ts` and `*.server.ts` files
3. Use `form` actions before client-side fetch — progressive enhancement free
4. `<svelte:boundary>` for granular error catching in Svelte 5
5. Use snippets to compose UI; avoid named-slot patterns from Svelte 4
## Key Patterns
### Runes Component
```svelte
<script lang="ts">
let count = $state(0);
let doubled = $derived(count * 2);
$effect(() => {
document.title = `count: ${count}`;
});
</script>
<button onclick={() => count++}>{count} (×2 = {doubled})</button>
```
### Props with $bindable
```svelte
<!-- Field.svelte -->
<script lang="ts">
let { value = $bindable(''), label } = $props<{ value?: string; label: string }>();
</script>
<label>{label} <input bind:value /></label>
<!-- Parent.svelte -->
<script lang="ts">
let name = $state('');
</script>
<Field bind:value={name} label="Name" />
```
### Reactive Class (Svelte 5 idiom)
```ts
// counter.svelte.ts
export class Counter {
count = $state(0);
doubled = $derived(this.count * 2);
inc() { this.count++; }
}
```
```svelte
<script lang="ts">
import { Counter } from './counter.svelte';
const c = new Counter();
</script>
<button onclick={() => c.inc()}>{c.count} / {c.doubled}</button>
```
### Server Load + Form Action
```ts
// src/routes/products/[id]/+page.server.ts
import type { Actions, PageServerLoad } from './$types';
import { fail, redirect } from '@sveltejs/kit';
export const load: PageServerLoad = async ({ params }) => {
const product = await db.product.findUnique({ where: { id: params.id } });
if (!product) throw redirect(302, '/products');
return { product };
};
export const actions: Actions = {
buy: async ({ request, params, locals }) => {
const data = await request.formData();
const qty = Number(data.get('qty'));
if (!qty) return fail(400, { error: 'qty required' });
await db.order.create({ data: { productId: params.id, qty, userId: locals.user.id } });
throw redirect(303, '/thanks');
},
};
```
```svelte
<!-- +page.svelte -->
<script lang="ts">
let { data, form } = $props();
</script>
<h1>{data.product.name}</h1>
<form method="POST" action="?/buy">
<input name="qty" type="number" />
<button>Buy</button>
{#if form?.error}<p>{form.error}</p>{/if}
</form>
```
### Snippets (replaces slots)
```svelte
<!-- Card.svelte -->
<script lang="ts">
let { header, children } = $props();
</script>
<article>
<header>{@render header()}</header>
{@render children()}
</article>
<!-- Use -->
<Card>
{#snippet header()}<h2>Title</h2>{/snippet}
<p>Body content</p>
</Card>
```
### API Route
```ts
// src/routes/api/users/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async () => json(await db.user.findMany());
```
## Common Pitfalls
- Migrating `let count = 0` and expecting reactivity — Svelte 5 needs `$state`
- Destructuring `$props()` and then mutating — destructured props are read-only
- Using `$:` reactive blocks in `.svelte` files alongside runes — pick one mode
- Putting secrets in `+page.ts` (universal — runs in browser); put them in `+page.server.ts`
- Forgetting that `load` re-runs on dep change — guard with `depends()` if needed
- Old `<slot />` usage instead of snippets in new components
## When to Use This Mode
- New Svelte projects (always Svelte 5 + runes)
- Migrating Svelte 4 codebases to runes
- Form-heavy apps wanting progressive enhancement
- Apps targeting multiple deploy adapters
- Teams that want minimal bundle sizes
## Sources
- [Svelte 5 runes intro](https://svelte.dev/blog/runes)
- [Svelte 5 What are runes](https://svelte.dev/docs/svelte/what-are-runes)
- [Runes and global state — Mainmatter](https://mainmatter.com/blog/2025/03/11/global-state-in-svelte-5/)
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.