Persistence
State persistence is opt-in via the persist config. Omit it and you get an in-memory store that resets on reload.
Storage backends
Section titled “Storage backends”Four built-in backends:
persist: { storage: "local" } // localStoragepersist: { storage: "session" } // sessionStoragepersist: { storage: "memory" } // per-store Map - useful for SSR/testspersist: { storage: customImpl } // any KitStorage objectAll four implement the same interface. The custom option is how you’d plug in IndexedDB, AsyncStorage (React Native), or a remote store.
storage defaults to "local" in browsers and falls back to "memory" automatically when localStorage is undefined (Node, SSR). You don’t need to detect the environment yourself — see SSR below.
Fail-soft behaviour
Section titled “Fail-soft behaviour”Storage access can fail in surprising places: Safari private mode, sandboxed iframes, blocked third-party cookies, quota errors. store-kit treats these as soft failures - the store keeps working with in-memory state, never throws.
If you need to know about a failure, wrap your own writes around setState or use a custom storage backend that surfaces errors how you want.
Partializing
Section titled “Partializing”Sometimes only part of state should persist (e.g. UI prefs yes, in-flight upload progress no):
createStore({ name: "app", initial: { theme: "dark", sidebar: "open", uploadProgress: 0, // ephemeral activeUploads: [], // ephemeral }, persist: { storage: "local", version: 1, partialize: (s) => ({ theme: s.theme, sidebar: s.sidebar }), },});Custom serialization
Section titled “Custom serialization”By default, state is JSON-encoded. For Maps, Sets, BigInts, or Dates, provide custom serde:
persist: { storage: "local", version: 1, serialize: (v) => superjson.stringify(v), deserialize: (v) => superjson.parse(v),}In Node, localStorage and sessionStorage are undefined. store-kit automatically falls back to memory storage when run server-side, so creating a store at module scope doesn’t crash. Hydrate from real persisted state on the client when the component mounts.
Async storage
Section titled “Async storage”Async backends (getItem returning a promise) work for writes but not for synchronous initial hydration. The first render uses initial state; the persisted data hydrates on the next tick. If you need synchronous hydration, use a sync storage layer (e.g. localStorage cached from IndexedDB).