Skip to content

Instantly share code, notes, and snippets.

@asevos
Created November 6, 2025 14:45
Show Gist options
  • Select an option

  • Save asevos/257b7fffa3900d248ef309189e97af53 to your computer and use it in GitHub Desktop.

Select an option

Save asevos/257b7fffa3900d248ef309189e97af53 to your computer and use it in GitHub Desktop.
An attempt to implement persistent store using localStorage in SvelteKit
import { browser } from '$app/environment'
export type PersistentStore<T> = ReturnType<typeof newPersistentStore<T>>
export function newPersistentStore<T>(key: string, initial: T) {
let value = $state<T>(initial)
let mounted = $state(false)
const storeName = `Persistent store '${key}'`
function mount() {
if (!browser) throw `${storeName} mounted outside of browser`
if (mounted) {
console.warn(`Repeated attempt to mount ${storeName}`)
return
}
const item = localStorage.getItem(key)
if (item) value = JSON.parse(item)
mounted = true
window.addEventListener('storage', (e: StorageEvent) => {
if (e.storageArea !== localStorage || e.key != key) return
const newValue = localStorage.getItem(key)
if (newValue === null) {
value = initial
} else {
value = JSON.parse(newValue)
}
})
$effect(() => {
if (!browser) throw `${storeName} updated outside of browser`
if (!mounted) throw `${storeName}: attempt to update value before mount`
localStorage.setItem(key, JSON.stringify(value))
})
console.log(`${storeName} init finished`)
}
function set(newValue: T) {
if (!mounted) throw `${storeName}: attempt to set value before mount`
value = newValue
}
function get(): T {
if (!mounted) throw `${storeName}: attempt to get value before mount`
return value
}
return {
value: get,
set,
mounted: () => mounted,
mount,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment