Svelte 5 Development Skill When to Activate Activate this skill when: Creating Svelte 5 components Working with SvelteKit routing Implementing runes ($state, $derived, $effect) Building forms with actions Setting up SvelteKit projects Quick Commands npx sv create my-app
Create SvelteKit project
cd my-app && pnpm install pnpm dev
Start dev server (localhost:5173)
pnpm build
Build for production
Runes Quick Reference Rune Purpose Example $state Reactive state let count = $state(0) $derived Computed values let doubled = $derived(count * 2) $effect Side effects $effect(() => console.log(count)) $props Component props let { name } = $props() $bindable Two-way binding let { value = $bindable() } = $props() Reactive State ($state)
- Clicked {count} times
- {user.name} is
- Deep reactivity
- Objects and arrays update automatically on mutation. Computed Values ($derived)
Side Effects ($effect)
Component Props ($props)
TypeScript Props
SvelteKit File Conventions File Purpose +page.svelte Page component +page.server.js Server-only load/actions +layout.svelte Shared layout +server.js API endpoints +error.svelte Error boundary Data Loading // src/routes/posts/+page.server.js export async function load ( { fetch } ) { const response = await fetch ( "/api/posts" ) ; return { posts : await response . json ( ) } ; }
{#each data.posts as post}
{post.title}
{/each} Form Actions Type-Safe Form Validation (Rootwork Pattern) Use parseFormData() for type-safe form handling at trust boundaries: // src/routes/login/+page.server.ts import { fail , redirect } from "@sveltejs/kit" ; import { parseFormData } from "@autumnsgrove/lattice/server" ; import { z } from "zod" ; const LoginSchema = z . object ( { email : z . string ( ) . email ( "Valid email required" ) , password : z . string ( ) . min ( 8 , "Password must be at least 8 characters" ) , } ) ; export const actions = { default : async ( { request , cookies } ) => { const formData = await request . formData ( ) ; const result = parseFormData ( formData , LoginSchema ) ; if ( ! result . success ) { const firstError = Object . values ( result . errors ) . flat ( ) [ 0 ] ; return fail ( 400 , { error : firstError || "Invalid input" } ) ; } const { email , password } = result . data ; // Authenticate with validated, typed data const token = await authenticate ( email , password ) ; if ( ! token ) { return fail ( 401 , { error : "Invalid credentials" } ) ; } cookies . set ( "session" , token , { path : "/" } ) ; throw redirect ( 303 , "/dashboard" ) ; } , } ; Benefits: Type-safe: result.data is fully typed as LoginSchema Structured errors: result.errors is a map of field → messages No as casts at trust boundaries
API Routes // src/routes/api/posts/+server.js import { json } from "@sveltejs/kit" ; export async function GET ( { url } ) { const posts = await getPosts ( ) ; return json ( posts ) ; } export async function POST ( { request } ) { const data = await request . json ( ) ; const post = await createPost ( data ) ; return json ( post , { status : 201 } ) ; } Common Pitfalls Destructuring Breaks Reactivity // ❌ Bad let { count } = $state ( { count : 0 } ) ; // ✅ Good let state = $state ( { count : 0 } ) ; state . count ++ ; Missing Keys in Each
{#each items as item}
{#each items as item (item.id)} Use Progressive Enhancement