sapper, svelte-routing, and svelte-spa-router represent three distinct approaches to navigation within the Svelte ecosystem. sapper is a full-stack application framework (the predecessor to SvelteKit) that provides server-side rendering (SSR), code splitting, and file-based routing out of the box. svelte-routing is a component-based router designed to work seamlessly with SSR, allowing route definitions to exist directly within your component tree. svelte-spa-router is a lightweight, code-first router optimized specifically for Single Page Applications (SPAs) where server-side rendering is not required, offering a familiar React-like API for defining routes.
When navigating the Svelte ecosystem, choosing the right routing solution depends entirely on whether you need server-side rendering (SSR) and how much framework structure you want. sapper, svelte-routing, and svelte-spa-router solve the same problem — moving users between views — but they do it in fundamentally different ways. Let's break down their architectures, trade-offs, and code patterns.
sapper was a full-stack framework. It didn't just handle routing; it managed your server, your build process, and your deployment. Routing was tied directly to your file system.
routes folder, and sapper automatically turned them into URLs.// sapper: File-based routing structure
// routes/about.svelte
<script>
export let segment;
</script>
<h1>About Page</h1>
svelte-routing is a library designed to work with SSR. It treats routes as regular Svelte components.
<Route> components inside your main layout.// svelte-routing: Component-based definition
<script>
import { Router, Route } from 'svelte-routing';
import Home from './Home.svelte';
import About from './About.svelte';
</script>
<Router>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
</Router>
svelte-spa-router is a lightweight library built strictly for Single Page Applications.
// svelte-spa-router: Code-based configuration
<script>
import Router from 'svelte-spa-router';
import Home from './Home.svelte';
import About from './About.svelte';
const routes = {
'/': Home,
'/about': About
};
</script>
<Router {routes} />
How you move between pages differs slightly in syntax, though the user experience is similar.
sapper uses a special <a> tag replacement.
sapper's anchor component to enable client-side navigation without page reloads.// sapper: Specialized anchor component
<script>
import { a } from 'sapper/app';
</script>
<a href="/about">Go to About</a>
svelte-routing provides a <Link> component.
active class prop to style links when their route is matched.// svelte-routing: Link component
<script>
import { Link } from 'svelte-routing';
</script>
<Link to="/about" let:active>{active ? <b>About</b> : "About"}</Link>
svelte-spa-router also uses a <Link> component.
// svelte-spa-router: Link with props
<script>
import { Link } from 'svelte-spa-router';
</script>
<Link to="/user/123" params={{ id: 123 }}>View User</Link>
Extracting data from the URL (like /user/5) is a common requirement. Each package handles this differently.
sapper exposes params via export let based on the filename.
[id].svelte, the variable id is automatically available.// sapper: Dynamic file naming [id].svelte
<script>
export let id; // Automatically populated from URL
</script>
<h1>User {id}</h1>
svelte-routing passes params as props to the component.
path string (e.g., /user/:id).id as a standard exported prop.// svelte-routing: Path parameters
<!-- Route definition -->
<Route path="/user/:id" component={User} />
<!-- User.svelte -->
<script>
export let id;
</script>
<h1>User {id}</h1>
svelte-spa-router passes params via a params prop.
/user/:id).params object containing all dynamic values.// svelte-spa-router: Params object
<!-- Route definition -->
const routes = { '/user/:id': User };
<!-- User.svelte -->
<script>
export let params;
</script>
<h1>User {params.id}</h1>
It is vital to understand that sapper is no longer maintained. The Svelte team officially transitioned to SvelteKit, which offers the same file-based routing and SSR capabilities but with a modern architecture, faster builds, and active support.
If you are starting a new project today:
sapper.svelte-routing if you need SSR in a custom setup without SvelteKit.svelte-spa-router for simple client-side dashboards.// DO NOT START NEW PROJECTS WITH THIS
import { a } from 'sapper/app';
// INSTEAD, USE SVELTEKIT FOR FULL STACK
// routes/about/+page.svelte (SvelteKit)
You need excellent SEO, fast initial loads, and content fetched from a CMS.
sapper)svelte-spa-router won't work because search engines can't execute JS to see content. svelte-routing works, but SvelteKit provides the build tools you need out of the box.Your app is behind a login screen. SEO doesn't matter. You just want it to feel snappy.
svelte-spa-router// Dashboard setup with svelte-spa-router
const routes = {
'/': DashboardHome,
'/settings': Settings,
'/users/*': Users // Catch-all for nested user routes
};
You are embedding Svelte into an existing Node.js or PHP application and need specific control over the HTML shell.
svelte-routingsapper (or SvelteKit) demands.| Feature | sapper | svelte-routing | svelte-spa-router |
|---|---|---|---|
| Type | Full-Stack Framework | SSR-Compatible Library | SPA-Only Library |
| Routing Style | File-system based | Component-based (<Route>) | Code-based (Object/Map) |
| SSR Support | ✅ Yes (Built-in) | ✅ Yes | ❌ No |
| Status | ⚠️ Deprecated | ✅ Maintained | ✅ Maintained |
| Learning Curve | High (Framework concepts) | Medium (Component logic) | Low (Simple config) |
| Best For | Legacy apps (Migrate to SvelteKit) | Custom SSR setups | Dashboards & SPAs |
The choice here is less about "which is best" and more about "what architecture do I need?"
svelte-spa-router. If you can, use SvelteKit. If you have a strict constraint preventing SvelteKit, use svelte-routing.svelte-spa-router is often the fastest way to get up and running. It removes the boilerplate of SSR you don't need.sapper in a tutorial: Remember that it is outdated. Any new project requiring its features should use SvelteKit instead.By matching the tool to your rendering needs (SSR vs. SPA), you avoid unnecessary complexity and ensure your application is built on a supported foundation.
Choose sapper only if you are maintaining a legacy codebase built before SvelteKit became stable. It is officially deprecated and should not be used for new projects. If you need full-stack capabilities like SSR and API routes today, migrate to SvelteKit, which supersedes sapper with better performance and modern features.
Choose svelte-routing if you are building a Svelte application that requires Server-Side Rendering (SSR) but you are not using the SvelteKit framework. It is the ideal choice when your routing logic needs to be rendered on the server to ensure SEO friendliness and fast initial loads without the opinionated structure of a full meta-framework.
Choose svelte-spa-router if you are building a pure Client-Side Application (SPA) where SEO and server rendering are not concerns. It is perfect for dashboards, internal tools, or prototypes where you want a simple, code-based routing configuration similar to react-router without the overhead of SSR compatibility.
The next small thing in web development, powered by Svelte.
Sapper is a framework for building high-performance universal web apps. Read the guide or the introductory blog post to learn more.
Sapper's successor, SvelteKit, is currently available for use. Please see the FAQ for more details.
Clone the starter project template with degit... When cloning you have to choose between rollup or webpack:
npx degit "sveltejs/sapper-template#rollup" my-app
# or: npx degit "sveltejs/sapper-template#webpack" my-app
...then install dependencies and start the dev server...
cd my-app
npm install
npm run dev
...and navigate to localhost:3000. To build and run in production mode:
npm run build
npm start
Pull requests are encouraged and always welcome. Pick an issue and help us out!
To install and work on Sapper locally:
git clone https://github.com/sveltejs/sapper.git
cd sapper
npm install
npm run dev
You can make changes locally to Sapper and test it against a local Sapper project. For a quick project that takes almost no setup, use the default sapper-template project. Instruction on setup are found in that project repository.
To link Sapper to your project, from the root of your local Sapper git checkout:
cd sapper
npm link
Then, to link from sapper-template (or any other given project):
cd sapper-template
npm link sapper
You should be good to test changes locally.
npm run test