Skip to content

Storage showcase

Interactive examples for all supported storage drivers.

Storage showcase

Use this page to decide which storage driver fits your use case fastest.

Quick decision guide#

  • local → preferences that should survive reloads and browser restarts
  • session → per-tab UI state that should reset when the tab closes
  • cookie → values the server also needs during SSR
  • memory → temporary or fallback state with no browser persistence
  • indexeddb → larger client-side data like drafts, caches, or offline data

Good default: start with local unless you specifically need per-tab behavior, SSR-visible cookies, or larger stored data.

Theme preference

local

Keep UI choices across browser restarts. Perfect for theme, density, or dashboard preferences.

value "dark"

Temporary UI state

session

Store values only for the active tab, for example open sidebars or draft filters.

value true

Ephemeral state

memory

Best for environments without browser storage or when you only need a reactive in-memory fallback.

value 1

Larger client data

indexeddb

IndexedDB hydrates asynchronously and fits bigger client-side payloads like drafts, cached lists, or offline data.

value "draft-a"

Shared key sync

memory

Two controllers with the same storage/key pair share a single reactive state.

value {
  "first": 0,
  "second": 0
}

Copy-paste examples#

Theme preference with localStorage#

const theme = persistedSignal("theme", "dark", { storage: "local" });

Best for:

  • theme
  • layout preferences
  • dismissed banners

Tab-scoped UI state with sessionStorage#

const sidebarOpen = persistedSignal("sidebar-open", true, { storage: "session" });

Best for:

  • open/closed UI state
  • temporary per-tab filters
  • wizard progress that should reset with the tab

Larger client-side data with IndexedDB#

const drafts = persistedSignal("drafts", [], {
  storage: "indexeddb",
  indexedDB: { database: "app-cache", store: "drafts" },
});

Keep in mind:

  • IndexedDB hydrates asynchronously
  • the signal starts with initialValue
  • stored data is applied after loading completes

SSR-visible values with cookies#

const locale = persistedSignal("locale", "de", {
  storage: "cookie",
  cookie: { path: "/", sameSite: "Lax" },
});

Use this when:

  • the server needs the value during SSR
  • middleware or templates should see the same value

If SSR does not need the value, prefer local or session.

Ephemeral state with memory#

const draftStep = persistedSignal("draft-step", 1, { storage: "memory" });

Best for:

  • fallback behavior
  • non-persistent reactive state
  • temporary state in non-browser environments

Common gotchas#

  • persistedSignal() is global by identity, so reuse the same key with the same effective options.
  • For SSR cookie usage, different cookieContext values stay isolated.
  • IndexedDB is the only built-in storage here with async hydration behavior.