The Future of Web Dev
The Future of Web Dev
Data & Declarative Routing Library – svelte-router

svelte-router is a lightweight, accessible, high-performance Svelte routing library that implements React Router’s API pattern for building modern single-page applications with proper navigation and data loading.
Features
✅ Multiple Router Types: BrowserRouter, HashRouter, MemoryRouter, and StaticRouter for different deployment scenarios.
🔄 Data Loading Integration: Built-in loader and action functions with proper error handling and loading states.
🛠️ Nested Routing Support: Full support for nested routes and layout components with outlet rendering.
🎯 Progressive Enhancement: Functions correctly with or without JavaScript enabled in the browser.
How to Use It
1. Install the package in your project.
# Yarn
$ yarn add @hvniel/svelte-router
# NPM
$ npm install @hvniel/svelte-router
# PNPM
$ pnpm install @hvniel/svelte-router2. Data Routing:
This is the more modern approach, where you define your routes as a centralized JavaScript object. I’ve found this pattern scales very well for larger applications.
You create a router instance with createBrowserRouter and provide it to your app with the RouterProvider component.
<!-- App.svelte -->
<script>
import { createBrowserRouter, RouterProvider } from '@hvniel/svelte-router';
import Root from './routes/Root.svelte';
import Home from './routes/Home.svelte';
import User, { loader as userLoader } from './routes/User.svelte';
const router = createBrowserRouter([
{
path: "/",
Component: Root,
children: [
{ index: true, Component: Home },
{
path: "/users/:id",
Component: User,
// The loader function fetches data before the component renders
loader: userLoader,
},
],
},
]);
</script>
<RouterProvider {router} />Inside a component, you can access the data from a loader using the useLoaderData hook.
<!-- routes/User.svelte -->
<script module>
// This loader runs on the server or in the browser before navigation
export const loader = async ({ params }) => {
const response = await fetch(`/api/users/${params.id}`);
return response.json();
};
</script>
<script>
import { useLoaderData } from '@hvniel/svelte-router';
// The hook gives you the data returned from the loader
const user = useLoaderData();
</script>
<h1>User: {user.name}</h1>3. Declarative Routing:
If you prefer defining routes with components, similar to older versions of React Router, you can use the declarative approach.
<!-- App.svelte -->
<script>
import { BrowserRouter, Routes, Route } from '@hvniel/svelte-router';
import Home from './Home.svelte';
import About from './About.svelte';
</script>
<BrowserRouter>
<nav>
<a href="/">Home</a> | <a href="/about">About</a>
</nav>
<Routes>
<Route path="/" Component={Home} />
<Route path="/about" Component={About} />
</Routes>
</BrowserRouter>4. API Methods and Hooks
useRevalidator(): Returns a function to revalidate route data, triggering fresh loader executionuseNavigate(): Returns a function for programmatic navigation with options for replace, state, and relative navigationuseLocation(): Returns the current location object with pathname, search, hash, and state propertiesuseParams(): Returns the current route parameters as a reactive object with proper TypeScript inferenceuseSearchParams(): Returns URL search parameters with methods for reading and updating query stringsuseHref(to): Returns the href string for a given destination, useful for custom link componentsuseLoaderData<T>(): Returns data from the route loader with full type safety based on loader function return typeuseActionData<T>(): Returns data from the route action, typically used for form submission resultsuseRouteError(): Returns the current route error for error boundary implementationsuseNavigation(): Returns navigation state information including loading states and form submission statususeSubmit(): Returns a function to submit forms programmatically with full control over submission behavioruseFetcher(): Returns a fetcher for loading data without navigation, useful for background data updates
FAQs
Q: Can I use this library with SvelteKit?
A: No, and you shouldn’t try. SvelteKit provides its own powerful, file-based router that is deeply integrated with its lifecycle. This library is designed specifically for client-side SPAs built with Svelte, not SvelteKit.
Q: How do I implement protected routes for authentication?
A: The loader function is the perfect place for this. In your route definition, the loader can check for an authentication status (e.g., from a cookie or local storage). If the user is not authenticated, the loader can throw a redirect() to your login page. This pattern is standard in the React Router world and translates directly here.
Q: What is the main difference between using <Link> and the useNavigate() hook?
A: The <Link> component is for declarative navigation; you render it in your markup like a normal <a> tag for users to click. The useNavigate() hook gives you a function that you can call from your <script> logic to trigger navigation programmatically, such as after a successful form submission or another user event that doesn’t involve clicking a link.
Q: How do I handle authentication and route protection?
A: Route protection works through loader functions that can throw redirect responses or return authentication state. You can implement route guards by checking authentication status in parent route loaders and redirecting unauthenticated users to login pages. The error boundary system also supports displaying authentication-related error messages.
Q: Does this router support server-side rendering?
A: The library includes StaticRouter for server-side rendering scenarios, but it focuses on client-side routing. For comprehensive SSR support with file-based routing and server-side data loading, SvelteKit provides a more complete solution. This router works best for single-page applications that handle SSR through separate backend services.
Q: How do I implement lazy loading for route components?
A: Svelte’s dynamic import syntax works seamlessly with the router. You can use Component: () => import('./LazyComponent.svelte') in your route definitions for data routing mode, or implement lazy loading logic within your route components for declarative routing mode. The router handles loading states through the navigation hook.
Q: Can I use this router for mobile applications built with Capacitor?
A: Yes, the MemoryRouter and HashRouter modes work well in Capacitor environments where browser history might behave differently. The library’s history abstraction handles the differences between web and mobile web view contexts transparently.