This post is outdated for SvelteKit 1.x. It covers SvelteKit's router before SvelteKit 1.0.0-next.406.
The SvelteKit docs state that
At the heart of SvelteKit is a filesystem-based router. This means that the structure of your application is defined by the structure of your codebase — specifically, the contents of
In this post, we will explore how SvelteKit's
filesystem-based router matches a requested
route to a page or an endpoint. SvelteKit transforms each route file in
a page or an endpoint. Conversely, SvelteKit needs to match a requested route to a route file. This
is called route matching.
A filesystem-based router makes route matching straightforward: the route can be interpreted as
the subpath in
src/routes and often there is only one matching route file. But what happens
when there are multiple matching route files? How does SvelteKit decide which route file it uses to
render a page or endpoint?
In this post, we look at a SvelteKit example and explore the rules that SvelteKit applies to decide which page or endpoint to serve. You will make the most out of this post if you follow along:
Duplicate route files are not permitted
When you have the example up and running, click route
/green in the preview.
SvelteKit matches this request to page
src/routes/green.svelte. This is the
filesystem-based router at work, which takes the route and looks for the corresponding route file
Now click route
/red. This time SvelteKit matches the request to page
src/routes/red/index.svelte, which is equivalent to
src/routes/red.svelte in the example and copy the content of file
src/routes/red/index.svelte. You should see this error message in the terminal:
Rule 1: Duplicate route files are not permitted.
You cannot have both
src/routes/red.svelte. SvelteKit won't let you.
src/routes/red.svelte and run
to restart the development server.
Matching against path segments
The SvelteKit router matches strings of route segments to path segments. Path segments inside
src/routes can be static (
.../static/...) or dynamic (
.../[dynamic]/...) with square brackets. Dynamic path segments match any string.
Static path segments require an exact match. The second rule describes the order in which
SvelteKit matches route segments to path segments:
Rule 2: SvelteKit matches route segments to path segments left to right.
Let's revisit the
/red route from before. Now that we know what dynamic path segments
are, we realize that there were three more candidate pages:
These are not duplicate routes because the strings inside
 differ. We already know
from the previous section, that
/red is not rendered with any of the above candidate pages.
The reason is this rule:
Rule 3: Static path segments take precedence over dynamic path segments.
src/routes/green.svelte (static) takes precedence over
Alphabetical order of path segments
Let's look at route
/blue in the example. The candidate pages are:
We need another rule to choose the page that is used to render
Rule 4: Index pages take precedence over non-index pages.
This is only relevant for pages that are not considered duplicate routes, e.g.,
src/routes/[colour]/index.svelte takes precedence over
When matching route segment
blue, we can use this rule to eliminate the first two
candidate pages. This results in page
rendered. You can confirm this by clicking on
/blue in the example.
Let's delete page
src/routes/[colour]/index.svelte in the example. To make the
workspace pick up this change, you need to click in the terminal and hit
the development server with
npm run dev.
Now the two candidates for route
A look at the rendered page reveals that the router used
src/routes/[color].svelte. It did so because of this rule:
Rule 5: For two path segments of the same type, the first one in alphabetical order takes precedence.
src/routes/[color].svelte takes precedence over
color comes before
nocolor in alphabetical order.
Matching with spread syntax
Let's look at route
/color/blue in the example. The candidate pages are:
[...rest] in the second route is a dynamic path segment, which uses
and matches any path under
/color, no matter how deep. We refer to it as a spread
segment. The following rule clarifies, which page the router chooses to render
Rule 6: Dynamic path segments take precedence over spread segments.
src/routes/color/[color].svelte takes precedence over
You can navigate to route
/color/blue/dark to see an example of a route that is
Last but not least, let's navigate to route
/blue/dark in the example. This time,
there are no candidate pages. What does the router do? It falls back to default error page
Note that as soon as there is one candidate page, including pages with spread segments, the
SvelteKit router does not fall back to an error page. This is what we observed for route
/color/blue/dark in the previous section. It was rendered with
src/routes/color/[...rest].svelte and not the default error page.
SvelteKit allows you to configure error pages more granular per directory and you can read up on how this works in the SvelteKit docs.