SvelteKit & Routing
SvelteKit is the official application framework for Svelte. It provides routing, server-side rendering, API endpoints, and a powerful filesystem-based routing system.
Filesystem-Based Routing
// Project structure defines routes
src/routes/
+page.svelte → /
about/+page.svelte → /about
blog/+page.svelte → /blog
blog/[slug]/+page.svelte → /blog/:slug
users/[id]/+page.svelte → /users/:id
admin/
+layout.svelte → Layout for /admin/*
+page.svelte → /admin
users/+page.svelte → /admin/users
// src/routes/+page.svelte (home page)
<script>
export let data; // From load function
</script>
<h1>Welcome to SvelteKit</h1>
<p>{data.message}</p>
// src/routes/blog/[slug]/+page.svelte
<script>
export let data;
</script>
<article>
<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>
</article>Loading Data
// src/routes/+page.ts (or +page.server.ts)
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, url, fetch }) => {
return {
message: 'Hello from load function'
};
};
// src/routes/blog/[slug]/+page.ts
export const load: PageLoad = async ({ params, fetch }) => {
const response = await fetch(`/api/posts/${params.slug}`);
const post = await response.json();
return {
post
};
};
// Server-only load function (+page.server.ts)
import type { PageServerLoad } from './$types';
import { db } from '$lib/server/database';
export const load: PageServerLoad = async ({ params }) => {
// Can access database, environment variables, etc.
const post = await db.posts.findOne({ slug: params.slug });
return {
post
};
};Layouts
// src/routes/+layout.svelte (root layout)
<script>
export let data;
</script>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/blog">Blog</a>
</nav>
<main>
<slot /> <!-- Child pages render here -->
</main>
<footer>
<p>© 2024 My App</p>
</footer>
// src/routes/blog/+layout.svelte (nested layout)
<script>
export let data;
</script>
<div class="blog-layout">
<aside>
<h3>Categories</h3>
{#each data.categories as category}
<a href="/blog/category/{category.slug}">{category.name}</a>
{/each}
</aside>
<div class="content">
<slot /> <!-- Blog pages render here -->
</div>
</div>Navigation
<script>
import { goto, invalidate, invalidateAll } from '$app/navigation';
import { page } from '$app/stores';
// Current page data
$: console.log('Current path:', $page.url.pathname);
$: console.log('Params:', $page.params);
$: console.log('Search params:', $page.url.searchParams);
function navigateToPost(slug) {
goto(`/blog/${slug}`);
}
function navigateWithOptions() {
goto('/about', {
replaceState: true, // Replace history instead of push
noScroll: true, // Don't scroll to top
keepFocus: true // Keep focus on current element
});
}
// Invalidate data
function refresh() {
invalidateAll(); // Rerun all load functions
}
</script>
<!-- Declarative navigation -->
<a href="/about">About</a>
<a href="/blog/{post.slug}">Read More</a>Form Actions
// src/routes/login/+page.server.ts
import type { Actions } from './$types';
import { fail, redirect } from '@sveltejs/kit';
export const actions: Actions = {
login: async ({ request, cookies }) => {
const data = await request.formData();
const email = data.get('email');
const password = data.get('password');
// Validate
if (!email || !password) {
return fail(400, { email, missing: true });
}
// Authenticate
const user = await authenticateUser(email, password);
if (!user) {
return fail(401, { email, incorrect: true });
}
// Set cookie
cookies.set('session', user.sessionId, {
path: '/',
httpOnly: true,
sameSite: 'strict',
maxAge: 60 * 60 * 24 * 7 // 1 week
});
throw redirect(303, '/dashboard');
}
};
// src/routes/login/+page.svelte
<script>
import { enhance } from '$app/forms';
export let form; // Action response
</script>
<form method="POST" action="?/login" use:enhance>
<input name="email" type="email" value={form?.email ?? ''} />
{#if form?.missing}
<p class="error">Email and password required</p>
{/if}
{#if form?.incorrect}
<p class="error">Invalid credentials</p>
{/if}
<input name="password" type="password" />
<button>Login</button>
</form>Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free