Description: AlpineJS's $persist magic
property allows you to easily make component data persistent across
browser sessions. It leverages the browser's
localStorage to remember user choices or component
states, significantly improving the user experience by retaining
settings like theme preferences, toggle states (e.g., sidebar
visibility), or form inputs even after the user closes the tab or
browser.
$persist(defaultValue)
This is an AlpineJS "magic property" that you assign to a data property within your component. It works as follows:
localStorage for a previously saved value
associated with this property.
localStorage (e.g., first
visit), the defaultValue you provide is used.
localStorage. Alpine handles serializing
objects/arrays to JSON strings.
Example usage within an Alpine component's data:
// In Alpine.data('myComponent', () => ({ ... }))
// 'darkMode' will be true/false, defaulting to false.
darkMode: this.$persist(false)
.as('storageKey')
This is a method chained onto $persist() to specify
a custom key name under which the data will be stored in
localStorage. While Alpine can generate a key
automatically, using .as() is highly recommended
for several reasons:
localStorage when debugging.
Example usage:
// 'sidebarOpen' state will be stored under the key 'myApp_sidebar_visibility'
sidebarOpen: this.$persist(true).as('myApp_sidebar_visibility')
localStorage
This is a standard Web Storage API provided by browsers. It
allows web applications to store key/value pairs locally within
the user's browser. Key characteristics relevant to
$persist:
localStorage persists even after the browser
window is closed and reopened.
localStorage can only store string values.
Alpine's $persist conveniently handles the
serialization (converting JavaScript
objects/arrays/booleans/numbers to JSON strings) and
deserialization (parsing JSON strings back to their original
JavaScript types) for you.
localStorage is
specific to the domain (protocol, host, and port). Data stored
by one domain cannot be accessed by another.
$persist is best for small pieces of UI state,
not large datasets.
Values from localStorage are strings;
$persist handles JSON
serialization/deserialization:
While localStorage itself only stores strings,
Alpine's $persist intelligently handles this. If
you persist an object (like
{ theme: 'dark', fontSize: 16 }) or an array,
$persist will automatically convert it to a JSON
string (e.g., '{"theme":"dark","fontSize":16}')
before saving to localStorage, and parse it back
into a JavaScript object/array when loading. This is a major
convenience, but it's good to be aware of what's happening under
the hood. If you are mixing $persist with manual
localStorage.getItem()/setItem()
calls, you'd need to handle JSON stringification/parsing
yourself for complex types.
Ensure storage keys used with
.as('storageKey') are unique to avoid
clashes:
This is crucial. If two different Alpine components (or even
different parts of your application, or another application on
the same domain) use the same localStorage key via
.as(), they will overwrite each other's data. This
can lead to very hard-to-debug issues. Adopt a consistent naming
convention for your keys, perhaps including an app prefix,
component name, and version, e.g.,
.as('myPythonWebApp_userPrefs_sidebarState_v1').
The example must instruct users to refresh the page to see
persistence in action:
Persistence means the state is remembered across page loads or
browser sessions. To truly observe
$persist working, you'll need to change a value,
then refresh the page (or close and reopen the tab). The value
should remain as you set it, not revert to its initial default.
The working example below will guide you through this.
This example demonstrates a persistent sidebar toggle.
This sidebar's visibility state is persisted in localStorage
using $persist().
Current state (sidebarOpen):
How to Test Persistence:
$persist().
'myApp_sidebar_state'
and its value.