Routing
SvelteKit uses filesystem-based routing. Files in src/routes/ map to URL paths.
Basic Routes
src/routes/
├── +page.svelte # /
├── about/
│ └── +page.svelte # /about
└── blog/
├── +page.svelte # /blog
└── [slug]/
└── +page.svelte # /blog/:slug
Route Files
| File | Purpose |
|---|---|
+page.svelte | Page component (renders the UI) |
+page.ts | Universal load function (runs on server AND client) |
+page.server.ts | Server-only load function (database, secrets) |
+layout.svelte | Shared layout wrapper (persists across child routes) |
+layout.ts | Layout load function |
+server.ts | API endpoint (GET, POST, etc.) |
+error.svelte | Error page for this route segment |
Dynamic Parameters
src/routes/blog/[slug]/+page.svelte
Access the parameter in a load function:
// +page.ts
export function load({ params }) {
return {
post: getPost(params.slug)
};
}
Layouts
Layouts wrap child routes. They persist across navigation (no remount):
<!-- src/routes/+layout.svelte -->
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
{@render children()}
Nested layouts stack. A layout at src/routes/blog/+layout.svelte wraps all /blog/* pages and itself is wrapped by the root layout.
API Endpoints
// src/routes/api/users/+server.ts
import { json } from '@sveltejs/kit';
export async function GET() {
const users = await db.getUsers();
return json(users);
}
export async function POST({ request }) {
const data = await request.json();
const user = await db.createUser(data);
return json(user, { status: 201 });
}
Gotcha:
+server.tsfiles can’t coexist with+page.sveltein the same directory if both handle GET requests. SvelteKit won’t know which one to use.