Dive into Svelte 5's runes reactivity system and SvelteKit's powerful features for building fast, scalable web apps. This guide covers setup, key concepts, and advanced techniques with practical examples.
## Getting Started with Svelte 5 and SvelteKit
Svelte 5 introduces transformative changes to the framework, particularly through its new runes-based reactivity model, while SvelteKit remains the go-to tool for full-stack applications. This combination enables developers to create performant, SEO-friendly sites with seamless server-side rendering (SSR). Whether you're migrating from earlier versions or starting fresh, understanding these tools is essential for modern web development.
To begin, install the latest SvelteKit, which supports Svelte 5 out of the box. Run `npm create svelte@latest my-app` in your terminal, select your preferences like TypeScript and ESLint, then `cd my-app` and `npm install`. Start the dev server with `npm run dev`. This scaffolds a project ready for Svelte 5 features. For the official SvelteKit repository, check out [SvelteKit on GitHub](https://github.com/sveltejs/kit/tree/main/packages/kit?s=21).
Svelte 5 was released at [this GitHub tag](https://github.com/sveltejs/svelte/releases/tag/svelte%405.0.0), marking a shift from signals-like reactivity to explicit runes for better fine-grained updates and debugging.
## Mastering Runes: The Core of Svelte 5 Reactivity
Runes are Svelte 5's explicit reactivity primitives, replacing implicit reactivity. They make state management predictable and composable across components and even server contexts.
### $state: Reactive State Declaration
Use `$state()` to create reactive variables. Unlike Svelte 4's `let count = 0`, which auto-tracks, `$state` requires explicit declaration:
```svelte
<script>
let count = $state(0);
function increment() {
count++;
}
</script>
<button onclick={increment}>
Count: {count}
</button>
```
This ensures reactivity only where intended, reducing unnecessary re-renders. Access detailed runes documentation [here](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/01-runes).
### $derived: Computed Values
For values derived from state, use `$derived()`. It recomputes only when dependencies change:
```svelte
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<p>Doubled: {doubled}</p>
```
This is more efficient than watchers. See reactivity docs [here](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/04-reactivity).
### $effect: Side Effects and Lifecycle
`$effect()` handles side effects, running after the DOM updates and cleaning up on destroy:
```svelte
<script>
let count = $state(0);
$effect(() => {
document.title = `Count: ${count}`;
});
</script>
```
For pre-DOM effects like fetching, use `$effect.pre()`. Effects track dependencies automatically. More on effects in the [events documentation](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/06-events).
## Enhanced Stores in Svelte 5
Stores remain vital, now integrating seamlessly with runes. Writable stores use `$state` internally:
```js
// store.js
import { writable } from 'svelte/store';
export const count = writable(0);
```
In components:
```svelte
<script>
import { count } from './store.js';
</script>
<button onclick={() => $count++}>
{$count}
</button>
```
Explore stores further [here](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/05-stores).
## Server-Side Rendering and Hydration
SvelteKit excels in SSR. Pages render on the server, hydrate on the client. Use `+page.server.js` for server load functions:
```js
// +page.server.js
export async function load() {
return { message: 'Hello from server!' };
}
```
In `+page.svelte`:
```svelte
<script>
export let data;
</script>
<h1>{data.message}</h1>
```
Hydration skips re-rendering server content. For universal stores, leverage `$state.untracked()` to avoid hydration mismatches. DOM manipulation docs [here](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/07-dom).
## DOM Actions for Imperative Control
Actions attach imperative logic to elements:
```svelte
<script>
function clickOutside(node) {
function handleClick(event) {
if (!node.contains(event.target)) {
node.dispatchEvent(new CustomEvent('outclick'));
}
}
document.addEventListener('click', handleClick, true);
return {
destroy() {
document.removeEventListener('click', handleClick, true);
}
};
}
</script>
<div use:clickOutside on:outclick={() => console.log('Clicked outside')}>
Content
</div>
```
Custom events dispatch via [this guide](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/08-events-dispatch).
## Props, Attributes, and Bindings
Props are reactive by default. Validate with schemas:
```svelte
<script>
import { z } from 'zod';
let props = $props({
name: z.string(),
age: z.number().min(0)
});
</script>
```
Attributes use `let { class: className } = $props();`. Bindings work with `$bindable()`. Details in [attributes](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/09-attributes), [bindings](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/10-binding), and [props docs](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/17-props).
## Conditional Rendering and Loops
`{#if}` and `{#each}` are familiar but now rune-aware:
```svelte
{#if count > 0}
<p>{count} items</p>
{:else}
<p>No items</p>
{/if}
{#each items as item (item.id)}
<li>{item.name}</li>
{/each}
```
See [conditionals](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/11-conditional) and [each blocks](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/12-each).
## Transitions, Animations, and HTML
Built-in transitions like `fade` and `slide` enhance UX. Raw HTML with `{#html}` escapes by default. Docs [here](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/13-html), [transitions](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/14-transitions), [animations](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/15-animations).
## Components, Slots, and Methods
Components are portable. Slots for content projection:
```svelte
<!-- Child.svelte -->
<slot>Default</slot>
```
Methods via `$bindable()` or events. Full coverage in [components](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/16-components), [slots](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/18-slots), [methods](https://github.com/sveltejs/svelte/tree/5.0.0/docs/02-svelte/19-methods).
## Advanced SvelteKit Features
### Enhanced Form Actions
`+page.server.js` actions handle forms progressively:
```svelte
<!-- +page.svelte -->
<form method="POST" use:enhance>
<input name="name" />
<button>Submit</button>
</form>
```
```js
// +page.server.js
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
// process
return { success: true };
}
};
```
This enables instant validation and optimistic updates.
### Streaming SSR
For dynamic content, stream with `{#await}` and promises in load functions. Improves perceived performance on slow networks.
### View Transitions
SvelteKit supports CSS view transitions for smooth page changes. Enable in `app.html` and use `data-transition` attributes.
## Migration from Svelte 4
Consult the [Svelte 5 migration guide](https://github.com/sveltejs/svelte/tree/5.0.0/MIGRATION.md) for step-by-step instructions. Key changes include wrapping top-level state in `$state()` and updating reactivity.
This guide equips you to build robust apps. Experiment in a new project to internalize these concepts—Svelte 5's explicitness pays dividends in larger codebases.
<div style="text-align: center; margin-top: 2rem;">
<a href="https://cursor.directory/svelte5-sveltekit-development-guide" target="_blank" rel="noopener noreferrer" class="view-full-resource-btn" style="display: inline-block; background-color: #f97316; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background-color 0.2s;">View Full Resource</a>
</div>