The $app/stores module contains store-based equivalents of the exports from $app/state.
If you’re using SvelteKit 2.12 or later, use $app/state instead. This module is deprecated and maintained for backward compatibility.
getStores
Returns all contextual stores.
Returns an object containing page, navigating, and updated stores.Returns: { page, navigating, updated }
On the server, this must be called during component initialization. Only use this if you need to defer store subscription until after the component has mounted.
<script>
import { getStores } from '$app/stores';
import { onMount } from 'svelte';
const { page, navigating } = getStores();
onMount(() => {
// Subscribe after mount
const unsubscribe = page.subscribe((value) => {
console.log('Page changed:', value);
});
return unsubscribe;
});
</script>
page
A readable store whose value contains page data.
Svelte readable store containing current page information.
Store Value Properties
The URL of the current page
The parameters extracted from the URL
Object with id property containing the route ID
The HTTP status code of the response
Combined data from all load functions
Data returned from form actions
State set via goto, pushState, or replaceState
Usage
<script>
import { page } from '$app/stores';
</script>
<p>Currently at {$page.url.pathname}</p>
{#if $page.error}
<span class="red">Error: {$page.error.message}</span>
{:else}
<span class="green">All good!</span>
{/if}
<pre>{JSON.stringify($page.data, null, 2)}</pre>
Reactive Statements
<script>
import { page } from '$app/stores';
$: pathname = $page.url.pathname;
$: slug = $page.params.slug;
$: console.log('Navigated to:', pathname);
</script>
<h1>Current path: {pathname}</h1>
{#if slug}
<p>Slug: {slug}</p>
{/if}
navigating
A readable store representing navigation state.
navigating
Readable<Navigation | null>
Svelte readable store that is null when not navigating, or a Navigation object during navigation.
Navigation Object Properties
Information about the page being navigated from
Information about the page being navigated to
Navigation type: 'enter', 'leave', 'link', 'goto', or 'popstate'
Whether the navigation will cause document unload
Number of history entries to traverse (only for 'popstate' type)
Promise that resolves when navigation completes
Usage
<script>
import { navigating } from '$app/stores';
</script>
{#if $navigating}
<div class="loading">
Navigating to {$navigating.to?.url.pathname}...
</div>
{/if}
Progress Indicator
<script>
import { navigating } from '$app/stores';
$: if ($navigating) {
console.log(`Navigation started: ${$navigating.from?.url} → ${$navigating.to?.url}`);
}
</script>
{#if $navigating}
<div class="progress-bar" />
{/if}
<style>
.progress-bar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, #4CAF50, #2196F3);
animation: slide 1s infinite;
}
@keyframes slide {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
</style>
updated
A readable store for detecting app updates.
updated
Readable<boolean> & { check(): Promise<boolean> }
Svelte readable store that’s initially false, becomes true when a new app version is detected.
Methods
Force an immediate version check. Returns Promise<boolean> indicating if an update is available.
Usage
<script>
import { updated } from '$app/stores';
</script>
{#if $updated}
<div class="toast">
<p>A new version of this app is available</p>
<button on:click={() => location.reload()}>Reload</button>
</div>
{/if}
Manual Check
<script>
import { updated } from '$app/stores';
async function checkForUpdates() {
const hasUpdate = await updated.check();
if (hasUpdate) {
if (confirm('New version available. Reload?')) {
location.reload();
}
} else {
alert('You are on the latest version');
}
}
</script>
<button on:click={checkForUpdates}>Check for updates</button>
Server vs Client Behavior
On the server, stores can only be subscribed to during component initialization. In the browser, they can be subscribed to at any time.
<script>
import { page } from '$app/stores';
import { onMount } from 'svelte';
// ✅ Safe: Subscribe during initialization
$: console.log('Current URL:', $page.url);
// ✅ Safe: Subscribe in onMount (browser only)
onMount(() => {
const unsubscribe = page.subscribe((value) => {
// Handle page changes
});
return unsubscribe;
});
</script>
Complete Example
<!--- file: +layout.svelte --->
<script>
import { page, navigating, updated } from '$app/stores';
// Reactive values
$: pathname = $page.url.pathname;
$: isLoading = $navigating !== null;
$: hasUpdate = $updated;
// Log navigation events
$: if ($navigating) {
console.log('Navigation started:', {
from: $navigating.from?.url.pathname,
to: $navigating.to?.url.pathname,
type: $navigating.type
});
}
</script>
<!-- Update notification -->
{#if hasUpdate}
<div class="update-toast">
<p>New version available</p>
<button on:click={() => location.reload()}>Reload</button>
</div>
{/if}
<!-- Loading indicator -->
{#if isLoading}
<div class="loading-bar" />
{/if}
<!-- Navigation -->
<nav>
<a href="/" class:active={pathname === '/'}>Home</a>
<a href="/about" class:active={pathname === '/about'}>About</a>
<a href="/contact" class:active={pathname === '/contact'}>Contact</a>
</nav>
<!-- Content -->
<main>
{#if $page.error}
<h1>Error {$page.status}</h1>
<p>{$page.error.message}</p>
{:else}
<slot />
{/if}
</main>
<!-- Footer with debug info -->
<footer>
<p>Route: {$page.route.id}</p>
<p>Status: {$page.status}</p>
</footer>
<style>
.active {
font-weight: bold;
color: #4CAF50;
}
.loading-bar {
position: fixed;
top: 0;
width: 100%;
height: 3px;
background: linear-gradient(90deg, #4CAF50, #2196F3);
animation: loading 1s ease-in-out infinite;
}
@keyframes loading {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
</style>
Migration to $app/state
If you’re using SvelteKit 2.12+, consider migrating to $app/state:
- import { page, navigating, updated } from '$app/stores';
+ import { page, navigating, updated } from '$app/state';
- $: pathname = $page.url.pathname;
+ const pathname = $derived(page.url.pathname);
- {#if $navigating}
+ {#if navigating}
Loading...
{/if}
- {#if $updated}
+ {#if updated.current}
New version available
{/if}