Skip to content


Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


svelte npm Build Status GitHub license Dependencies Status

Simple Svelte 3 hash based router with global routes.


Demo REPL:


npm i -D svelte-hash-router


First, set the routes schema before the root component.

// index.js
import { routes } from 'svelte-hash-router'
import App from './App.svelte'
import Home from './Home.svelte'
import About from './About.svelte'

  '/home': Home,
  '/about': About 

export default new App({ target: document.body })

Then use Router inside.

<!-- App.svelte -->
import Router from 'svelte-hash-router'


Or more simple:

// index.js
export default new Router({ target: document.body })

Nested routes

// schema
  '/': {
    $$component: MainLayout,
    'home': Home,
    'networking': {
      $$component: NetworkingLayout,
      '/github': Github,
      '/facebook': Facebook
  '*': NotFound

Then just simply use Router for each level.

<!-- MainLayout.svelte -->
<div id='header'></div>

<Router/> <!-- match '/home' and '/networking' -->

<div id='footer'></div>
<!-- NetworkingLayout.svelte -->
<p>A social networking</p>

<Router/> <!-- match '/networking/github' and '/networking/facebook' -->

If $$component in the parent is omitted:

// schema
  '/': {
    'home': Home,
    'about': About

// will act the same as
  '/home': Home,
  '/about': About

Except that in the first schema, / is an individual route, has its own data and can be looped for children routes when needed. See routes.


Root paths must start with a / or if using wildcard, *.

import { routes, Router } from 'svelte-hash-router'

  '/home': Home,
  '*': NotFound

export default new Router({ target: document.body })

An object of options can be passed. All properties starting with $$ will be treated as options, the rest will be seen as nested routes. All options are saved as none-enumerable. $$component is a reserved option.

  '/home': HomeComponent,
  '/about': {
    // options
    $$component: AboutComponent,
    $$name: 'About me',
    $$customOption: 'any',
    // nested routes
    '/biography': BiographyComponent,
    '/hobbies': HobbiesComponent 


Get params of current active route with the params store.

// schema
  '/books/:id': BookComponent,
  '/authors/:name/novels/:title': NovelComponent

// Svelte component
import { params } from 'svelte-hash-router'

// /books/123
$ === '123'

// /authors/John/novels/Dreams
$ === 'John'
$params.title === 'Dreams'

Same with query.

// Svelte component
import { query } from 'svelte-hash-router'

// /book?id=123&title=Dreams
$ === '123'
$query.title === 'Dreams'


The order of schema does matter. Whichever route matching first will be rendered. Wildcard * matches anything, so it is usually put at the end. Wilcard is collected in params as _.

// schema
{ '/book/*': BookComponent }

// /book/123?title=Dreams
$params._ === '123' // not catch query


This library uses the nice package url-pattern, check it out for more syntaxes.


Redirect routes by using a string instead of a Svelte component, or if passing options object, use $$redirect. The redirect path must be an asbolute path.

  '/home': Home,
  '/networking': {
    '/github': GithubComponent,
    // redirect using string syntax
    '*': '/networking/github'
  // redirect using options object
  '*': {
    $$redirect: '/home'

The routes store

After the first schema setup, routes becomes readonly. The following reserved properties are added for each route:

  • $$pathname the exact path as in schema define
  • $$href full path including # at the beginning
  • $$stringify a function to generate string from params. Check out url-pattern stringify
  • $$pattern url-pattern object

Since they are non-enumarable, you can easily loop for just nested routes when needed.

<!-- Navigator.svelte -->
import { routes, active } from 'svelte-hash-router'

$: links = Object.values($routes['/books']['/comedy'])

{#each links as e}
    class:active={e === $active}
    > {e.$$name}

.active { color: blue; }

The store active is the current active route. If you want to check if a parent route has an active child route, use the store matches. It is an array including all the parents of the active route and itself.

import { matches } from 'svelte-hash-router'

<a class:active={$matches.includes(route)}></a>

A route containing params can be stringified.

<!-- schema: '/book/:id/:name' -->
<a href='{route.$$stringify({id: 123, name: `Dreams`})}'>

<!-- will give: '/book/123/Dreams' -->

Standard links to new pages should be preceded by a '#' symbol :

<a href='#/books'>