Dynamische Routen
Nicht jede URL ist statisch bekannt. Mit eckigen Klammern im Ordnernamen werden Teile der URL zu Parametern — genau wie /blog/:id in Rails, nur dateibasiert.
Ein Segment: [slug]
Ein Ordner mit eckigen Klammern wie [slug] macht dieses
URL-Segment dynamisch. src/routes/blog/[slug]/+page.svelte bedient damit /blog/hallo-welt, /blog/svelte-tipps und jede andere einzelne
Blog-URL — mit einer Datei.
src/routes/blog/[slug]/
├── +page.svelte # zeigt einen Artikel
└── +page.ts # lädt den Artikel anhand des slugDen konkreten Wert bekommst du in der load-Funktion über params.slug — der Name entspricht exakt dem Klammer-Namen im Ordner.
// src/routes/blog/[slug]/+page.ts
import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, fetch }) => {
// params.slug ist der dynamische Teil der URL
const res = await fetch(`/api/posts/${params.slug}`);
if (!res.ok) error(404, 'Artikel nicht gefunden');
return { post: await res.json() };
};In der Komponente stehen die geladenen Daten via data-Prop bereit; den rohen
Parameter erreichst du zusätzlich reaktiv über page.params aus $app/state.
<!-- src/routes/blog/[slug]/+page.svelte -->
<script lang="ts">
import { page } from '$app/state';
let { data } = $props();
</script>
<h1>{data.post.titel}</h1>
<p class="meta">slug: {page.params.slug}</p>
<article>{@html data.post.inhalt}</article>🛤️ Rails-Vergleich: dynamische Segmente & Constraints
[slug] entspricht dem :id / :slug in Rails-Routen. Wo
du in Rails auf params[:id] im Controller zugreifst, nutzt du in SvelteKit params.slug in load. Route-Constraints (constraints:)
heißen hier Matcher.
# config/routes.rb
resources :blog, only: :show # /blog/:id
get "docs/*pfad", to: "docs#show" # Wildcard/Glob
# Constraint = SvelteKit-Matcher
get "produkt/:id", to: "produkte#show",
constraints: { id: /\d+/ } # nur Ziffern
# Zugriff im Controller: params[:id], params[:slug]Live: URL-Muster gegen Pfade
Wähle einen Beispiel-Pfad und sieh, welchen slug das Muster /blog/[slug] extrahiert:
Pfad: /blog/hallo-welt
params.slug = "hallo-welt"
Rest, optional & Matcher
Neben dem einfachen [slug] gibt es zwei weitere Klammer-Formen:
- Rest-Parameter
[...pfad]fängt beliebig viele Segmente auf — gut für Dokumentations-Bäume wie/docs/a/b/c. - Optionaler Parameter
[[lang]]matcht mit oder ohne das Segment — nützlich für Sprachpräfixe (/und/de).
src/routes/
├── blog/[slug]/+page.svelte # ein Segment: /blog/hallo
├── docs/[...pfad]/+page.svelte # Rest (beliebig tief):
│ # /docs/a, /docs/a/b/c
└── [[lang]]/+page.svelte # optional: / und /de, /enMatcher: Parameter validieren
Standardmäßig matcht [slug] jeden Text. Willst du einschränken — z. B. nur
numerische IDs — definierst du einen wiederverwendbaren Matcher in src/params/ und referenzierst ihn mit [id=integer].
// src/params/integer.ts — wiederverwendbarer Matcher
import type { ParamMatcher } from '@sveltejs/kit';
export const match: ParamMatcher = (param) => {
return /^\d+$/.test(param); // nur Ziffern
};src/routes/
└── produkt/[id=integer]/+page.svelte
# /produkt/42 → matcht (params.id = "42")
# /produkt/abc → matcht NICHT → 404 (oder andere Route)⚠️ Matcher gehören zum Routing, nicht zur Validierung
Ein Matcher entscheidet nur, ob eine Route greift. Passt der Parameter nicht,
versucht SvelteKit andere Routen und liefert sonst 404 — er ersetzt keine inhaltliche
Prüfung deiner Daten in load.
Zusammenfassung
💡 Das Wichtigste
[slug]macht ein Segment dynamisch; Zugriff viaparams.slug.[...pfad]fängt beliebig viele Segmente (Rest) auf.[[lang]]ist optional — matcht mit und ohne das Segment.[id=integer]bindet einen Matcher aussrc/params/ein.- In der Komponente reaktiv über
page.paramserreichbar.
🎯 Probier es selbst
Lege eine Route src/routes/blog/[slug]/+page.svelte mit passender +page.ts an, die params.slug ausliest und (zunächst) einfach als
Überschrift ausgibt. Ergänze anschließend einen Matcher src/params/integer.ts und eine Route produkt/[id=integer] — teste, dass /produkt/42 matcht, /produkt/abc aber einen 404 liefert.