03 - Routing

File-Based Routing

Routes are defined by the folder structure in src/routes/. Each folder with a +page.svelte becomes a URL.

Basic Routes

src/routes/
├── +page.svelte              → /
├── about/
│   └── +page.svelte          → /about
└── blog/
    ├── +page.svelte          → /blog
    └── [slug]/
        └── +page.svelte      → /blog/hello-world (dynamic)

Dynamic Routes

Square brackets [param] create dynamic segments. The value is available via params in load functions.

// src/routes/blog/[slug]/+page.ts
import type { PageLoad } from './$types';

export const load: PageLoad = async ({ params }) => {
  // params.slug = "hello-world" when URL is /blog/hello-world
  return {
    post: {
      title: params.slug,
      content: 'Post content...'
    }
  };
};

OR this simpler (untyped) version does the same thing:

export const load = ({ params }) => {
    return { slug: params.slug };
};
<!-- src/routes/blog/[slug]/+page.svelte -->
<script lang="ts">
let { data } = $props();  // data comes from the load function above
</script>

<h1>{data.post.title}</h1>
<p>{data.post.content}</p>

Multiple Parameters

Each folder level can have its own parameter:

src/routes/
└── [category]/
    └── [id]/
        └── +page.svelte      → /electronics/123

params would be { category: "electronics", id: "123" }.

Optional Parameters

Double brackets [[param]] make a segment optional — the route matches with or without it:

src/routes/
└── [[lang]]/
    └── +page.svelte          → / or /en or /fr

Rest Parameters

[...param] captures all remaining segments as a single string:

src/routes/
└── docs/
    └── [...path]/
        └── +page.svelte      → /docs/a/b/c

params.path would be "a/b/c".

Navigation

Two ways to navigate between pages:

<script>
import { goto } from '$app/navigation';
</script>

<!-- Declarative — standard <a> tags, SvelteKit handles them as client-side navigation -->
<a href="/about">About</a>

<!-- Programmatic — navigate from code (after form submit, button click, etc.) -->
<button onclick={() => goto('/about')}>Go to About</button>

SvelteKit intercepts <a> clicks automatically — no special <Link> component needed.

Route Groups

Parentheses (name) create layout groups — they organize routes without affecting URLs:

src/routes/
├── (marketing)/
│   ├── +layout.svelte       ← marketing layout (no nav bar)
│   ├── about/+page.svelte   → /about
│   └── contact/+page.svelte → /contact
└── (app)/
    ├── +layout.svelte       ← app layout (with sidebar, auth)
    └── dashboard/+page.svelte → /dashboard

The (marketing) and (app) folders don't appear in the URL. They just let you apply different layouts to different groups of pages.