The user-visible URL is {page.shallow?.url.href ?? page.url.href}
The actual page you're on is {page.url.href}
``` A regular `goto` call without `shallow: true`, or a standard link click, exits shallow routing. > [!LEGACY] > In SvelteKit 2 this functionality was achieved using `pushState` and `replaceState`, which are now deprecated. Use `goto` with `shallow: true` instead, and use the `replace` option when replacing the current history entry. ## Routing options By default, the above examples create a new navigation entry in the history stack. If you don't want that, you can replace the existing navigation entry instead: ```js import { goto } from '$app/navigation'; const url = new URL('https://example.com'); const state = { showModal: true }; // ---cut--- goto(url, { state, replace: true }); ``` By default, state set with `goto` is not restored after a reload. To change that, use `persistState`: ```js import { goto } from '$app/navigation'; const url = new URL('https://example.com'); const state = { showModal: true }; // ---cut--- goto(url, { state, persistState: true }); ``` Shallow navigations preserve the current scroll position and focused element by default. You can opt out of either behavior with `noScroll: false` or `keepFocus: false`: ```js import { goto } from '$app/navigation'; const url = new URL('https://example.com'); // ---cut--- goto(url, { shallow: true, noScroll: false, keepFocus: false }); ``` > [!NOTE] > `page.state` is only populated after JavaScript loads, which can cause flickering UI. Use it carefully. ## Loading data for a route When shallow routing, you may want to render another `+page.svelte` inside the current page. For example, clicking on a photo thumbnail could pop up the detail view without navigating to the photo page. For this to work, you need to load the data that the `+page.svelte` expects. A convenient way to do this is to use [`preloadData`]($app-navigation#preloadData) inside the `click` handler of an `` element. If the element (or a parent) uses [`data-sveltekit-preload-data`](link-options#data-sveltekit-preload-data), the data will have already been requested, and `preloadData` will reuse that request. ```svelte {#each data.thumbnails as thumbnail} { if (innerWidth < 640 // bail if the screen is too small || e.shiftKey // or the link is opened in a new window || e.metaKey || e.ctrlKey // or a new tab (mac: metaKey, win/linux: ctrlKey) // should also consider clicking with a mouse scroll wheel ) return; // prevent navigation e.preventDefault(); const { href } = e.currentTarget; // run `load` functions (or rather, get the result of the `load` functions // that are already running because of `data-sveltekit-preload-data`) const result = await preloadData(href); if (result.type === 'loaded' && result.status === 200) { goto(href, { shallow: true, state: { selected: result.data } }); } else { // something bad happened! try navigating goto(href); } }} >