This episode dissects SvelteKit routing: file-based routing in src/routes, dynamic routes with optional parameters and catch-all routes, nested layouts along with layout resets, and navigation via anchors and the goto function. You will also learn route groups for sharing UI without changing the URL structure.

Routing is the foundation of every web application: it determines which page appears for a given URL. Episode 4 changes the way you think about routing — in SvelteKit, the folder structure is the URL structure, and there's no centralized routing configuration to maintain.
This file-based approach sounds simple, but it holds a lot of power: dynamic routes, nested layouts, even navigation prefetching. Understanding the full map of routing features in this episode will make subsequent episodes, especially data loading and forms, much easier.
We'll start from the most basic concept, then move up to more complex techniques. Make sure the project from episode 3 is still running, because every example here can be practiced right away.
Each folder inside src/routes represents a URL segment. The +page.svelte file inside that folder becomes the page rendered for that URL.
src/routes/
|-- +page.svelte -> /
|-- about/
| |-- +page.svelte -> /about
|-- blog/
| |-- +page.svelte -> /blog
| |-- [slug]/
| | |-- +page.svelte -> /blog/apa-saja
|-- api/
| |-- +server.js -> endpoint GET/POST /apiThe plus prefix in a file name marks a special role. The most common ones:
+page.svelte — the page component.+page.js — data for the page, running on server and client.+page.server.js — data for the page, server only.+layout.svelte — a layout wrapping the pages in that folder.+server.js — a pure API endpoint that responds over HTTP.Other files inside a route folder, like helper components, are not routed. SvelteKit only pays attention to plus-prefixed files. This convention keeps the src/routes folder clean.
A folder named [slug] captures a dynamic value from the URL. That value is available as params inside a load function.
export const load = async ({ params }) => {
return {
slug: params.slug,
judul: "Artikel " + params.slug
};
};Access params.slug to retrieve the value from the URL. This convention applies to all dynamic segments: [id], [username], [kategori], and so on.
Double square brackets [[opsional]] make a segment optional in the URL. Useful for pages like /docs and /docs/pengenalan that share a single file.
Meanwhile [...rest] captures the rest of the URL in any number of segments, forming an array. This is great for flexible nested paths, such as a file browser supporting unlimited folder depth. Both can be combined: a folder like [...rest] inside [modul] provides enormous flexibility.
Layouts wrap the pages inside the same folder and all its subfolders. src/routes/+layout.svelte applies to the entire application, while src/routes/blog/+layout.svelte only applies to pages under /blog.
<script>
let { children } = $props();
</script>
<header>Layout blog</header>
<main>
{@render children()}
</main>The wrapped page content is rendered via {@render children()}. With nested layouts, shared UI like a sidebar, breadcrumb, or header can be split per application section without duplication.
Sometimes several routes need different layouts but live in the same folder. Route groups solve this: folders with parentheses at the start and end don't affect the URL. For example (auth)/login and (auth)/register can share a layout without adding a URL segment.
Meanwhile, a layout reset +layout@.svelte ignores all parent layouts and starts from the root layout. Useful for pages like login that shouldn't show the application navbar. Combining route groups and layout resets gives you full control over the UI hierarchy.
Basic navigation still uses anchor elements. SvelteKit intercepts clicks on internal <a> tags and performs client-side navigation without a full reload.
<script>
import { goto } from "$app/navigation";
import { page } from "$app/stores";
</script>
<a href="/">Beranda</a>
<a href="/blog" data-sveltekit-prefetch>Blog</a>
<a href="/blog/artikel-pertama">Artikel pertama</a>
<button onclick={() => goto("/tentang")}>Tentang</button>
<p>Halaman aktif: {$page.url.pathname}</p>The data-sveltekit-prefetch attribute tells SvelteKit to fetch the target page's data before it's clicked, making navigation feel instant. For navigation from within code, call goto(route) from the $app/navigation module.
The $page store provides information about the active page: URL, params, and the data produced by load functions. To highlight the active menu item, compare $page.url.pathname with the menu href. Use $page.params.slug to read a parameter in any component without passing it down as a prop.
Key takeaways:
src/routes become URLs; only plus-prefixed files are routed.[slug] are available as params in load functions.[[opsional]] makes a segment optional; [...rest] captures the rest of the URL.+layout@.svelte.goto from $app/navigation, with prefetching via data-sveltekit-prefetch.In the next episode we discuss data loading & forms: load functions on server and client, fetching data with fetch from within load, form handling with server actions and progressive enhancement, plus error and redirect handling.