SvelteKit Knowledge Base
Setup
npm create svelte@latest my-app
# Select: Skeleton, TypeScript, ESLint, Prettier
cd my-app
npm install
Project Structure
src/
├── routes/
│ ├── +layout.svelte
│ ├── +page.svelte
│ ├── +page.ts # Load function
│ ├── +page.server.ts # Server load
│ ├── [locale]/
│ │ ├── +layout.svelte
│ │ └── +page.svelte
│ └── api/
│ └── contact/
│ └── +server.ts
├── lib/
│ ├── components/
│ └── utils.ts
├── app.html
└── app.css
Svelte 5 Runes
<script lang="ts">
// State
let count = $state(0);
// Derived state
let doubled = $derived(count * 2);
// Props
let { name, onClick }: { name: string; onClick: () => void } = $props();
// Effect
$effect(() => {
console.log('count changed:', count);
});
</script>
<button => count++}>
{count} (doubled: {doubled})
</button>
Load Functions
// +page.ts (runs on client and server)
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, fetch }) => {
const res = await fetch(`/api/posts/${params.slug}`);
const post = await res.json();
return { post };
};
// +page.server.ts (server only - can access DB)
import type { PageServerLoad } from './$types';
import { db } from '$lib/db';
export const load: PageServerLoad = async ({ params }) => {
const post = await db.posts.findUnique({
where: { slug: params.slug }
});
return { post };
};
Form Actions
// +page.server.ts
import type { Actions } from './$types';
import { fail } from '@sveltejs/kit';
export const actions: Actions = {
default: async ({ request }) => {
const data = await request.formData();
const email = data.get('email');
if (!email) {
return fail(400, { email, missing: true });
}
// Process...
return { success: true };
}
};
<!-- +page.svelte -->
<script lang="ts">
import { enhance } from '$app/forms';
let { form } = $props();
</script>
<form method="POST" use:enhance>
<input name="email" value={form?.email ?? ''}>
{#if form?.missing}
<p class="error">Email required</p>
{/if}
<button>Submit</button>
</form>
API Routes
// src/routes/api/contact/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const POST: RequestHandler = async ({ request }) => {
const data = await request.json();
// Process...
return json({ success: true });
};
Layouts
<!-- +layout.svelte -->
<script lang="ts">
import { page } from '$app/stores';
let { children } = $props();
</script>
<nav>
<a href="/" class:active={$page.url.pathname === '/'}>Home</a>
</nav>
<main>
{@render children()}
</main>
Hooks
// src/hooks.server.ts
import type { Handle } from '@sveltejs/kit';
export const handle: Handle = async ({ event, resolve }) => {
// Auth check, locale detection, etc.
const locale = event.cookies.get('locale') || 'it';
event.locals.locale = locale;
return resolve(event);
};
Best Practices
- Use Runes - $state, $derived, $effect
- Server load - For sensitive data
- Form actions - For mutations
- Progressive enhancement - use:enhance
- Preloading - data-sveltekit-preload-data