svelte
Svelte 5 - Reactive UI framework with compiler magic, Runes API, SvelteKit full-stack framework, SSR/SSG, minimal JavaScript
What this skill does
# Svelte 5 - Compiler-First Reactive Framework
## Overview
Svelte is a **compiler-based** reactive UI framework that shifts work from runtime to build time. Unlike React/Vue, Svelte compiles components to highly optimized vanilla JavaScript with minimal overhead. **Svelte 5** introduces Runes API for explicit, fine-grained reactivity.
**Key Features**:
- **Runes API**: $state, $derived, $effect for explicit reactivity
- **Zero runtime overhead**: Compiles to vanilla JS
- **Built-in state management**: No external libraries needed
- **SvelteKit**: Full-stack framework with SSR/SSG/SPA
- **Write less code**: Simple, readable component syntax
- **Exceptional performance**: Small bundles, fast runtime
**Installation**:
```bash
# Create new SvelteKit project
npm create svelte@latest my-app
cd my-app
npm install
npm run dev
# Or Svelte only (no SvelteKit)
npm create vite@latest my-app -- --template svelte-ts
```
## Svelte 5 Runes API (Modern Approach)
### State Management with $state
```svelte
<script lang="ts">
// Reactive state - automatically tracks changes
let count = $state(0);
let user = $state({ name: 'Alice', age: 30 });
// Arrays and objects are deeply reactive
let todos = $state<Todo[]>([]);
function addTodo(text: string) {
todos.push({ id: Date.now(), text, done: false });
// No need for todos = [...todos] like React!
}
function increment() {
count++; // Triggers reactivity
}
</script>
<button onclick={increment}>
Clicked {count} times
</button>
```
### Computed Values with $derived
```svelte
<script lang="ts">
let firstName = $state('John');
let lastName = $state('Doe');
// Automatically updates when dependencies change
let fullName = $derived(`${firstName} ${lastName}`);
let greeting = $derived(`Hello, ${fullName}`);
// Complex derivations
let items = $state([1, 2, 3, 4, 5]);
let total = $derived(items.reduce((sum, n) => sum + n, 0));
let average = $derived(total / items.length);
</script>
<p>{greeting}</p>
<p>Average: {average.toFixed(2)}</p>
```
### Side Effects with $effect
```svelte
<script lang="ts">
let count = $state(0);
let logs = $state<string[]>([]);
// Runs when dependencies change
$effect(() => {
console.log(`Count is now: ${count}`);
logs.push(`Count changed to ${count}`);
// Optional cleanup function
return () => {
console.log('Cleaning up previous effect');
};
});
// Effect with external subscriptions
$effect(() => {
const interval = setInterval(() => {
count++;
}, 1000);
return () => clearInterval(interval);
});
</script>
```
### Component Props with $props
```svelte
<script lang="ts">
interface Props {
title: string;
count?: number;
onUpdate?: (value: number) => void;
}
// Type-safe props with defaults
let { title, count = 0, onUpdate } = $props<Props>();
// Props are read-only, but can derive from them
let displayTitle = $derived(title.toUpperCase());
</script>
<h1>{displayTitle}</h1>
<p>Count: {count}</p>
<button onclick={() => onUpdate?.(count + 1)}>
Increment
</button>
```
### Two-Way Binding with $bindable
```svelte
<!-- Child: SearchInput.svelte -->
<script lang="ts">
interface Props {
value: string;
placeholder?: string;
}
// Allows parent to bind to this prop
let { value = $bindable(''), placeholder = 'Search...' } = $props<Props>();
</script>
<input bind:value {placeholder} type="search" />
<!-- Parent.svelte -->
<script lang="ts">
import SearchInput from './SearchInput.svelte';
let query = $state('');
let results = $derived(query ? search(query) : []);
</script>
<SearchInput bind:value={query} />
<p>Found {results.length} results for "{query}"</p>
```
## Component Patterns
### Basic Component Structure
```svelte
<!-- Counter.svelte -->
<script lang="ts">
let count = $state(0);
let doubled = $derived(count * 2);
function increment() {
count++;
}
function decrement() {
count--;
}
</script>
<div class="counter">
<button onclick={decrement}>-</button>
<span>Count: {count} (Doubled: {doubled})</span>
<button onclick={increment}>+</button>
</div>
<style>
.counter {
display: flex;
gap: 1rem;
align-items: center;
}
button {
padding: 0.5rem 1rem;
font-size: 1.2rem;
}
</style>
```
### Conditional Rendering
```svelte
<script lang="ts">
let loggedIn = $state(false);
let user = $state<User | null>(null);
let loading = $state(true);
</script>
{#if loading}
<p>Loading...</p>
{:else if loggedIn && user}
<p>Welcome, {user.name}!</p>
{:else}
<p>Please log in</p>
{/if}
```
### Lists and Keyed Each Blocks
```svelte
<script lang="ts">
interface Todo {
id: number;
text: string;
done: boolean;
}
let todos = $state<Todo[]>([
{ id: 1, text: 'Learn Svelte', done: true },
{ id: 2, text: 'Build app', done: false }
]);
function toggle(id: number) {
const todo = todos.find(t => t.id === id);
if (todo) todo.done = !todo.done;
}
</script>
<ul>
{#each todos as todo (todo.id)}
<li class:done={todo.done}>
<input
type="checkbox"
checked={todo.done}
onchange={() => toggle(todo.id)}
/>
{todo.text}
</li>
{/each}
</ul>
<style>
.done {
text-decoration: line-through;
opacity: 0.6;
}
</style>
```
## SvelteKit Framework
### Project Structure
```
my-app/
├── src/
│ ├── routes/
│ │ ├── +page.svelte # Home page
│ │ ├── +page.ts # Universal load
│ │ ├── +page.server.ts # Server load
│ │ ├── +layout.svelte # Shared layout
│ │ ├── about/
│ │ │ └── +page.svelte # /about
│ │ └── blog/
│ │ ├── +page.svelte # /blog
│ │ └── [slug]/
│ │ └── +page.svelte # /blog/my-post
│ ├── lib/
│ │ ├── components/
│ │ ├── stores/
│ │ └── utils/
│ └── app.html
├── static/ # Static assets
└── svelte.config.js
```
### Load Functions (Data Fetching)
```typescript
// src/routes/blog/[slug]/+page.ts
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, fetch }) => {
const response = await fetch(`/api/posts/${params.slug}`);
const post = await response.json();
return {
post
};
};
```
```svelte
<!-- src/routes/blog/[slug]/+page.svelte -->
<script lang="ts">
import type { PageData } from './$types';
let { data } = $props<{ data: PageData }>();
</script>
<article>
<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>
</article>
```
### Server-Only Load Functions
```typescript
// src/routes/admin/+page.server.ts
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ locals }) => {
if (!locals.user?.isAdmin) {
throw redirect(303, '/login');
}
const users = await db.users.findMany();
return {
users
};
};
```
### Form Actions
```typescript
// src/routes/login/+page.server.ts
import { fail, redirect } from '@sveltejs/kit';
import type { Actions } from './$types';
import { z } from 'zod';
const schema = z.object({
email: z.string().email(),
password: z.string().min(8)
});
export const actions = {
default: async ({ request, cookies }) => {
const formData = await request.formData();
const data = Object.fromEntries(formData);
const result = schema.safeParse(data);
if (!result.success) {
return fail(400, {
errors: result.error.flatten().fieldErrors
});
}
const user = await authenticateUser(result.data);
if (!user) {
return fail(401, { message: 'Invalid credentials' });
}
cookies.set('session', user.sessionToken, { path: '/' });
throw redirect(303, '/dashboard');
}
} satisfies Actions;
```
```svelte
<!-- src/routes/login/+page.svelte -->
<script lang="ts">
import type { ActionData } from './$types';
let { form } = $props<{ formRelated in toolchain
nextjs-core
IncludedCore Next.js patterns for App Router development including Server Components, Server Actions, route handlers, data fetching, and caching strategies
nextjs-v16
IncludedNext.js 16 migration guide (async request APIs, "use cache", Turbopack)
vitest
IncludedVitest - Modern TypeScript testing framework with Vite-native performance, ESM support, and TypeScript-first design
mcp-protocol-builder
IncludedMCP (Model Context Protocol) - Build AI-native servers with tools, resources, and prompts. TypeScript/Python SDKs for Claude Desktop integration.
golang-database-patterns
IncludedGo database integration patterns using sqlx, pgx, and migration tools like golang-migrate
sveltekit
IncludedSvelteKit - Full-stack Svelte framework with file-based routing, SSR/SSG, form actions, and adapters for deployment