npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

svelte-spa-history-router

v3.0.1

Published

History base router for Svelte SPA

Readme

svelte-spa-history-router

A history-based router for Svelte Single Page Applications (SPAs).

[!TIP] Svelte's official routing library is SvelteKit. This library is designed for small or simple projects.

Features

  • History-Based Routing
  • Path matching and Variable Capture using regular expressions
  • Resolver for dynamic routing, code splitting, data preloading, etc.

Features not supported

  • Hash-based Routing
  • Nested router
  • Server-Side Rendering (SSR)

Install

$ npm install --save-dev svelte-spa-history-router
$ # or
$ yarn add svelte-spa-history-router

Usage

Import Router and include it in your main component (typically App.svelte).

For example:

# App.svelte

<script>
  import { Router } from 'svelte-spa-history-router';

  import Home from './Home.svelte';
  import Article from './Article.svelte';
  import NotFound from './NotFound.svelte';

  const routes = [
    { path: '/', component: Home},
    { path: '/posts/(?<postId>.*)', component: Article},
    { path: '.*', component: NotFound},
  ];
</script>
<Router {routes}/>
  • Router requires the routes parameter.

  • routes is a list of route objects. Each route object must have a path property, and either a component or resolver property.

    • path can be a regular expression. ^ and $ are automatically added when matching.
    • component is a Svelte component. There are no specific requirements for the component.
    • resolver is a function to return a dynamic component and return props of the type expected by the component.
  • Matching is simply performed in the order defined by routes.

Path variable

For routes that do not use a resolver, matched parameters are passed to the component via the params prop.

For example:

# App.svelte
<script>
  import { Router } from "svelte-spa-history-router";
  import ItemPage from "./ItemPage.svelte";

  const routes = [
    { path: "/items/(?<itemId>\\d+)", component: ItemPage },
  ];
</script>
<Router {routes}/>
# ItemPage.svelte

<script lang="ts">
  let { params }: { params: { itemId: string } } = $props();

  const itemId = $derived(parseInt(params.itemId));
</script>
<div>
  { itemId }
</div>

Navigation methods

To navigate to another page, link and push are available.

  • link turns an <a> tag into a spa navigation link. For example:
<script>
  import { link } from 'svelte-spa-history-router';
</script>

<a use:link href="/">Home</a>
  • push navigates to the given path programatically.
<script>
  import { push } from 'svelte-spa-history-router';
<script>

<button onclick={ () => push('/') }>Go to Home</button>

resolver

A resolver is a mechanism for dynamically determining which component to render. It can be used for various purposes, such as:

Example: code splitting (dynamic import)

<script>
  import { Router } from 'svelte-spa-history-router';

  const routes = [
    { path: '/', resolver: () => import("Home.svelte") },
  ];
</script>
<Router {routes}/>

Example: dynamic routing and pass value to component props.

<script lang="ts">
  import { Router } from 'svelte-spa-history-router';

  import Article from "./Article.svelte";
  import NotFound from "./NotFound.svelte";

  async function prefetchArticle(params: Record<string, string>) {
    const article = await getArticle(params.postId);
    if (article) {
      return { component: Article, props: { article } };
    } else {
      return NotFound;
    }
  }

  const routes = [
    { path: '/posts/(?<postId>.*)', resolver: prefetchArticle },
  ];
</script>
<Router {routes}/>

[!TIP] This routing mechanism allows preloading data before rendering the component, minimizing layout flicker and improving perceived performance. While skeleton screens are a common modern pattern, this approach can simplify state handling in simple apps.

Example: guard

<script lang="ts">
  import { Router, redirect } from 'svelte-spa-history-router';

  import Admin from "./Admin.svelte";


  let user: User = $state()

  function adminGuard() {
    if (!isAdmin(user)) {
      return redirect("/");
    }
    return Admin;
  }

  const routes = [
    { path: '/', component: Home },
    { path: '/admin', resolver: adminGuard },
  ];
</script>
<Router {routes}/>

A resolver must return one of the following types:

| Component
| { component: Component, props: ComponentProps }
| Redirection // return value of `redirect()`
| Promise<
   | Component
   | { component: Component, props: ComponentProps }
   | Redirection
   | { default: Component } // return value of `import()`
  >

(Added in v2.0.0)

(Changed resolver interface in v3.0.0-next.1)

currentURL()

state to detect URL changes (including query string or hash)

<script>
  import { currentURL } from "svelte-spa-history-router";

  let name = $derived(currentURL().searchParams.get("name") ?? "unknown");
</script>
<div>{ name }</div>

(Added in v2.1.0)

(Replaced with Svelte5's $state() in v3.0.0-next.1)

Typing

svelte-spa-history-router provides Route type to check combination of component and props.

<script lang="ts">
  import type { Route } from "svelte-spa-history-router"

  // BlogPost requires article property
  import type BlogPost from "./pages/BlogPost.svelte"

  import Top from "./pages/Top.svelte"

  const routes: [
    Route<typeof Top>,
    Route<typeof BlogPost | typeof NotFound>,
  ] = [
    { path: "/", component: Top },
    {
      path: "/blog/posts/(?<slug>.*)",
      resolver: async (params: Record<"slug", string>) => {
        const article = await getArticle(params.slug);
        if (article) {
          const component = (await import("./pages/BlogPost.svelte")).default;
          return { component, props: { article } }
        } else {
          return NotFound;
        }
      },
    },
  ];
</script>

(Added in v3.0.0-next.1)

Full example:

example

ChangeLog

ChangeLog

License

MIT License.

Appendix

A history-based router generally requires server-side routing to support direct links or page reloads.

For example, the following nginx configuration allows proper routing:

location / {
    try_files $uri /index.html =404;
}

If you are considering using firebase hosting for your application, rewrite may be useful.

Inspired

svelte-spa-history-router is inspired by svelte-spa-router and Svelte Router SPA.

If you don't need support for both history-based routing and regular expressions, I recommend these powerful routers.