1# client-side navigation 2 3## preserving player state across navigation 4 5the player lives in the root layout (`+layout.svelte`) and persists across all page navigations. to maintain uninterrupted playback, client-side navigation must work correctly. 6 7## critical rule: never use `stopPropagation()` on links 8 9**problem**: calling `e.stopPropagation()` on link click handlers breaks SvelteKit's client-side router, causing full page reloads that unmount and remount the player. 10 11```svelte 12<!-- ❌ WRONG - causes full page reload, interrupts playback --> 13<a href="/tag/{tag}" onclick={(e) => e.stopPropagation()}>{tag}</a> 14``` 15 16```svelte 17<!-- ✅ CORRECT - client-side navigation works, playback continues --> 18<a href="/tag/{tag}">{tag}</a> 19``` 20 21## handling links inside clickable containers 22 23when you have links nested inside a clickable button/div, check the event target instead of using `stopPropagation()`: 24 25```svelte 26<button 27 onclick={(e) => { 28 // skip if user clicked a link inside 29 if (e.target instanceof HTMLAnchorElement || (e.target as HTMLElement).closest('a')) { 30 return; 31 } 32 doSomething(); 33 }} 34> 35 <span>click me</span> 36 <a href="/other-page">or click this link</a> 37</button> 38``` 39 40this pattern: 411. lets the link trigger proper client-side navigation 422. only calls `doSomething()` when clicking non-link elements 433. preserves all global state including the player 44 45## why this matters 46 47SvelteKit's client-side router intercepts `<a>` tag clicks to: 48- avoid full page reload 49- preserve global state (player, queue, auth) 50- enable smooth transitions 51 52when `stopPropagation()` is called, the click event never reaches SvelteKit's router, falling back to native browser navigation which: 53- performs a full page reload 54- unmounts and remounts all components 55- resets audio playback 56 57## examples from the codebase 58 59### TrackItem.svelte 60 61the track container is a button that plays the track on click. it contains multiple links (artist, album, tags) that should navigate without affecting playback: 62 63```svelte 64<button 65 class="track" 66 onclick={(e) => { 67 // only play if clicking the track itself, not a link inside 68 if (e.target instanceof HTMLAnchorElement || (e.target as HTMLElement).closest('a')) { 69 return; 70 } 71 onPlay(track); 72 }} 73> 74 <a href="/u/{track.artist_handle}" class="artist-link">{track.artist}</a> 75 <a href="/tag/{tag}" class="tag-badge">{tag}</a> 76</button> 77``` 78 79## debugging navigation issues 80 81**symptom**: clicking a link stops music playback 82 83**diagnosis**: 841. check if the link has `onclick={(e) => e.stopPropagation()}` 852. check parent elements for event handling that might interfere 863. verify the route uses SvelteKit conventions (`+page.svelte`, `+page.ts`) 87 88**fix**: remove `stopPropagation()` and use event target checking in parent handlers instead