{pageTitle('Settings')}

Settings

Appearance

Theme
{#each ['dark', 'light', 'system'] as opt (opt)} {/each}

System follows your device's light/dark preference.

Playback

{player.crossfadeSec === 0 ? 'Off' : `${player.crossfadeSec}s`}
setCrossfade(Number((e.currentTarget as HTMLInputElement).value))} aria-label="Crossfade duration in seconds" class="w-full accent-accent" />

Fades the end of one track into the start of the next. 0 = off · most albums sound best at 0.

ListenBrainz

{#if $status.isPending}

Loading…

{:else if $status.isError}

Couldn't load status.

{:else if $status.data}
{#if $status.data.last_scrobbled_at}

Last scrobbled: {new Date($status.data.last_scrobbled_at).toLocaleString()}

{/if}

Get a token at listenbrainz.org/profile. Tokens are stored unencrypted in this server's database — treat as sensitive.

{/if}

Recommendation metrics

How plays launched from each recommendation surface land, over the last {$metrics.data?.window_days ?? 30} days. Lower skip rate and higher average completion mean the surface is hitting.

{#if $metrics.isPending}

Loading…

{:else if $metrics.isError}

Couldn't load metrics.

{:else if $metrics.data && $metrics.data.sources.length > 0} {#each $metrics.data.sources as m (m.source)} {/each}
Surface Plays Skip rate Avg completion
{sourceLabel(m.source)} {m.plays} {(m.skip_rate * 100).toFixed(0)}% {(m.avg_completion * 100).toFixed(0)}%
{:else}

No recommendation plays yet. Play something from For You, Discover, or a mix.

{/if}

Profile

Your display name and recovery email.

Password

API Token

Used by Subsonic clients (DSub, Symfonium, etc.) to authenticate to your library. Regenerating invalidates clients that have the old token cached.

{#if apiToken} {apiToken} {/if}

Library