Episode ini membahas routing dan navigasi di SvelteKit: routing berbasis filesystem dengan +page dan +layout, dynamic dan nested routes, navigasi dengan elemen a dan fungsi goto, serta route parameters, query parameters, dan mekanisme preload.

Sebuah aplikasi web hampir selalu memiliki lebih dari satu halaman: beranda, tentang, detail produk, dan lain-lain. Cara halaman-halaman itu dihubungkan dan data mengalir di antaranya adalah pekerjaan routing. Di SvelteKit, routing dibangun dari filesystem — folder dan file menentukan URL aplikasi kalian.
Pendekatan filesystem membuat struktur aplikasi terbaca langsung dari struktur folder. Kalian tidak perlu mendaftarkan rute di satu file konfigurasi raksasa; cukup buat file, dan rutenya ada. Ditambah layout yang membungkus beberapa halaman sekaligus, kalian bisa mengatur navigasi dan UI bersama dengan sangat rapi.
Episode ini membahas routing filesystem, dynamic dan nested routes, navigasi dengan elemen <a> dan fungsi goto(), serta route parameters, query parameters, dan preload. Inilah peta jalan yang menghubungkan semua halaman aplikasi kalian.
Setiap file +page.svelte di dalam src/routes menjadi satu halaman yang bisa diakses. Folder menentukan URL:
src/routes/
├── +page.svelte # /
├── about/+page.svelte # /about
└── blog/+page.svelte # /blogsrc/routes/about/+page.svelte dirender ketika pengguna mengunjungi /about. Konvensi tanda plus di depan nama file membedakan file ini dari file lain di folder yang sama — komponen, endpoint API, atau modul pendukung tidak secara otomatis menjadi rute.
Setiap halaman bisa memiliki file +page.js yang menyediakan data:
<script>
let { data } = $props()
</script>
<h1>Blog</h1>
{#each data.artikel as artikel}
<a href={`/blog/${artikel.slug}`}>{artikel.judul}</a>
{/each}data.artikel berasal dari load function +page.js. Halaman merender daftar artikel sebagai tautan menuju halaman detail. Perhatikan bagaimana URL dibangun dari artikel.slug — inilah gerbang menuju dynamic routes di bagian berikutnya.
Untuk halaman yang bergantung pada identitas tertentu — misalnya /blog/hello-svelte — gunakan folder dengan nama dinamis. Nama folder itu menjadi nama parameter:
src/routes/
└── blog
├── +page.svelte
└── [slug]/+page.svelte<script>
let { data } = $props()
</script>
<h1>{data.artikel.judul}</h1>
<p>{data.artikel.isi}</p>Folder [slug] menangkap segmen URL. Di load function, parameter tersedia di params.slug:
export async function load({ params }) {
const artikel = await cariArtikel(params.slug)
return { artikel }
}params.slug berisi nilai segmen URL. Dengan ini satu folder melayani tak terbatas halaman: /blog/satu, /blog/dua, semuanya lewat file yang sama.
Layout adalah komponen yang membungkus beberapa halaman. File +layout.svelte di sebuah folder berlaku untuk semua rute di bawahnya:
<script>
let { children } = $props()
</script>
<nav>
<a href="/blog">Semua artikel</a>
</nav>
{@render children()}{@render children()} adalah cara Svelte 5 merender konten halaman yang dibungkus layout. Navbar di layout ini muncul di semua halaman blog tanpa menulis ulang markup. Layout bisa bertumpuk: layout folder terdalam membungkus layout folder yang lebih luar.
Cara paling sederhana dan benar untuk navigasi tetap elemen <a>. SvelteKit mengintervensi klik dan melakukan navigasi client-side tanpa reload penuh:
<nav>
<a href="/">Beranda</a>
<a href="/about">Tentang</a>
<a href="/blog">Blog</a>
</nav>href="/about" diintervensi SvelteKit untuk navigasi mulus. Sebagai bonus, SvelteKit me-prefetch tautan saat pengguna menahan pointer di atasnya, sehingga halaman terbuka lebih cepat. Tidak ada API khusus yang perlu dipanggil — kalian cukup menulis tautan biasa.
Saat navigasi harus dipicu dari logika — setelah form sukses, setelah login, setelah countdown selesai — gunakan fungsi goto dari $app/navigation:
<script>
import { goto } from "$app/navigation"
function selesai() {
goto("/terima-kasih")
}
</script>
<button onclick={selesai}>Selesai</button>goto("/terima-kasih") memindahkan pengguna ke rute yang ditargetkan dari dalam kode JavaScript. goto juga menerima opsi seperti { replaceState: true } untuk mengganti riwayat tanpa menambah entri baru.
Data opsional di URL — seperti filter, pencarian, atau halaman — dikirim sebagai query string. Akses dari load function melalui url:
export async function load({ url }) {
const halaman = Number(url.searchParams.get("halaman") ?? 1)
const q = url.searchParams.get("q") ?? ""
return { halaman, q }
}url.searchParams.get("halaman") membaca parameter dari query string. Kombinasi ?? 1 memberikan nilai default saat parameter tidak dikirim. Query parameter membuat satu halaman bisa menyajikan banyak variasi tanpa membuat banyak rute.
SvelteKit menjalankan load function sebelum navigasi selesai, jadi halaman datang lengkap dengan data. Untuk aplikasi yang butuh respons ekstra cepat, tambahkan data-sveltekit-preload-data pada tautan:
<a href="/dashboard" data-sveltekit-preload-data>Dashboard</a>data-sveltekit-preload-data memerintahkan SvelteKit mengambil data halaman segera setelah atribut ini terlihat — biasanya saat pointer mendekati tautan. Hasilnya: ketika pengguna benar-benar mengklik, data sudah menunggu. Kombinasikan dengan layout untuk pengalaman navigasi yang terasa instan.
Inti yang harus dibawa pulang:
+page.svelte di src/routes menentukan URL aplikasi secara filesystem.[slug] menciptakan dynamic route; nilainya dibaca lewat params di load function.+layout.svelte membungkus semua halaman di bawah folder dengan konten yang dirender lewat {@render children()}.<a> sudah cukup untuk navigasi client-side; gunakan goto() untuk navigasi dari kode.url.searchParams di load function.data-sveltekit-preload-data mempercepat navigasi dengan mengambil data lebih awal.Di episode 10 selanjutnya kita akan membahas forms dan validation — form handling dengan bindings dan events, validation patterns dan custom validators, server-side validation di SvelteKit, serta accessibility forms dan UX feedback. Navigasi yang baru saja kalian pelajari akan menutup alur submit form.