Skip to content

File-based Routing

In react-router you declare routes in JavaScript. In Next.js you create files in a pages/ or app/ directory. SvelteKit works like Next.js App Router: create a folder, add +page.svelte, and you have a route. No imports, no route config, no wrapping component needed.

Run this in a SvelteKit project (npx sv create).

The simplest case: a static path maps directly to a folder + +page.svelte.

React (react-router)
// react-router v6
import { createBrowserRouter } from 'react-router-dom';
import About from './pages/About';
const router = createBrowserRouter([
{ path: '/about', element: <About /> },
]);
SvelteKit
<!-- src/routes/about/+page.svelte -->
<!-- This file IS the /about route. No config needed. -->
<h1>About</h1>
<p>Welcome to the about page.</p>

react-router uses :id in the path string. Next.js uses [id] in the filename. SvelteKit uses [param] as a folder name — the folder name (without brackets) becomes the parameter key.

React / Next.js
// react-router v6
{ path: '/posts/:id', element: <PostPage /> }
// Next.js Pages Router
// pages/posts/[id].tsx
// Next.js App Router
// app/posts/[id]/page.tsx
SvelteKit
<!-- src/routes/posts/[id]/+page.svelte -->
<!-- Matches /posts/1, /posts/hello, /posts/anything -->
<h1>Post detail page</h1>

A realistic SvelteKit src/routes/ structure:

flowchart TB
  routes(["src/routes/"])
  routes --> rootPage["+page.svelte → /"]
  routes --> about["about/"]
  about --> aboutPage["+page.svelte → /about"]
  routes --> blog["blog/"]
  blog --> blogPage["+page.svelte → /blog"]
  blog --> slug["[slug]/"]
  slug --> slugPage["+page.svelte → /blog/:slug"]
  routes --> dashboard["dashboard/"]
  dashboard --> dashLayout["+layout.svelte (shared layout)"]
  dashboard --> dashPage["+page.svelte → /dashboard"]
  dashboard --> settings["settings/"]
  settings --> settingsPage["+page.svelte → /dashboard/settings"]
SvelteKit src/routes/ file tree

Every +page.svelte is a route. The +layout.svelte inside dashboard/ wraps all pages in that folder and its subfolders — equivalent to a <Outlet> layout route in react-router or a layout.tsx in Next.js App Router.

The cleanest approach is to read params inside +page.js or +page.server.js and pass them to the component as data. The component stays param-agnostic.

src/routes/blog/[slug]/+page.js
export async function load({ params }) {
const post = await fetchPost(params.slug);
return { post };
}
src/routes/blog/[slug]/+page.svelte
<script>
let { data } = \$props();
// data.post is what load() returned
<\/script>
<h1>{data.post.title}</h1>
<article>{@html data.post.content}</article>

You can also read params directly in the component using the $page store from $app/state:

src/routes/blog/[slug]/+page.svelte
<script>
import { page } from '\$app/state';
// page.params.slug is the current [slug] value
<\/script>
<p>Viewing slug: {page.params.slug}</p>

The load function approach is preferred — it keeps data fetching co-located and typed, and it works well with server-side rendering.

How do you create a dynamic route for /posts/:id in SvelteKit?
What is the SvelteKit equivalent of a react-router layout route with <Outlet />?
What syntax does SvelteKit use for dynamic route segments — and how does it differ from react-router?