# Defining routes
## Basic route definitions
Each route is a normal Svelte component. The route definition is a JavaScript dictionary (object) where the key is the path and the value is the component.
```js
import Home from './routes/Home.svelte'
import Author from './routes/Author.svelte'
import Book from './routes/Book.svelte'
import NotFound from './routes/NotFound.svelte'
const routes = {
// Exact path
'/': Home,
// Using named parameters, with last being optional
'/author/:first/:last?': Author,
// Wildcard parameter
'/book/*': Book,
// Catch-all (must be last)
'*': NotFound,
}
```
## defineRoutes() — type-safe routes (recommended)
Use `defineRoutes()` for a single source of truth that gives you IDE autocomplete on route names and parameters, preventing typos at compile time:
```javascript
// src/routes.js (or routes.ts for TypeScript)
import { defineRoutes } from '@keenmate/svelte-spa-router/routes'
import Home from './routes/Home.svelte'
const { routes, nav, paths } = defineRoutes({
home: {
path: '/',
component: Home
},
about: {
path: '/about',
component: () => import('./routes/About.svelte')
},
user: {
path: '/user/:id',
component: () => import('./routes/User.svelte'),
conditions: [checkAuth],
breadcrumbs: [{ label: 'Users' }, { id: 'user', label: 'User' }]
},
settings: {
path: '/settings',
component: () => import('./routes/Settings.svelte'),
permissions: { any: ['settings.read'] }
}
})
export { routes, nav, paths }
```
**Use in App.svelte:**
```svelte
User 123
About
User 99
```
**What `defineRoutes()` returns:**
| Property | Description |
|----------|-------------|
| `routes` | Standard routes object for `` |
| `nav.X.push(params?, query?, ctx?)` | Navigate to route X (calls `push()` internally) |
| `nav.X.replace(params?, query?, ctx?)` | Replace with route X (calls `replace()` internally) |
| `nav.X.link(params?, query?)` | Returns object for `use:link` action |
| `nav.X.path` | Raw path pattern (e.g. `'/user/:id'`) |
| `paths.X(params?, query?)` | Build URL string for `href` attributes |
**TypeScript support:**
In TypeScript, `defineRoutes()` extracts `:param` names from path patterns at the type level:
```typescript
const { nav, paths } = defineRoutes({
user: { path: '/user/:id', component: UserPage }
})
nav.user.push({ id: 123 }) // ✅ TypeScript knows 'id' is required
nav.user.push({ userId: 123 }) // ❌ Type error — 'userId' doesn't exist
nav.user.push() // ✅ OK — params are optional at runtime
paths.user({ id: 123 }) // ✅ Returns '/user/123'
```
**Supported route options:**
Each route in `defineRoutes()` accepts `path`, `component`, and all existing `createRoute()` / `wrap()` options: `loadingComponent`, `loadingParams`, `conditions`, `props`, `routeContext`, `title`, `breadcrumbs`, `shouldDisplayLoadingOnRouteLoad`, `permissions`, `authorizationCallback`, and inheritance flags (`inheritBreadcrumbs`, `inheritPermissions`, etc.).
> **Note:** `defineRoutes()` automatically calls `registerRoutes()` internally — no separate registration step is needed. Named routes work immediately with `push()`, `replace()`, and `buildUrl()`.
## Include the router
In your main component (usually `App.svelte`):
```svelte
```
## Dynamic imports and code-splitting
### Using createRoute() (recommended)
The most convenient way to create routes with async loading, metadata, and conditions:
```js
import { createRoute } from '@keenmate/svelte-spa-router/wrap'
import Home from './routes/Home.svelte'
import NotFound from './routes/NotFound.svelte'
const routes = {
'/': Home,
// No wrap() needed! createRoute() handles it for you
'/author/:first/:last?': createRoute({
component: () => import('./routes/Author.svelte'),
title: 'Author Profile',
breadcrumbs: [
{ label: 'Home', path: '/' },
{ label: 'Authors' }
]
}),
// With loading component
'/book/*': createRoute({
component: () => import('./routes/Book.svelte'),
title: 'Book Details',
loadingComponent: LoadingPlaceholder,
loadingParams: { message: 'Loading book...' }
}),
'*': NotFound,
}
```
### Using wrap() directly (advanced)
For more control, use `wrap()` directly or with `createRouteDefinition()`:
```js
import { wrap, createRouteDefinition } from '@keenmate/svelte-spa-router/wrap'
import Home from './routes/Home.svelte'
import NotFound from './routes/NotFound.svelte'
const routes = {
'/': Home,
// Direct wrap() syntax
'/author/:first/:last?': wrap({
asyncComponent: () => import('./routes/Author.svelte')
}),
// Using createRouteDefinition() for consistency
'/book/*': wrap(createRouteDefinition({
component: () => import('./routes/Book.svelte'),
loadingComponent: LoadingPlaceholder,
loadingParams: { message: 'Loading book...' }
})),
'*': NotFound,
}
```
### Metadata access
Title and breadcrumbs are stored in `userData` and accessible in route events:
```svelte
{title || 'Default Title'}
{#if breadcrumbs.length > 0}
{/if}
```